Rules for frontend/src/. Structure & layers: architecture.md. Workflow: frontend-engineer.md. UI components: shadcn/SKILL.md.
- KISS — small modules; hooks for side effects; one router, one routes file.
- DRY — shared primitives in
components/uiandlib/; routes only incore/router/routes.ts. - SOLID — one concern per hook/page; domain layouts live in the owning feature.
- Isolation — no cross-feature imports (ESLint); compose in
core/router.
| Kind | Convention | Example |
|---|---|---|
| Routes | core/router/routes.ts |
ROUTES.workspace.overview(wid) |
| Feature barrel | index.ts |
features/inbox/index.ts |
| Page | *.page.tsx |
overview.page.tsx |
| Layout | features/<name>/layouts/ |
workspace-layout.tsx |
| Hook | hooks/use-*.hook.ts |
use-inbox-logs.hook.ts |
| API / types | *.api.ts, *.types.ts |
inbox.api.ts |
Use @/ for all imports — one alias covers everything:
| Target | Import as |
|---|---|
| shadcn / atoms | @/components/ui/<component> |
| lib, shared, core | @/lib/*, @/shared/*, @/core/* |
| Same feature | @/features/<feature>/… — not ../../ |
| Router (barrels) | @/features/<feature> |
Do not import another feature — not via @/features/<other>, not via relative paths into another slice. ESLint enforces this in eslint.config.js. Route composition stays in core/router only.
| Layer | Path | Rule |
|---|---|---|
| Atoms | components/ui/ |
shadcn primitives — add via npx shadcn@latest add in frontend/ |
| Feature UI | features/<name>/components/ |
Compose atoms; business-specific layout only |
| Pages | features/<name>/pages/ |
Orchestration; no raw HTML form controls |
Follow shadcn/SKILL.md: semantic tokens, flex+gap-*, DialogTitle, cn().
- Derive values during render — do not
useState+useEffectto mirror props or hook data. - Side effects in
useEffectonly; include cleanup for subscriptions/fetches; respect dependency arrays. - Colocate data fetching in hooks (
use-*.hook.ts); pages stay thin. - React Compiler–friendly code: no conditional hooks; stable keys in lists.
- Semantic tokens only (
bg-background,text-primary) — see shadcn rules. - Layout spacing:
flex+gap-*, notspace-x/space-y. - Buttons with icons:
data-icon="inline-start"orinline-end. - Dialogs require
DialogTitle(orsr-only).
From repo root: verification chain (/smell develop → make audit). See frontend/README.md for scripts.
Agent skills: typescript-react-reviewer + overlay; typescript-advanced-types + overlay; software-architecture + overlay.