docs(frontend): the canonical table and the ui README name the module shape; adding a page is written down
CLAUDE.md gains the header-content, module-store and saved-views rows. docs/development.md says what a new page is and which tests hold it. components/ui/README.md names every file in the directory, and a contract test keeps it that way: seventeen had slipped in unlisted. copyItems' comment still claimed it was a feature file.
This commit is contained in:
@@ -36,6 +36,27 @@ The dev server also serves the **design lab** at `http://localhost:5173/design-l
|
||||
decisions and the chosen patterns, rendered with the app's real CSS. It never reaches a production build
|
||||
(see [`DESIGN.md`](DESIGN.md)).
|
||||
|
||||
## Adding a page
|
||||
|
||||
A frontend page is one folder, `frontend/src/modules/<id>/` (the layering is in
|
||||
[`CLAUDE.md`](../CLAUDE.md) § Architecture shape):
|
||||
|
||||
1. The page itself, default-exported, and anything only it uses. Header content (a search box, a toggle) the
|
||||
page renders into the floating header itself through `PageHeader`; the shell knows no page.
|
||||
2. `module.ts`: its `ModuleDef` (`lib/moduleDef.ts`): id, label keys, icon, an optional `gate`, the page as a
|
||||
`lazyWithPreload(() => import(…))`, and optionally a rail and a `Store`. Of its own folder it imports statically
|
||||
only its store (a `…Provider` / `…Store` file); the page and the rail load lazily.
|
||||
3. `index.ts`, the module's public face: the definition, and only what other folders must read (its store's
|
||||
hooks). Another folder reaches the module through this file or not at all.
|
||||
4. The id in `lib/urlState`'s `PAGES`, and the definition in `features/navigation/moduleRegistry.ts`, in
|
||||
nav-rail order. The rail, the palette, the `g` chords, the tab title and the root's stores all read from there.
|
||||
5. Its strings in both locales (`src/i18n/locales`).
|
||||
|
||||
What holds it: `moduleRegistry.contract.test.ts` (every id defined once, from its own folder, lazily),
|
||||
`moduleStores.contract.test.tsx` (no store reads another module), the `local/layers` lint rule (imports only go
|
||||
down, a module only through its face) and `chunkGuard` in the build (no lazy page on the boot path), plus the
|
||||
i18n parity test.
|
||||
|
||||
## The gate
|
||||
|
||||
A change is done when this is green, from the repo root:
|
||||
|
||||
Reference in New Issue
Block a user