Feature-Sliced Design
Layers, slices, segments, the import rule and FSD with Next.
Updated
What Feature-Sliced Design is
Feature-Sliced Design (FSD) is an architecture methodology for the frontend, with strict rules about where you put code and who may import what. Code is split by how business-specific it is — from pages (very specific) down to utilities (generic).
Feature-Sliced Design in 1 minute
FSD organizes code on 3 levels: layers → slices → segments.
src/app/global setup: providers, styles, initviews/pages ("pages" in FSD; renamed so it doesn't clash with Next)widgets/big composed UI blocks: header, sidebar, playgroundfeatures/user actions with business value: run-exercise, add-to-cartentities/business concepts: user, lesson, product, progressshared/generic code, no business: ui kit, lib, api client, config
The golden rule
A layer may import only from the layers below it.
views→widgets→features→entities→sharedfeatures/run-exercisecan useentities/exercise✓entities/exercisecan NOT usefeatures/...✗- Two slices in the same layer don't import each other (
features/a✗→features/b). You combine them one level up (a widget/view).
Slices and segments
A slice = one concept (entities/lesson). Inside it, segments by technical role:
| Segment | Contains |
|---|---|
ui/ |
components |
model/ |
types, state, stores, logic hooks |
api/ |
requests, queries, server actions |
lib/ |
helpers specific to the slice |
config/ |
constants |
How we use it in this project
app/[locale]/[topic]/[lesson]/page.tsxjust composes the viewsrc/views/lesson/ui/lesson-view.tsxwidgets/playground/ui/playground.tsxfeatures/run-exercise/lib/run-js.tsentities/lesson/api/lesson-api.tsui/lesson-content.tsx
Our convention: no index.ts that re-exports — we import directly from the file, with descriptive kebab-case names. Official FSD recommends an index.ts as each slice's public API; we drop it for easier searching, a faster dev server and zero accidental circular dependencies. The cost: the discipline of "don't import internal details" is on you, not on the structure.
FSD + the Next App Router
- The root
app/folder is Next's routing — thin files that import fromviews. - FSD's
pageslayer → we call itviews(to avoid confusion with the Pages Router). - FSD's
applayer (providers, global CSS) can live inapp/layout.tsxor insrc/app.
Pros / cons
| Pros | Cons |
|---|---|
| clear rules: you know where to put anything | a learning curve, "is it an entity or a feature?" |
| no circular imports | too much for small projects |
| scales to big teams | many folder hops when navigating |
| deleting a feature = deleting a folder | needs a linter (Steiger) to stay clean |
Summary
- 6 layers, from specific to generic: app → views → widgets → features → entities → shared.
- Imports only go down; slices in the same layer don't import each other.
- Here: no barrels, descriptive kebab-case files, the root
app/only for routing.