Practical Patterns
Modular route files
Compose route declarations across files without losing parent validation or generated contracts.
Declare leaves near the feature
import { defineRoute } from '@cookbook/router';
export const usersRoute = defineRoute({
id: 'users',
path: '/users',
});
export const userDetailsRoute = defineRoute({
id: 'users.details',
parent: 'users',
path: ':userId(number)',
});Compose once
import { defineRouteTree } from '@cookbook/router';
import { usersRoute, userDetailsRoute } from './features/users/users.route';
export const routes = defineRouteTree([
usersRoute,
userDetailsRoute,
]);defineRouteTree() resolves parent, detects missing parents and cycles, rejects absolute child paths, and validates the composed tree. A declaration's order controls sibling order during composition.
Let the CLI discover files
import { defineRouterConfig } from '@cookbook/router-cli';
export default defineRouterConfig({
routeFiles: ['src/**/*.route.{ts,tsx}'],
});The generated routes.ts is conditional: it exists only when the extractor can compose route exports. Contracts and manifest generation do not require that runtime module.
Where this bites
A child declared inline under one route cannot also name a different parent. That is two ownership models for one node, and the validator rejects it.