Convert Figma logo to code with AI

oedotme logogenerouted

Generated file-based routes for Vite

1,095
57
1,095
4

Top Related Projects

30,309

Build Better Websites. Create modern, resilient user experiences with web fundamentals.

SolidStart, the Solid app framework

6,895

6,666

🥢 A minimalist-friendly ~2.1KB routing for React and Preact

Declarative routing for React

Quick Overview

Generouted is a file-based routing library for React applications, inspired by Next.js and Remix. It automatically generates routes based on your file structure, simplifying the process of setting up and managing routes in React projects.

Pros

  • Simplifies route management by using a file-based approach
  • Reduces boilerplate code for routing configuration
  • Supports nested routes and dynamic segments
  • Integrates well with popular React frameworks like Vite

Cons

  • Limited flexibility compared to manual route configuration
  • May require adjusting project structure to fit the routing conventions
  • Learning curve for developers accustomed to traditional React routing
  • Potential performance impact for large applications with many routes

Code Examples

  1. Basic route definition:
// src/pages/index.tsx
export default function Home() {
  return <h1>Welcome to the home page</h1>
}
  1. Dynamic route segment:
// src/pages/users/[id].tsx
import { useParams } from 'react-router-dom'

export default function UserProfile() {
  const { id } = useParams()
  return <h1>User Profile: {id}</h1>
}
  1. Nested routes:
// src/pages/dashboard/layout.tsx
import { Outlet } from 'react-router-dom'

export default function DashboardLayout() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Outlet />
    </div>
  )
}

// src/pages/dashboard/index.tsx
export default function DashboardHome() {
  return <p>Dashboard Home Content</p>
}

Getting Started

  1. Install Generouted:
npm install generouted
  1. Set up Vite configuration:
// 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()]
})
  1. Create your routes in the src/pages directory following the file-based routing conventions.

  2. Use the generated routes in your main application file:

// src/main.tsx
import { Routes } from '@generouted/react-router'

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

Competitor Comparisons

30,309

Build Better Websites. Create modern, resilient user experiences with web fundamentals.

Pros of Remix

  • Full-featured web framework with server-side rendering and data loading
  • Robust ecosystem with extensive documentation and community support
  • Integrated with React and provides a seamless development experience

Cons of Remix

  • Steeper learning curve due to its comprehensive feature set
  • Requires more setup and configuration compared to simpler routing solutions
  • May be overkill for small projects or static websites

Code Comparison

Remix route definition:

export default function Route() {
  return <div>Hello, Remix!</div>;
}

Generouted route definition:

import { Route } from 'generouted';

export default () => (
  <Route path="/" element={<div>Hello, Generouted!</div>} />
);

Summary

Remix is a full-featured web framework that offers server-side rendering, data loading, and a robust ecosystem. It's well-suited for complex applications but may be excessive for simpler projects. Generouted, on the other hand, focuses solely on routing and provides a more lightweight solution. It's easier to set up and integrate into existing projects but lacks the comprehensive features of Remix. The choice between the two depends on the project's requirements and complexity.

SolidStart, the Solid app framework

Pros of Solid Start

  • Full-featured framework with server-side rendering, routing, and data fetching
  • Integrated with SolidJS ecosystem, providing a cohesive development experience
  • Supports both static site generation and server-side rendering out of the box

Cons of Solid Start

  • Steeper learning curve due to its comprehensive nature
  • More opinionated structure, which may limit flexibility for some projects
  • Larger bundle size compared to minimal routing solutions

Code Comparison

Solid Start route definition:

// src/routes/index.tsx
export default function Home() {
  return <h1>Welcome to Solid Start</h1>;
}

Generouted route definition:

// src/pages/index.tsx
export default function Home() {
  return <h1>Welcome to Generouted</h1>;
}

Both examples show similar simplicity in defining routes, with Generouted following a more traditional file-based routing approach, while Solid Start integrates routing within its framework structure.

6,895

Pros of Reach Router

  • More mature and widely adopted project with extensive documentation
  • Built-in accessibility features and focus management
  • Supports server-side rendering out of the box

Cons of Reach Router

  • Larger bundle size compared to Generouted
  • Less flexible routing configuration options
  • Not actively maintained (last commit over 2 years ago)

Code Comparison

Reach Router:

import { Router, Link } from "@reach/router"

const App = () => (
  <Router>
    <Home path="/" />
    <Dashboard path="dashboard" />
  </Router>
)

Generouted:

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

const App = () => (
  <Routes />
)

Generouted offers a more minimalistic approach, automatically generating routes based on file structure, while Reach Router requires manual route configuration. Reach Router provides a more explicit routing setup, which can be beneficial for larger applications with complex routing needs. However, Generouted's file-based routing can lead to cleaner and more maintainable code in many cases.

Both libraries aim to simplify routing in React applications, but they take different approaches. Reach Router focuses on accessibility and ease of use, while Generouted emphasizes convention over configuration and automatic route generation.

6,666

🥢 A minimalist-friendly ~2.1KB routing for React and Preact

Pros of wouter

  • Lightweight and minimalistic, with a small bundle size
  • Simple API that's easy to learn and use
  • Supports both hash-based and history-based routing

Cons of wouter

  • Less feature-rich compared to generouted
  • May require additional setup for more complex routing scenarios
  • Limited built-in support for nested routes

Code Comparison

wouter:

import { Route, Switch } from "wouter";

<Switch>
  <Route path="/users/:id" component={UserProfile} />
  <Route path="/about" component={About} />
</Switch>

generouted:

import { Route } from "@generouted/react-router";

<Route>
  <Route path="/users/:id" element={<UserProfile />} />
  <Route path="/about" element={<About />} />
</Route>

Both libraries offer a similar syntax for defining routes, but generouted provides a more integrated approach with automatic route generation based on file structure. wouter focuses on simplicity and minimal configuration, while generouted offers more advanced features and integration with the file system for route management.

Declarative routing for React

Pros of React Router

  • Mature and widely adopted library with extensive documentation and community support
  • Offers a rich set of features, including nested routing, route parameters, and programmatic navigation
  • Provides a flexible and powerful API for handling complex routing scenarios

Cons of React Router

  • Requires more boilerplate code for setting up routes and navigation
  • Can be overkill for simple applications with straightforward routing needs
  • Learning curve may be steeper for beginners due to its extensive feature set

Code Comparison

React Router:

import { BrowserRouter, Routes, Route } from 'react-router-dom';

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
  </Routes>
</BrowserRouter>

Generouted:

import { Router } from 'generouted';

<Router />

Generouted automatically generates routes based on the file structure, reducing the need for manual route configuration. React Router, on the other hand, requires explicit route definitions but offers more control over routing behavior.

Both libraries have their strengths, with React Router being more suitable for complex applications and Generouted offering a simpler, convention-based approach for smaller projects or those preferring file-based routing.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README


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

NPM DownloadsLast 30 Days