Feature-Sliced Design with hard boundaries
Notes: Mention this is the second iteration. v1 was Feb 2026.
src/
├── app/ routing, layouts
├── shared/ reusable code
├── entities/ data models
├── pages/ route entry points
└── features/ user actions
Each layer only imports from below.
Notes: Walk through each directory top to bottom.
| Layer ↓ / Import → | Pages | Features | Entities | Shared |
|---|---|---|---|---|
| Pages | — | ✅ | ❌ | ✅ |
| Features | ❌ | ⚠️ | ✅ | ✅ |
| Entities | ❌ | ❌ | — | ✅ |
| Shared | ❌ | ❌ | ❌ | ✅ |
Notes: ⚠️ means hooks/types only — no UI components or api.ts imports between features
// shared/api/client.ts
// All HTTP goes through here. Never raw fetch().
Responsibilities:
ApiErrorOne client, one error model.
Notes: This is the most important file in the architecture. If this is clean, everything works.
3 core principles:
// Components display states, nothing else
<OrderList
orders={data}
loading={isLoading}
error={error}
/>
Notes: Components never import api.ts. Hooks handle all data and side effects.
| Layer | Test Type | Mock |
|---|---|---|
| Entities | Unit | Nothing |
| Features | Integration | HTTP (MSW) |
| Pages | Component / E2E | Feature hooks |
| Shared | Unit | Nothing |
Test at the right layer. Fast feedback loops.
Notes: Entities at 100% coverage. Features integration tests catch the most bugs.