Configuration file
Configure route discovery, generated output, path normalization, and custom constraints.
cookbook-router.config.* is shared by the CLI and bundler plugins. It tells Cookbook Router where route definitions live, where generated artifacts belong, and which path rules apply to the route tree.
If you ran cbr init, the configuration file already exists. Most projects only need routeFiles and outDir.
Basic configuration
import { defineRouterConfig } from '@cookbook/router-cli';
export default defineRouterConfig({
routeFiles: 'src/**/*.route.{ts,tsx}',
outDir: '.cookbook-router',
});Paths declared in the config are resolved relative to the configuration file.
Prop
Type
Accepted configuration files
Cookbook Router checks these filenames in order:
cookbook-router.config.ts
cookbook-router.config.mts
cookbook-router.config.cts
cookbook-router.config.js
cookbook-router.config.mjs
cookbook-router.config.cjsDiscovery starts from the current project directory and moves upward until a supported file is found.
Select a specific file when automatic discovery is not appropriate:
cbr generate --config config/cookbook-router.config.tsBundler plugins expose the same behavior through their configFile option.
Route inputs
Use routeFiles to identify the modules containing route declarations that the generator should inspect.
One file or pattern
Use a string:
export default defineRouterConfig({
routeFiles: 'src/**/*.route.{ts,tsx}',
});Multiple files or patterns
Use an array with two or more entries:
export default defineRouterConfig({
routeFiles: [
'src/**/*.route.{ts,tsx}',
'features/**/*.route.{ts,tsx}',
],
});Route files may export defineRoute(...), defineRoutes(...), defineRouteTree(...), or statically inspectable route arrays.
Folder structure does not define route hierarchy. Nesting comes from the route declarations and their explicit parent relationships.
Generated output
outDir controls where Cookbook Router writes generated artifacts:
export default defineRouterConfig({
routeFiles: 'src/**/*.route.{ts,tsx}',
outDir: '.generated/router',
});The default directory is:
.cookbook-routerA successful aggregate generation writes:
contracts.ts
register.d.ts
manifest.jsonIt also writes routes.ts when the selected route exports can be composed into a static generated route module.
Keep the output directory in the project and add its contract files to the include array in tsconfig.json.
See Generated artifacts for the purpose and lifecycle of each file.
Path normalization
pathOptions.prune controls slash normalization.
It does not remove route definitions, path segments, parameters, or constraints. It only determines whether duplicate and trailing slashes are removed.
export default defineRouterConfig({
routeFiles: 'src/**/*.route.{ts,tsx}',
pathOptions: {
prune: 'all',
},
});Given this pathname:
/users//42/the available values behave as follows:
| Value | Result | Behavior |
|---|---|---|
'all' | /users/42 | Removes duplicate and trailing slashes |
'duplication' | /users/42/ | Removes duplicate slashes and preserves the trailing slash |
'trailing' | /users//42 | Removes the trailing slash and preserves duplicate slashes |
false | /users//42/ | Preserves the pathname as written |
The default is:
{
prune: 'all',
}The root path remains / in every mode.
The same normalization must be used during validation, matching, and URL generation. Define it once in the config instead of letting different route sources disagree about what a path means.
See Path routes and constraints for the complete path model.
Custom path constraints
If any route path uses a custom constraint, register it in pathConstraints.
This is required for route validation and generation. Without the constraint definition, Cookbook Router cannot validate the path pattern, generate the route tree, or keep generated contracts aligned with runtime behavior.
import { defineRouterConfig } from '@cookbook/router-cli';
import { pathConstraints } from './src/path-constraints';
export default defineRouterConfig({
routeFiles: 'src/**/*.route.{ts,tsx}',
pathConstraints,
});A route can then use the registered name:
{
id: 'posts.show',
path: '/posts/{slug:slug}',
}Use the same constraint object at runtime and during generation. Two implementations with the same name can validate differently and produce contracts that lie.
Keep custom constraints in a regular application module that both the router and the config can import.
Static configuration
Cookbook Router statically inspects configuration files. It does not execute arbitrary project code to discover route inputs.
Recommended:
const routeFiles = [
'src/**/*.route.tsx',
'features/**/*.route.tsx',
] as const;
export default defineRouterConfig({
routeFiles,
outDir: '.cookbook-router',
});Not supported:
export default defineRouterConfig({
routeFiles: discoverRouteFiles(),
});Configuration values such as routeFiles, outDir, and pathOptions must remain statically inspectable.
Static means predictable. Generation should not need to run the application to find the application.
Command-line overrides
Command options take precedence over matching configuration values:
cbr generate \
--config cookbook-router.config.ts \
--routes src/routes.ts \
--out-dir .generated/routerBe careful with --routes: when route files are supplied without --config, automatic config discovery is skipped. Configured pathOptions and pathConstraints will not be loaded.
Provide both options when overriding route inputs while keeping the remaining project configuration:
cbr generate \
--config cookbook-router.config.ts \
--routes src/routes.tsWhere this bites
Use a string for one routeFiles entry and an array for two or more. A single-item array is rejected.
Keep route discovery static. A TypeScript configuration file can contain TypeScript syntax, but that does not make computed route inputs statically inspectable.
Keep one authoritative configuration for the CLI and bundler plugin. Two configurations do not create flexibility. They create two definitions of the same build.