React Component Architecture
Composition, prop design, and folder layout for scalable React codebases.
# CLAUDE.md — React Component Architecture
## Component types
- **UI primitives** — `<Button>`, `<Input>`, `<Card>`. Live in `components/ui/`. No app logic, no data fetching, no domain knowledge.
- **Feature components** — `<UserProfile>`, `<InvoiceList>`. Live in `features/<feature>/`. Compose primitives, own feature logic.
- **Layouts / providers** — `<AppLayout>`, `<ThemeProvider>`. Live in `app/` or `layouts/`. Mostly structural.
## Composition over configuration
- Prefer `children` and slot props over a long flat prop list. A component with 12 props is asking to be split.
- Compound components for related parts: `<Tabs>`, `<Tabs.List>`, `<Tabs.Trigger>`, `<Tabs.Panel>`. Share state via context internal to the parent.
- Render-props or hook patterns when the consumer needs to customize the rendering, not just the data.
## Prop design
- Required props first, optional props after.
- Boolean props default to `false`. Naming is positive: `disabled`, not `notDisabled`.
- Avoid `is*` and `has*` for the same concept. Pick one (`isLoading`, `hasError`).
- Use discriminated unions for mutually exclusive prop sets (`{ kind: 'text', value } | { kind: 'icon', icon }`).
- Spread the rest of native HTML props (`...rest`) to the underlying element so consumers can pass `aria-*`, `data-*`, etc.
## Folder layout
```
features/users/
components/
UserCard.tsx
UserAvatar.tsx
hooks/
useUser.ts
api.ts
types.ts
index.ts // public surface
```
- The `index.ts` is the only file other features should import from.
- Internal files importing each other use relative paths; cross-feature imports use the alias (`@/features/users`).
## Splitting components
- Split when:
- The component has more than one reason to change
- State and rendering are independent
- You'd want to test parts separately
- Don't split for line count alone. A 200-line cohesive component beats four 50-line confused ones.
## Performance
- Memoize at boundaries (`React.memo`) only after profiling. Most components don't need it.
- Big lists: use `react-window` or `@tanstack/react-virtual` instead of rendering thousands of nodes.
- Code-split at the route level with `React.lazy`. Don't lazy-load primitives.
## Don't
- Don't pass JSX as a prop just to "skip" rendering — use `<Suspense>` or conditional rendering.
- Don't barrel-export every component from `components/index.ts`. Big barrels break tree-shaking.
- Don't put feature logic into UI primitives. The primitive should work in any app.
- Don't reach into a child's internals via refs. If you need to, redesign the API.
Other TypeScript templates
Next.js App Router + TypeScript Rules
Server Components, Server Actions, and TypeScript discipline for the Next.js App Router.
Next.js + Server Actions + Shadcn UI
Forms with Server Actions, Zod validation, and Shadcn UI primitives.
Next.js + Supabase Auth
Auth flows with Supabase SSR, cookies, and Row Level Security policies.
Next.js + Tailwind + Prisma Stack
Full-stack Next.js with Prisma ORM, Tailwind CSS, and Postgres.
Next.js SEO + Metadata Rules
Metadata API, sitemap, robots, OG images, and structured data done right.