Frontend Architecture Principles
Goals
- Keep the codebase predictable under team growth.
- Make extensions low-risk (new pages, new libs, new backends).
- Prevent mixed responsibilities across UI, data, and transport.
Stable boundaries
domains/*: feature UI and local feature logic.context/*: app-level shared state only (auth, theme, UI notices, system catalog).lib/services/*: HTTP transport wrappers and endpoint typing.query/*: key factories and cross-feature query conventions.
Page composition rule
- Pages orchestrate layout, guards, and UI interactions.
- Pages do not own fetch/retry/cache/invalidation logic directly.
- Data lifecycle lives in query/mutation hooks near the feature.
Scaling rule for new technology
- New client libraries are allowed only behind stable project boundaries.
- Keep the page API unchanged when replacing internal tooling.
- Example:
- switching HTTP client should only affect
lib/services/api/* - adding realtime sync should extend domain hooks first, then page usage
- switching HTTP client should only affect
Long-term maintainability rule
- Prefer explicit conventions over implicit shortcuts.
- Keep naming minimal and consistent (
index.tsx,queries/*,mutations/*,skeleton.tsx). - For multi-page shared features, prefer folder-per-page (
list/index.tsx,detail/index.tsx,create/index.tsx) and keep each page skeleton in its own folder. - Document any new cross-cutting pattern in
docs/frontend/*and, when architectural, in ADRs.