├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md └── workflows │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .husky └── pre-commit ├── .nvmrc ├── .prettierignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── babel.config.cjs ├── codecov.yml ├── eslint.config.js ├── examples ├── app │ ├── .gitignore │ ├── @types │ │ └── nextjs-routes.d.ts │ ├── README.md │ ├── eslint.config.cjs │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ ├── src │ │ └── app │ │ │ ├── [store] │ │ │ ├── client.tsx │ │ │ └── page.tsx │ │ │ ├── client.tsx │ │ │ ├── head.tsx │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ └── tsconfig.json ├── cjs │ ├── .gitignore │ ├── README.md │ ├── __test__ │ │ └── index.test.tsx │ ├── eslint.config.cjs │ ├── jest.config.mjs │ ├── jest.setup.js │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ │ ├── _app.tsx │ │ ├── bars │ │ │ └── [bar].tsx │ │ └── index.tsx │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ ├── tsconfig.json │ └── types │ │ └── nextjs-routes.d.ts ├── intl │ ├── .gitignore │ ├── @types │ │ └── nextjs-routes.d.ts │ ├── README.md │ ├── eslint.config.cjs │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── vercel.svg │ ├── src │ │ └── pages │ │ │ ├── [store].tsx │ │ │ ├── _app.tsx │ │ │ └── index.tsx │ └── tsconfig.json └── typescript │ ├── .gitignore │ ├── README.md │ ├── __test__ │ └── index.test.tsx │ ├── eslint.config.cjs │ ├── jest.config.mjs │ ├── jest.setup.js │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ ├── _app.tsx │ ├── api │ │ └── hello.ts │ ├── bars │ │ └── [bar].tsx │ ├── foos │ │ └── [foo].tsx │ └── index.tsx │ ├── public │ ├── favicon.ico │ └── vercel.svg │ ├── tsconfig.json │ └── types │ └── nextjs-routes.d.ts ├── images └── nextjs-routes.gif ├── jest.config.cjs ├── package.json ├── packages ├── e2e │ ├── @types │ │ └── nextjs-routes.d.ts │ ├── app │ │ ├── bars │ │ │ └── [bar] │ │ │ │ └── page.tsx │ │ └── layout.tsx │ ├── e2e.test.ts │ ├── eslint.config.cjs │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── pages │ │ ├── [...slug].tsx │ │ ├── foos │ │ │ └── [foo].tsx │ │ └── index.tsx │ ├── tsconfig.json │ └── typetest.tsx └── nextjs-routes │ ├── .npmignore │ ├── package.json │ ├── src │ ├── cli.ts │ ├── config.ts │ ├── core.ts │ ├── index.ts │ ├── logger.ts │ ├── test │ │ ├── __snapshots__ │ │ │ └── core.test.ts.snap │ │ ├── core.test.ts │ │ ├── index.test.ts │ │ ├── logger.test.ts │ │ └── utils.test.ts │ ├── utils.ts │ └── version.ts │ ├── tsconfig.json │ └── webpack.config.cjs ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── tsconfig.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "bug:" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A description of what the bug is. 11 | 12 | **Context (please complete the following information):** 13 | 14 | - nextjs-routes version: 15 | - Are you using the [pages](https://nextjs.org/docs/pages/building-your-application/routing) directory, [app](https://nextjs.org/docs/app/building-your-application/routing) directory, or both? 16 | - Are you using nextjs-routes via [next.config.js](https://github.com/tatethurston/nextjs-routes?tab=readme-ov-file#installation--usage-) or the CLI (`npx nextjs-routes`)? 17 | - nextjs version: 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "feature:" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Additional context** 16 | Add any other context or screenshots about the feature request here. 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | jobs: 8 | build-package: 9 | name: Build Package 10 | runs-on: ubuntu-latest 11 | outputs: 12 | package: ${{ steps.publish-local-package.outputs.package }} 13 | steps: 14 | - uses: tatethurston/github-actions/publish-local-package@main 15 | id: publish-local-package 16 | with: 17 | path: packages/nextjs-routes 18 | ci: 19 | name: Lint and Test 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: tatethurston/github-actions/test@main 23 | with: 24 | codecov_token: ${{ secrets.CODECOV_TOKEN }} 25 | - uses: tatethurston/github-actions/check-generated-files@main 26 | with: 27 | cmd: pnpm examples:regen 28 | ci-windows: 29 | name: Windows CI 30 | runs-on: windows-latest 31 | needs: build-package 32 | steps: 33 | - uses: tatethurston/github-actions/install-local-package@main 34 | with: 35 | name: ${{ needs.build-package.outputs.package }} 36 | - name: Bin Check 37 | run: | 38 | echo 'module.exports = {}' > next.config.js 39 | mkdir pages 40 | npx --no nextjs-routes 41 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish NPM Package 2 | on: 3 | release: 4 | types: [published] 5 | workflow_dispatch: 6 | jobs: 7 | publish: 8 | name: Publish to NPM 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: tatethurston/github-actions/publish@main 12 | with: 13 | package_directory: packages/nextjs-routes 14 | npm_token: ${{ secrets.NPM_TOKEN }} 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | coverage 3 | node_modules 4 | tsconfig.tsbuildinfo 5 | .next 6 | .vscode 7 | # copied over durring build 8 | packages/nextjs-routes/LICENSE 9 | packages/nextjs-routes/README.md 10 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | # pnpm run e2e:setup 2 | # pnpm run examples:regen 3 | pnpm run lint:fix 4 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20.9.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | coverage 3 | public.package.json 4 | .next 5 | .swc 6 | out 7 | node_modules 8 | pnpm-lock.yaml 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2.2.5 4 | 5 | - Fix CLI invocation on Windows. 6 | 7 | ## 2.2.4 8 | 9 | - CLI invocation now reads next.config.js or next.config.mjs. 10 | - Fix `route`'s handling of query keys whose value is `undefined`. Fixes #206. Thanks @sleepdotexe! 11 | 12 | ## 2.2.3 13 | 14 | - Bug fix: `usePathname` and `useParams` were incorrectly resolving to `any` return types. 15 | 16 | ## 2.2.2 17 | 18 | - Adds support for Next.js's `app` directory. `Link` accepts either static routes (no url parameters) or a `RouteLiteral` string, which can be generated by the `route` helper from this library: 19 | 20 | ```tsx 21 | import { route } from "nextjs-routes"; 22 | 23 | 29 | Baz 30 | ; 31 | ``` 32 | 33 | - Add `RouteLiteral` type. This type represents a string that has been confirmed to be a validated application route and can be passed to `Link` or `useRouter`. This is a TypeScript branded type. 34 | 35 | ```ts 36 | import { RouteLiteral } from "nextjs-routes"; 37 | ``` 38 | 39 | `route` returns a `RouteLiteral`. If you construct a route string you can cast it to a `RouteLiteral` so that `Link` and `useRouter` will accept it: 40 | 41 | ``` 42 | const myRoute = `/foos/${foo}` as RouteLiteral 43 | ``` 44 | 45 | In general, prefer using the `route` helper to generate routes. 46 | 47 | - Refine types for `usePathname`, `useRouter` and `useParams` from `"next/navigation"` to use `nextjs-routes` generated types. 48 | 49 | - Fix generated routes when using [parallel-routes](https://nextjs.org/docs/app/building-your-application/routing/parallel-routes) and [intercepting-routes](https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes). 50 | 51 | - Fix `ref` type for `Link`. Previously `ref` was missing, now it's correctly typed. 52 | 53 | ## 2.2.1 54 | 55 | - Fix route generation on Windows. See [#187](https://github.com/tatethurston/nextjs-routes/issues/187). Thanks @AkanoCA! 56 | 57 | ## 2.2.0 58 | 59 | - Add `trailingSlash` option to `route`. See [#168](https://github.com/tatethurston/nextjs-routes/issues/168) 60 | - Fix the generated optional catch all route type. See [#183](https://github.com/tatethurston/nextjs-routes/issues/183) 61 | - Sort the generated route types lexicographically. 62 | 63 | ## 2.1.0 64 | 65 | - Add experimental support for app directory [route handler](https://nextjs.org/docs/app/building-your-application/routing/route-handlers). See [#178](https://github.com/tatethurston/nextjs-routes/issues/178). 66 | 67 | ## 2.0.1 68 | 69 | - Fix `GetServerSidePropsContext` and `GetServerSidePropsResult` types. Thanks @po4tion! 70 | - Change generated file location from `nextjs-routes.d.ts` to `@types/nextjs-routes.d.ts`. Thanks @po4tion! 71 | 72 | To preserve the old location, make the following change to your `next.config.js`: 73 | 74 | ```diff 75 | const nextRoutes = require("nextjs-routes/config"); 76 | const withRoutes = nextRoutes({ 77 | + outDir: "", 78 | }); 79 | ``` 80 | 81 | Otherwise, delete your old `nextjs-routes.d.ts` once `@types/nextjs-routes.d.ts` is generated. 82 | 83 | ## 2.0.0 84 | 85 | - `router.query` types must now be narrowed using `router.isReady`. This ensures types are correct for pages that use [Automatic Static Optimization](https://nextjs.org/docs/advanced-features/automatic-static-optimization). 86 | 87 | [Next's documentation](https://nextjs.org/docs/advanced-features/automatic-static-optimization) notes the following: 88 | 89 | > During prerendering, the router's query object will be empty since we do not have query information to provide during this phase. After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object. 90 | 91 | See [#117](https://github.com/tatethurston/nextjs-routes/issues/117) for more context and discussion. 92 | 93 | - Route type generation can now also be generated outside of `next build` / `next dev` by using `npx nextjs-routes`. 94 | 95 | ## 1.0.9 96 | 97 | - Enable `Link` and `router` methods to only update the route `hash`. Thanks @sitch! 98 | - Publish commonjs for `route` runtime so jest tests don't require transpilation for users. Thanks @panudetjt! 99 | - Add `GetServerSidePropsContext` type. Thanks @slhck! 100 | 101 | ## 1.0.8 102 | 103 | - Fix type definition import path for `nextjs-routes/config` so it is visible to `tsc`. 104 | 105 | ## 1.0.7 106 | 107 | - Remove package.json version import. This resolves `TypeError[ERR_IMPORT_ASSERTION_TYPE_MISSING]`. [See #115](https://github.com/tatethurston/nextjs-routes/issues/115) for more context. 108 | 109 | ## 1.0.6 110 | 111 | - Fix bad publish of 1.0.5 112 | 113 | ## 1.0.5 114 | 115 | - The version of `nextjs-routes` is now included in the generated `nextjs-routes.d.ts` file. 116 | - Switch `Link` to use TypeScript unions instead of function overloading. Function overloading resulted in errors that were difficult for users to understand, and [created issues for some use cases](https://github.com/tatethurston/nextjs-routes/issues/111). 117 | 118 | ## 1.0.4 119 | 120 | - `LinkProps` now accept path strings for static routes: 121 | 122 | ```tsx 123 | import { LinkProps } from "next/link"; 124 | // previously this would error 125 | const props: LinkProps = { href: "/foo" }; 126 | ``` 127 | 128 | ## 1.0.3 129 | 130 | - The `Route` type now includes `hash`. This enables the following: 131 | 132 | ```tsx 133 | // this will link to /foo#bar 134 | Foo 135 | ``` 136 | 137 | ## 1.0.2 138 | 139 | - `Link` now [accepts anchor props](https://beta.nextjs.org/docs/api-reference/components/link): 140 | 141 | ```tsx 142 | 143 | Dashboard 144 | 145 | ``` 146 | 147 | ## 1.0.1 148 | 149 | - Update `NextRouter` type to keep `query` and `pathname` bound in a union. This allows you to use `router` from `useRouter` as an argument to `router.push` or `router.replace`: 150 | 151 | ```ts 152 | const router = useRouter(); 153 | // reload the current page, preserving search parameters 154 | router.push(router, undefined, { locale: "fr" }); 155 | ``` 156 | 157 | ## 1.0.0 158 | 159 | - This library will now follow [semantic versioning](https://docs.npmjs.com/about-semantic-versioning). 160 | 161 | - The previously deprecated direct invocation of nextjs-routes via `npx nextjs-routes` has been removed in favor of automatic regeneration via [withRoutes](https://github.com/tatethurston/nextjs-routes#installation--usage-). See [#63](https://github.com/tatethurston/nextjs-routes/issues/63) for the motivation behind this change or to voice any concerns. 162 | 163 | ## 0.1.7 164 | 165 | - Support [Next 13 app (beta) directory](https://nextjs.org/docs/advanced-features/custom-app) 166 | 167 | - Add `dir` option to support non standard NextJS project structures such as [Nx](https://nx.dev/packages/next): 168 | 169 | ```js 170 | // next.config.js 171 | const withRoutes = require("nextjs-routes/config")({ dir: __dirname }); 172 | ``` 173 | 174 | Thanks [@alexgorbatchev](https://github.com/alexgorbatchev) for the contribution! 175 | 176 | ## 0.1.6 177 | 178 | - Accept path strings for static routes: 179 | 180 | ```tsx 181 | Foo 182 | ``` 183 | 184 | Thanks [@MariaSolOs](https://github.com/MariaSolOs) for the contribution! 185 | 186 | - Use function overloads for `Link` and `router.push` and `router.replace`. This yields better hints for typos in pathnames: 187 | 188 | ```tsx 189 | Foo 190 | ``` 191 | 192 | Previously: 193 | `[tsserver 2322] [E] Type '"/foos/[foo]"' is not assignable to type '"/"'.` 194 | 195 | Now: 196 | `Type '"/foosy/[foo]"' is not assignable to type '"/api/hello" | "/bars/[bar]" | "/foos/[foo]" | "/"'. Did you mean '"/foos/[foo]"'?` (+2 other overload errors). 197 | 198 | ## 0.1.5 199 | 200 | - Export `Locale` from `nextjs-routes`. 201 | 202 | ```ts 203 | import { Locale } from "nextjs-routes"; 204 | ``` 205 | 206 | Thanks [@Asamsig](https://github.com/Asamsig) for the contribution! 207 | 208 | ## 0.1.4 209 | 210 | - `nextjs-routes` now generates route types for [Nextjs i18n configuration](https://nextjs.org/docs/advanced-features/i18n-routing). Eg the following next config: 211 | 212 | ```js 213 | module.exports = withRoutes({ 214 | i18n: { 215 | defaultLocale: "de-DE", 216 | locales: ["de-DE", "en-FR", "en-US"], 217 | }, 218 | }); 219 | ``` 220 | 221 | Will make `locale` typed as `'de-DE' | 'en-FR' | 'en-US'` for `Link` and `useRouter`. 222 | 223 | ## 0.1.3 224 | 225 | - `nextjs-routes` [pageExtensions](https://nextjs.org/docs/api-reference/next.config.js/custom-page-extensions) has been updated to respect multiple extensions such as `.page.tsx`. In `0.1.2`, only single extensions `.tsx` were respected. This is now identical behavior to Next.js. 226 | 227 | ## 0.1.2 228 | 229 | - `nextjs-routes` now respects [pageExtensions](https://nextjs.org/docs/api-reference/next.config.js/custom-page-extensions) from `next.config.js`. 230 | 231 | ## 0.1.1 232 | 233 | [ skipped ] 234 | 235 | ## 0.1.0 236 | 237 | This release contains a breaking change, indicated by the minor version bump to 0.1.0. `nextjs-routes` has not yet reached v1, but will follow semantic versioning once it does. Until then, minor version changes will be used to help flag breaking changes. 238 | 239 | - Breaking change: the `withRoutes` import path and invocation has changed to better align with the general pattern in the Nextjs plugin ecosystem and to support configuration options, notably the new `outDir` option. It also now includes an ESM export to support usage in `next.config.mjs`. 240 | 241 | ```diff 242 | - const { withRoutes } = require("nextjs-routes/next-config.cjs"); 243 | + const withRoutes = require("nextjs-routes/config")(); 244 | 245 | /** @type {import('next').NextConfig} */ 246 | const nextConfig = { 247 | reactStrictMode: true, 248 | }; 249 | 250 | module.exports = withRoutes(nextConfig); 251 | ``` 252 | 253 | Note the import path has changed and the import itself has changed to function that is invoked with any configuration options. This provides better ergonomics for configuration options: 254 | 255 | ```js 256 | const withRoutes = require("nextjs-routes/config")({ outDir: "types" }); 257 | ``` 258 | 259 | - The type `RoutedQuery` has been added to retrieve the `Query` for a given `Route`. This is useful as the context type parameter inside `getStaticProps` and `getServerSideProps`. Thanks [@MariaSolOs](https://github.com/MariaSolOs) for the contribution! 260 | 261 | - `withRoutes` now accepts `outDir` as a configuration option to dictate where `nextjs-routes.d.ts` is generated. Thanks [@MariaSolOs](https://github.com/MariaSolOs) for the contribution! 262 | 263 | ## 0.0.22 264 | 265 | - Deprecate direct invocation of nextjs-routes in favor of automatic regeneration via [withRoutes](https://github.com/tatethurston/nextjs-routes#installation--usage-). See [#63](https://github.com/tatethurston/nextjs-routes/issues/63) for the motivation behind this change or to voice any concerns. 266 | 267 | ## 0.0.21 268 | 269 | - Add `route` runtime for generating type safe pathnames from a `Route` object 270 | 271 | This can be used to fetch from API routes: 272 | 273 | ```ts 274 | import { route } from "nextjs-routes"; 275 | 276 | fetch(route({ pathname: "/api/foos/[foo]", query: { foo: "foobar" } })); 277 | ``` 278 | 279 | Or for type safe redirects from `getServerSideProps`: 280 | 281 | ```ts 282 | import { route } from "nextjs-routes"; 283 | 284 | export const getServerSideProps: GetServerSideProps = async (context) => { 285 | return { 286 | redirect: { 287 | destination: route({ pathname: "/foos/[foo]", query: { foo: "foobar" } }), 288 | permanent: false, 289 | }, 290 | }; 291 | }; 292 | ``` 293 | 294 | ## 0.0.20 295 | 296 | - Move `chokidar` from `devDependencies` to `dependencies` so it's installed automatically. 297 | 298 | ## 0.0.19 299 | 300 | - Bug Fix: quote query segments in generated types. See [#49](https://github.com/tatethurston/nextjs-routes/issues/49) for more context. 301 | - Bug Fix: don't generate routes for non navigable routes (`_error`, `_app`, `_document`). 302 | - Bug Fix: don't generate routes for test files that are co-located in pages directory. See [#50](https://github.com/tatethurston/nextjs-routes/pull/50) for more context. 303 | 304 | ## 0.0.18 305 | 306 | - `query` is now typed as `string | string[] | undefined` instead of `string | undefined`. 307 | - `nextjs-routes` can now be configured via your `next.config.js` to automatically regenerate types whenever your routes change: 308 | 309 | ```js 310 | // next.config.js 311 | 312 | /** @type {import('next').NextConfig} */ 313 | const { withRoutes } = require("nextjs-routes/next-config.cjs"); 314 | 315 | const nextConfig = { 316 | reactStrictMode: true, 317 | }; 318 | 319 | module.exports = withRoutes(nextConfig); 320 | ``` 321 | 322 | This wiring will only run in Next.js' development server (eg `npx next dev`) and `withRoutes` will no-op in production. 323 | 324 | ## 0.0.17 325 | 326 | - re-export types from `next/link` and `next/router`. 327 | - remove prettier as a peer dependency. 328 | - enable src/pages for windows users. 329 | - routes are now generated for routes that start with `_`. `_app`, `_document`, `_error` and `middleware` are excluded. 330 | - gracefully handles missing pages directory and no pages. 331 | 332 | ## 0.0.16 333 | 334 | - fixed prettier as an optional peer dependency 335 | 336 | ## 0.0.15 337 | 338 | - nextjs-routes no longer adds types to the global type namespace. Previously, 339 | `Route` was available globally. Now, it must be imported: 340 | 341 | ```ts 342 | import type { Route } from "nextjs-routes"; 343 | ``` 344 | 345 | - query from `useRouter` is now correctly typed as `string | undefined` instead of `string`. If you know the current route, you can supply a type argument to narrow required parameters to `string`, eg: 346 | 347 | ``` 348 | // if you have a page /foos/[foo].ts 349 | 350 | const router = useRouter<"/foos/[foo]">(); 351 | // foo will be typed as a string, because the foo query parameter is required and thus will always be present. 352 | const { foo } = router.query; 353 | ``` 354 | 355 | ## 0.0.14 356 | 357 | - Allow passing in `query` without `pathname` to change current url parameters. 358 | - `router.query` can no longer be `undefined`. 359 | 360 | ## 0.0.13 361 | 362 | - Support search parameters. See [#17](https://github.com/tatethurston/nextjs-routes/issues/17) for more context. 363 | 364 | ## 0.0.12 365 | 366 | - Removed reexports of `next/link` and `next/router`. 367 | 368 | This means replacing imports of `next/link` with `nextjs-routes/link` and `next/router` with `nextjs-routes/router` is no longer necessary: 369 | 370 | ```diff 371 | -import Link from "nextjs-routes/link"; 372 | +import Link from "next/link"; 373 | ``` 374 | 375 | ```diff 376 | -import { useRouter } from 'nextjs-routes/router' 377 | +import { useRouter } from 'next/router' 378 | ``` 379 | 380 | - Added windows support. 381 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 👫 2 | 3 | Thanks for helping make this project better! 4 | 5 | ## Report an Issue 🐛 6 | 7 | If you find a bug or want to discuss a new feature, please [create a new issue](https://github.com/tatethurston/nextjs-routes/issues). If you'd prefer to keep things private, feel free to [email me](mailto:tatethurston@gmail.com?subject=nextjs-routes). 8 | 9 | ## Contributing Code with Pull Requests 🎁 10 | 11 | Please create a [pull request](https://github.com/tatethurston/nextjs-routes/pulls). Expect a few iterations and some discussion before your pull request is merged. If you want to take things in a new direction, feel free to fork and iterate without hindrance! 12 | 13 | ## Code of Conduct 🧐 14 | 15 | My expectations for myself and others is to strive to build a diverse, inclusive, safe community. 16 | 17 | For more guidance, check out [thoughtbot's code of conduct](https://thoughtbot.com/open-source-code-of-conduct). 18 | 19 | ## Licensing 📃 20 | 21 | See the project's [MIT License](https://github.com/tatethurston/nextjs-routes/blob/main/LICENSE). 22 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Local Development 2 | 3 | ### First time setup 4 | 5 | From the project directory root: 6 | 7 | 1. `nvm use` 8 | 1. `pnpm install` 9 | 1. `pnpm package:build` 10 | 11 | The source code for the package is in `packages/nextjs-routes/`. 12 | 13 | There are examples that use the locally built package in `examples/`. 14 | 15 | There is an e2e test that runs against a minimal nextjs application in `packages/e2e/`. 16 | 17 | ### Testing 18 | 19 | Tests are run with jest. 20 | 21 | From the project directory root: 22 | 23 | `pnpm test` 24 | 25 | ### Linting 26 | 27 | As part of installation, husky pre-commit hooks are installed to run linters against the repo. 28 | 29 | ### Publishing 30 | 31 | There are CI and publishing GitHub workflows in `./github/workflows`. These are named `ci.yml` and `publish.yml`. 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tate Thurston 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next.js Routes 2 | 3 |
Type safe routing for Next.js4 | 5 |
= Extract<
34 | Route,
35 | { pathname: P }
36 | >["query"];
37 |
38 | export type Locale = undefined;
39 |
40 | type Brand =
136 | BaseRouter (): NextRouter ;
168 | }
169 |
170 | // prettier-ignore
171 | declare module "next/navigation" {
172 | export * from "next/dist/client/components/navigation";
173 | import type { Route, RouteLiteral, RoutedQuery } from "nextjs-routes";
174 | import type { AppRouterInstance as NextAppRouterInstance, NavigateOptions, PrefetchOptions } from "next/dist/shared/lib/app-router-context.shared-runtime";
175 |
176 | type StaticRoute = Exclude Version: {version} Store: {store} {f} = Extract<
34 | Route,
35 | { pathname: P }
36 | >["query"];
37 |
38 | export type Locale = undefined;
39 |
40 | type Brand =
136 | BaseRouter (): NextRouter ;
168 | }
169 |
--------------------------------------------------------------------------------
/examples/intl/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env.local
30 | .env.development.local
31 | .env.test.local
32 | .env.production.local
33 |
34 | # vercel
35 | .vercel
36 |
37 | # typescript
38 | *.tsbuildinfo
39 |
--------------------------------------------------------------------------------
/examples/intl/@types/nextjs-routes.d.ts:
--------------------------------------------------------------------------------
1 | // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | // This file will be automatically regenerated when your Next.js server is running.
3 | // nextjs-routes version: 2.2.5
4 | /* eslint-disable */
5 |
6 | // prettier-ignore
7 | declare module "nextjs-routes" {
8 | import type {
9 | GetServerSidePropsContext as NextGetServerSidePropsContext,
10 | GetServerSidePropsResult as NextGetServerSidePropsResult
11 | } from "next";
12 |
13 | export type Route =
14 | | StaticRoute<"/">
15 | | DynamicRoute<"/[store]", { "store": string }>;
16 |
17 | interface StaticRoute = Extract<
34 | Route,
35 | { pathname: P }
36 | >["query"];
37 |
38 | export type Locale =
39 | | "en-US"
40 | | "fr"
41 | | "nl-NL";
42 |
43 | type Brand =
143 | BaseRouter (): NextRouter ;
179 | }
180 |
--------------------------------------------------------------------------------
/examples/intl/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```sh
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | ```
14 |
15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
16 |
17 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
18 |
19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
20 |
21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
22 |
23 | ## Learn More
24 |
25 | To learn more about Next.js, take a look at the following resources:
26 |
27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29 |
30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
31 |
32 | ## Deploy on Vercel
33 |
34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35 |
36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
37 |
--------------------------------------------------------------------------------
/examples/intl/eslint.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["next/core-web-vitals"],
3 | };
4 |
--------------------------------------------------------------------------------
/examples/intl/next-env.d.ts:
--------------------------------------------------------------------------------
1 | /// = Extract<
36 | Route,
37 | { pathname: P }
38 | >["query"];
39 |
40 | export type Locale = undefined;
41 |
42 | type Brand =
138 | BaseRouter (): NextRouter ;
170 | }
171 |
--------------------------------------------------------------------------------
/images/nextjs-routes.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tatethurston/nextjs-routes/9fc0668c6ff1acfa69a54e6c1a434e350cf5b13a/images/nextjs-routes.gif
--------------------------------------------------------------------------------
/jest.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | clearMocks: true,
3 | coverageDirectory: "coverage",
4 | modulePathIgnorePatterns: ["dist", "examples"],
5 | // TS ESM imports are referenced with .js extensions, but jest will fail to find
6 | // the uncompiled file because it ends with .ts and is looking for .js.
7 | moduleNameMapper: {
8 | "(.+)\\.jsx?": "$1",
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "nextjs-routes-development",
4 | "version": "0.0.1",
5 | "license": "MIT",
6 | "author": "Tate