Skip to content

ivanfilhoz/safe-router

Repository files navigation

safe-router

NPM Version Github License NPM Downloads Codecov

⚡️ Automagic type-safe route generation for Next.js.

Features

  • ✅ 100% type-safe
  • ✅ Easy setup, no migration needed
  • ✅ Runs as a language service plugin
  • ✅ Watches for changes in the app directory
  • ✅ Supports dynamic and catch-all routes
  • ✅ Supports search parameters (experimental)

Goals

  • 🚧 Support for pages router
  • 🚧 Support for other frameworks like Remix

Requirements

Setup

Install the package from the npm registry:

npm install safe-router

Now, add the following to your tsconfig.json:

{
  "compilerOptions": {
    // ...
    "plugins": [
      // ...
      {
        "name": "safe-router",
        "appFolder": "app" // (optional)
        "outputFile": "routes.generated.ts" // (optional)
      }
    ]
  }
}

Usage

Given the following directory structure:

app/
├── api/
│   ├── [[...params]]/
│   │   └── route.ts
├── products/
│   ├── [id]/
│   │   ├── details/
│   │   │   └── page.tsx
│   │   └── page.tsx
│   └── page.tsx
├── settings/
│   └── page.tsx
└── page.tsx

Use the exported routes object to access your routes throughout your app:

import { routes } from './routes.generated'

routes.get() // /
routes.api.get() // /api
routes.api.params('hello', 'world').get() // /api/hello/world
routes.products.get() // /products
routes.products.id('123').get() // /products/123
routes.products.id('123').details.get() // /products/123/details
routes.settings.get() // /settings

In your page files, use the exported RouteParams type to get typed route parameters:

import type { RouteParams } from './routes.generated'

type Props = {
  params: RouteParams['product.id.details']
}

export default function ProductDetailsPage({ params }: Props) {
  return <div>Details for product {params.id}</div>
}

Search parameters

Search parameters are supported by using the CreateSearchParams type from the safe-router/helpers package:

import { RouteParams } from '@/routes.generated'
import type { CreateSearchParams } from 'safe-router/helpers'

export type Props = {
  params: RouteParams['products.id.details']
  searchParams: CreateSearchParams<{ tab: string }>
}

export default function ProductDetailsPage({ params, searchParams }: Props) {
  const currentTab = searchParams.tab ?? 'default'

  return (
    <div>
      Details for product {params.id}

      Current tab: {currentTab}
    </div>
  )
}

The typed search params will be available as arguments to the get method of the route:

routes.products.id('123').details.get({
  tab: 'specs',
  otherParam: 'hello', // additional params are still supported
}) // /products/123/details?tab=specs&otherParam=hello

License

MIT

About

⚡️ Type-safe routing for Next.js

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published