Socket
Socket
Sign inDemoInstall

generouted

Package Overview
Dependencies
182
Maintainers
1
Versions
106
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    generouted

Generated client-side file-based routes for Vite


Version published
Weekly downloads
14K
decreased by-8.09%
Maintainers
1
Install size
36.6 kB
Created
Weekly downloads
ย 

Readme

Source

generouted


Generouted

Generated file-based routes for Vite

Motivation

I enjoyed using file-based routing since I tried Next.js (pages directory). After applying the same concept with Vite and client-side applications, I started writing blog posts covering the implementation of client-side file-based routing with React Router which was packaged later as generouted.

Today generouted brings many features, supports multiple frameworks and routers, and inspires ideas and conventions from Next.js, Remix, Expo, Docusaurus, SvelteKit and more.


How does it work?

generouted uses Vite's glob import API to list the routes within the src/pages directory and generates the routes tree and modals based on generouted's conventions.

There are also Vite plugins available for some integrations to provide type-safe components/hooks/utils through code-generation.



Features

  • ๐Ÿ“ Client-side file-based routing
  • โšก Powered by Vite
  • โœจ React support with react-router-dom or @tanstack/router ๐Ÿงช or @tanstack/react-location ๐Ÿšจ
  • โœจ Solid support with @solidjs/router
  • โœจ File-based MDX routes with React or Solid, requires @mdx-js/rollup installation and setup
  • ๐Ÿ” Type-safe navigation
  • ๐Ÿš€ Type-safe global modals
  • ๐Ÿ’ค Route-based code-splitting and lazy-loading
  • ๐Ÿ“„ Route-based data loaders and actions
  • ๐Ÿ’ฃ Route-based error boundary
  • ๐Ÿ“‚ Nested layouts
  • ๐Ÿซ™ Pathless layout groups
  • โ“ Optional static and dynamic routes
  • ๐Ÿ’ญ Ignored routes per file or directory

Online explorer

  • โšก Visit generouted's interactive playground via StackBlitz
  • ๐Ÿงฉ Explore file-based routing patterns and conventions
  • ๐Ÿ”Ž Visualize the routes layouts and the resolved routes paths
  • ๐Ÿ“ Update src/pages/ files and see your changes reflecting

Getting started

React Router

React Router

In case you don't have a Vite project with React and TypeScript, check Vite documentation to start a new project.

Installation
pnpm add @generouted/react-router react-router-dom
Setup
// vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import generouted from '@generouted/react-router/plugin'

export default defineConfig({ plugins: [react(), generouted()] })
Usage
// src/main.tsx

import { createRoot } from 'react-dom/client'
import { Routes } from '@generouted/react-router'

createRoot(document.getElementById('root')!).render(<Routes />)
Adding pages

Add the home page by creating a new file src/pages/index.tsx โ†’ /, then export a default component:

export default function Home() {
  return <h1>Home</h1>
}

Check the routing conventions section below.

Docs

You can find more details about type-safe navigation and global modals at @generouted/react-router docs.

Examples

Solid Router

Solid Router

In case you don't have a Vite project with Solid and TypeScript, check Vite documentation to start a new project.

Installation
pnpm add @generouted/solid-router @solidjs/router
Setup
// vite.config.ts

import { defineConfig } from 'vite'
import solid from 'vite-plugin-solid'
import generouted from '@generouted/solid-router/plugin'

export default defineConfig({ plugins: [solid(), generouted()] })
Usage
// src/main.tsx

import { render } from 'solid-js/web'
import { Routes } from '@generouted/solid-router'

render(Routes, document.getElementById('root')!)
Adding pages

Add the home page by creating a new file src/pages/index.tsx โ†’ /, then export a default component:

export default function Home() {
  return <h1>Home</h1>
}

See more about generouted routing conventions below.

Docs

You can find more details about type-safe navigation and global modals at @generouted/solid-router docs.

Examples

TanStack React Router โ€” In-progress experimental support ๐Ÿงช

TanStack React Router โ€” In-progress experimental support ๐Ÿงช

Check out the docs here

Examples

React Location โ€” Deprecated ๐Ÿšจ

React Location โ€” Deprecated ๐Ÿšจ

In case you don't have a Vite project with React and TypeScript, check Vite documentation to start a new project.

Installation
pnpm add generouted @tanstack/react-location
Usage
// src/main.tsx

import { createRoot } from 'react-dom/client'
import { Routes } from 'generouted/react-location'

