new-route
Scaffolds a new route with its page component, page story, and optional i18n keys. Use this skill whenever the user asks to "create a route", "add a new page", "scaffold /dashboard", "wire up a new ro
SKILL.mdapps/web/.claude/skills/new-route/SKILL.md
GitHubnew-route
Workflow
- Confirm with the user: the name (kebab-case) as free text, then the group (
_publicor_session), whether the page loads service data (and which variant), and whether it needs--action, as oneAskUserQuestioncall of three questions, each with its recommended answer first and marked(Recommended). Pass--i18nwhenever the project has i18n (app/i18n.tsexists): without it the page carries literal text, which lint (i18next/no-literal-string) rejects. - Run from the repo root:
./.gaia/cli/gaia scaffold route <name> --group <group> [flags](the package comes from the registry, not the working directory). Flags:./.gaia/cli/gaia scaffold route --help. - Verify:
pnpm typecheckclean;pnpm devreaches the new route. - Before filling in the page, loader, or action by hand, read one or two existing routes with a similar shape and follow their pattern.
The scaffold writes app/routes/<group>.<name>.tsx plus app/pages/<name>/page.tsx (export <Name>Page) with tests/page.stories.tsx, a page story with a .test() that asserts the page structure (the story is the page's test, not a route test; wiki/decisions/Stories as Tests.md owns the doctrine). It refuses the reserved page-folder names tests, hooks, state, utils and assets. Layout rule: apps/web/.claude/rules/coding-guidelines-react.md.
Data variants
Bind a service with --data <server|client|query> --service <name> --shape <list|detail>. The rule for choosing a variant lives in apps/web/.claude/skills/react-code/SKILL.md; the default is server.
server: a serverloader, read withuseLoaderData.client: aclientLoaderand aHydrateFallback. The server renders only theHydrateFallback, so the first load shows its skeleton until the JavaScript loads and theclientLoaderresolves, and the document's title and meta tags are the ones theHydrateFallbackrenders, never values from the loaded data.query: aclientLoaderthat primes the Query cache and aHydrateFallback, with the page readinguseSuspenseQuery. Needs Query installed and the service'squeries.ts; the same first-load and metadata cost asclientapplies.
--shape list writes the list route, and --shape detail writes the detail route (app/pages/<name>/id/); run both with the same name for the pair. A scaffolded page story installs its MSW handlers in the meta's beforeEach and drives the route through stubs.reactRouter.