ADR-0001: Feature vertical slices + folder-per-component
- Status: Accepted
- Date: 2026-05-30
- Scope: core (any React frontend)
Context
A React app sprawls when components, styles, hooks, and API calls are organized
by type (all hooks here, all styles there). We want each feature to be a
self-contained unit that’s easy to find, move, and reason about.
Decision
Feature-based vertical slices. Each page owns its full slice:
pages/[Page]/
├── index.tsx # calls use[Page]Page(), renders
├── styles.ts # all styled.X for the page
├── hooks/ # use[Page]Page (logic) + thin use[Resource] query/mutation hooks
├── schemas/ # Zod schemas, createSchema(t) for i18n-aware messages
└── components/[Name]/ # page-specific subcomponents (same folder pattern)
Folder-per-component. Every component/atom/subcomponent is a folder
<Name>/{index.tsx, styles.ts}:
index.tsxcontains zerostyled.Xdeclarations — all styling is in
styles.ts(tagged templates, so.tsnot.tsx).- Generic atoms live in
src/components/; page-specific ones under the page’s
components/. Pages don’t reach into other pages’ internals.
Supporting conventions:
- Forms: react-hook-form + Zod (
type FormData = z.infer<typeof schema>);
formattable values go through masks (0003-masked-inputs-for-formattable-values). - The API layer and server-state discipline have their own ADR:
0013-centralized-api-layer-and-server-state; styling/theming likewise:
0014-theme-tokens-not-hex.
The authoritative, current operational detail is in each app repo’s
CLAUDE.md; this ADR records the structural decision and its rationale.
Consequences
- A feature is one folder you can read top-to-bottom; deleting/moving it is clean.
index.tsx/styles.tsseparation keeps JSX readable and styling greppable.- More folders/files per feature, accepted for locality and consistency.
Related
- 0013-centralized-api-layer-and-server-state · 0014-theme-tokens-not-hex
- 0004-component-state-hygiene-and-shared-form-logic
- Design language + tokens: the app’s design-system skill
(0015-design-system-as-single-visual-source) + itssrc/styles/theme.ts