createRoot(document.getElementById('root')!).render(<Routes />)
Adding pages

Add the home page by creating a new file src/pages/index.tsx โ†’ /, then export a default component:

export default function Home() {
  return <h1>Home</h1>
}
Examples


Conventions

File and directories naming and conventions

  • Routes declaration at src/pages
  • Supports .tsx, .jsx and .mdx file extensions
  • Optional src/pages/_app.tsx for an app level layout
  • Optional src/pages/404.tsx for a custom not-found page
Index routes
  • src/pages/index.tsx โ†’ /
  • src/pages/posts/index.tsx โ†’ /posts
Nested routes
  • src/pages/posts/2022/index.tsx โ†’ /posts/2022
  • src/pages/posts/2022/resolutions.tsx โ†’ /posts/2022/resolutions
Dynamic routes
  • src/pages/posts/[slug].tsx โ†’ /posts/:slug
  • src/pages/posts/[slug]/tags.tsx โ†’ /posts/:slug/tags
  • src/pages/posts/[...all].tsx โ†’ /posts/*
Nested layouts
  • By defining _layout.tsx in any nested directory โ†’ src/pages/posts/_layout.tsx
  • Requires using an <Outlet /> component to render layout children
  • All the files within the src/pages/posts/ directory in this case, will be wrapped with that layout
Nested URLs without nested layouts
  • Route file should be outside of the nested layout directory
  • Include dots . between the segments to be converted to forward slashes
  • src/pages/posts.nested.as.url.not.layout.tsx โ†’ /posts/nested/as/url/not/layout
Pathless layouts
  • Similar to nested layouts for layout definition
  • By wrapping the parent directory with parentheses ()
  • src/pages/(auth)/_layout.tsx
  • src/pages/(auth)/login.tsx โ†’ /login
  • Layout parent directory name is not included in the routes paths
Global modals
  • By prefixing the file name with a plus sign + (thinking the modal is an extra route overlaying the current route)
  • Modals navigation available via the useModals() hook
  • src/pages/+info.tsx โ†’ /info
  • src/pages/+checkout/+details.tsx โ†’ /checkout/details
  • src/pages/+checkout/+payment.tsx โ†’ /checkout/payment
Optional segments
  • By prefixing a route segment with a minus sign - (thinking the segment can be subtracted or removed from the route path)
  • src/pages/-en/about.tsx โ†’ /en?/about โ†’ /en/about, /about
  • src/pages/-[lang]/about.tsx โ†’ /:lang?/about โ†’ /en/about, /fr/about, /about
Ignored routes
  • Any directory or file starts with an underscore _ will be ignored
  • src/pages/_ignored.tsx
  • src/pages/posts/_components/button.tsx
  • src/pages/posts/_components/link.tsx

Page exports

  • Required page component export default Component() {...}
  • Optional page loader function export const Loader = () => {...}
  • Optional page action function export const Action = () => {...}
  • Optional suspense-based pending component export const Pending = () => {...}
  • Optional error boundary component export const Catch = () => {...}

Example

Directory structure
src/pages
โ”œโ”€โ”€ (auth)
โ”‚   โ”œโ”€โ”€ _layout.tsx
โ”‚   โ”œโ”€โ”€ login.tsx
โ”‚   โ””โ”€โ”€ register.tsx
โ”œโ”€โ”€ blog
โ”‚   โ”œโ”€โ”€ _components
โ”‚   โ”‚   โ”œโ”€โ”€ button.tsx
โ”‚   โ”‚   โ””โ”€โ”€ comments.tsx
โ”‚   โ”œโ”€โ”€ [...all].tsx
โ”‚   โ”œโ”€โ”€ [slug].tsx
โ”‚   โ”œโ”€โ”€ _layout.tsx
โ”‚   โ”œโ”€โ”€ index.tsx
โ”‚   โ””โ”€โ”€ tags.tsx
โ”œโ”€โ”€ docs
โ”‚   โ”œโ”€โ”€ -[lang]
โ”‚   โ”‚   โ”œโ”€โ”€ index.tsx
โ”‚   โ”‚   โ””โ”€โ”€ resources.tsx
โ”‚   โ””โ”€โ”€ -en
โ”‚       โ””โ”€โ”€ contributors.tsx
โ”œโ”€โ”€ +info.tsx
โ”œโ”€โ”€ 404.tsx
โ”œโ”€โ”€ _app.tsx
โ”œโ”€โ”€ _ignored.tsx
โ”œโ”€โ”€ about.tsx
โ”œโ”€โ”€ blog.w.o.layout.tsx
โ””โ”€โ”€ index.tsx
Overview
FilePathConvention
(auth)/_layout.tsxPathless Layout group
(auth)/login.tsx/loginRegular route
(auth)/register.tsx/registerRegular route
blog/_components/button.tsxIgnored route by an ignored directory
blog/_components/comments.tsxIgnored route by an ignored directory
blog/[...all].tsx/blog/*Dynamic catch-all route
blog/[slug].tsx/blog/:slugDynamic route
blog/_layout.tsxLayout for /blog routes
blog/index.tsx/blogIndex route
blog/tags.tsx/blog/tagsRegular route
docs/-[lang]/index.tsx/docs/:lang?/indexOptional dynamic route segment
docs/-[lang]/resources.tsx/docs/:lang?/resourcesOptional dynamic route segment
docs/-en/contributors.tsx/docs/en?/contributorsOptional static route segment
+info.tsx/infoModal route
404.tsx*Custom 404 (optional)
_app.tsxCustom app layout (optional)
_ignored.tsxIgnored route
about.tsx/aboutRegular route
blog.w.o.layout.tsx/blog/w/o/layoutRoute without /blog layout
index.tsx/Index route

API

Routing

Via @generouted/react-router or @generouted/solid-router

  • <Routes /> โ€” file-based routing component to be render in the app entry
  • routes โ€” file-based routes tree/object used by default at <Routes /> component

Routing + code-splitting and lazy-loading

Via @generouted/react-router/lazy or @generouted/solid-router/lazy

  • Used instead of @generouted/react-router or @generouted/solid-router to enable lazy-loading
  • Make sure to replace all imports to lazy imports โ€” namely at app entry and src/pages/_app.tsx
  • Provides the same <Routes /> and routes exports

Plugins

Via @generouted/react-router/plugin or @generouted/solid-router/plugin

  • Vite plugin for type generation and initializing type-safe components/hooks/utils
  • Generates src/router.ts file
  • Exports type-safe <Link>, <Navigate>, useModals(), useNavigate(), useParams(), redirect(), etc.
  • Check out @generouted/react-router docs or @generouted/solid-router docs for more details

Core

Via @generouted/react-router/core or @generouted/solid-router/core

  • Available for customization, however it's recommended to use the available integrations directory via the <Routes/> component
  • Check out the custom integration example

FAQ

How to implement protected or guarded routes?

There are multiple approaches to achieve that. If you prefer handling the logic in one place, you can define the protected routes with redirection handling within a component:

// src/config/redirects.tsx

import { Navigate, useLocation } from 'react-router-dom'

import { useAuth } from '../context/auth'
import { Path } from '../router'

const PRIVATE: Path[] = ['/logout']
const PUBLIC: Path[] = ['/login']

export const Redirects = ({ children }: { children: React.ReactNode }) => {
  const auth = useAuth()
  const location = useLocation()

  const authenticatedOnPublicPath = auth.active && PUBLIC.includes(location.pathname as Path)
  const unAuthenticatedOnPrivatePath = !auth.active && PRIVATE.includes(location.pathname as Path)

  if (authenticatedOnPublicPath) return <Navigate to="/" replace />
  if (unAuthenticatedOnPrivatePath) return <Navigate to="/login" replace />

  return children
}

Then use that component (<Redirects> ) at the root-level layout src/pages/_app.tsx to wrap the <Outlet> component:

// src/pages/_app.tsx

import { Outlet } from 'react-router-dom'

import { Redirects } from '../config/redirects'

export default function App() {
  return (
    <section>
      <header>
        <nav>...</nav>
      </header>

      <main>
        <Redirects>
          <Outlet />
        </Redirects>
      </main>
    </section>
  )
}

You can find a full example of this approach at Render template


How to use with Hash or Memory Routers?

You can use the exported routes object to customize the router or to use hash/memory routers:

import { createRoot } from 'react-dom/client'
import { RouterProvider, createHashRouter } from 'react-router-dom'
import { routes } from '@generouted/react-router'

const router = createHashRouter(routes)
const Routes = () => <RouterProvider router={router} />

createRoot(document.getElementById('root')!).render(<Routes />)


License

MIT

Keywords

FAQs

Last updated on 13 Apr 2024

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc