next-pathmap walks the app and pages directories of a Next.js project, resolves each file to the URL it serves, and writes the result to a JSON file. Every route gets an entry you can extend with your own fields, such as analytics event names, page titles or feature ownership, so that metadata lives next to the list of routes instead of being scattered across pages.
{
"/": {
"alias": "home-viewed",
"query": []
},
"/blog/[slug]": {
"alias": "blog-post-viewed",
"query": ["slug"]
}
}Running it again adds new routes and removes deleted ones while keeping the fields you edited by hand.
- Node.js 16.14 or later
- Next.js with the Pages Router, the App Router, or both
npm install --save-dev next-pathmap
npx next-pathmap init
npx next-pathmapinit detects your router directories and writes pathmap.config.mjs. Running next-pathmap with no command generates the pathmap. A config file is optional; without one, the defaults below apply.
To keep the pathmap current, run it before dev and build:
{
"scripts": {
"predev": "next-pathmap",
"prebuild": "next-pathmap"
}
}next-pathmap looks for pathmap.config.js, pathmap.config.mjs or pathmap.config.cjs in the project root. Use --config to load another file.
/** @type {import("next-pathmap").PathmapConfig<{ alias: string; trackPageView: boolean }>} */
export default {
pagesDir: "src/pages",
output: "src/pathmap.json",
pageExtensions: ["page.tsx", "page.ts"],
exclude: ["**/*.test.*"],
defaults: {
alias: "",
trackPageView: true,
},
categories: [
{ services: "customer-service" },
{ insurance: "insurance/main" },
],
};| Option | Default | Description |
|---|---|---|
appDir |
app, then src/app |
App Router directory. false skips it. |
pagesDir |
pages, then src/pages |
Pages Router directory. false skips it. |
output |
"pathmap/pathmap.json" |
File to write. Must end with .json. |
pageExtensions |
["tsx", "ts", "jsx", "js"] |
Same as pageExtensions in next.config.js. Keep the two in sync. |
exclude |
[] |
Glob patterns, relative to each router directory, for files that are not routes. |
defaults |
{} |
Fields every entry starts with. |
categories |
none | Lookup tables per path depth. categories[i][segment] labels the i-th segment of a route, and the matched labels are written to categories. |
When appDir and pagesDir are omitted, directories are detected the same way Next.js does: app and pages in the project root take precedence, and src is only checked when neither exists there.
The rules follow Next.js routing, so the pathmap lists the URLs your app actually serves.
Pages Router. Every file with a page extension is a route. index maps to its parent directory. _app, _document, _error and everything under api are skipped.
App Router. Only page files are routes. Route groups such as (marketing) are removed from the path. Private folders (_components), parallel route slots (@modal) and intercepting routes ((.)photo) are skipped because they do not define URLs of their own.
Dynamic segments. [id], [...slug] and [[...slug]] stay in the key as written, and their names are listed in query.
If two files resolve to the same URL, for example pages/about.tsx and app/(site)/about/page.tsx, generation fails and names both files.
Each entry is built from three layers. Later layers win:
defaultsfrom the config.- The entry already in the output file, including any fields edited by hand.
- Fields derived from the route:
query, andcategorieswhen configured.
Routes that no longer exist are removed. Keys are sorted, and the file is only written when its content changes, so repeated runs do not touch the file or trigger a reload in next dev.
If the existing output file is not valid JSON, generation stops instead of replacing it, so hand-written data is never lost to a merge conflict.
npx next-pathmap --check--check writes nothing. It lists added and removed routes and exits with code 1 when the committed pathmap is out of date.
next-pathmap [options] Generate the pathmap
next-pathmap init [options] Create pathmap.config.mjs
Options:
--cwd <dir> Project root (default: current directory)
--config <file> Config file to use
--check Fail instead of writing when the pathmap is outdated
-h, --help Display help
-v, --version Display the version
import { generate, PathmapError } from "next-pathmap";
try {
const result = await generate({ cwd: process.cwd(), write: false });
console.log(result.added, result.removed, result.changed);
} catch (error) {
if (error instanceof PathmapError) console.error(error.code, error.message);
else throw error;
}generate accepts cwd, config (inline configuration that skips the config file), configFile and write. It resolves to the pathmap, the resolved routes, the output path, the routes that were added and removed, and whether the file changed. Every expected failure is a PathmapError with a stable code.
The package is ESM only.
The interactive prompt was replaced by next-pathmap init and config file defaults. Options were renamed:
| 1.x | 2.x | Notes |
|---|---|---|
pathToPages |
pagesDir |
Optional now; detected like Next.js does. |
pathToSave |
output |
|
includes |
pageExtensions |
["**/*.page.{ts,tsx}"] becomes ["page.ts", "page.tsx"], matching next.config.js. |
excludes |
exclude |
Drop the leading !. _app, _document, _error and api are skipped without configuration. |
schema |
defaults |
The JSDoc type moved from next-pathmap/config to next-pathmap:
- /** @type {import('next-pathmap/config').PathmapConfig} */
+ /** @type {import('next-pathmap').PathmapConfig} */Node.js 14 is no longer supported.
Bug reports and pull requests are welcome. See CONTRIBUTING.md.
MIT © Wonkook Lee
