Feature-Sliced Design Architecture
Overview
Provides guidance for implementing Feature-Sliced Design (FSD v2.1) in Next.js applications. FSD organizes code into a layered hierarchy that prevents circular dependencies and promotes maintainability.
Next.js Customization (Only Difference from Official FSD)
This skill adapts FSD for Next.js App Router with one structural choice:
| Official FSD | This Skill (Next.js) |
|---|
| (routing, providers) + (page logic) | = Next.js routing + FSD App merged |
| layer | — page business logic |
| Separate routing layer | Next.js file-based routing (, ) |
holds both Next.js routing files (
,
, route groups) and FSD App layer concerns (providers, styles).
imports from
and renders. All other FSD rules (layers, slices, segments, public API, import rules) align with
FSD v2.1.
Reference files (load as needed):
- layers-and-segments.md — Layer definitions, slices (zero coupling, slice groups), segment patterns, migration
- public-api.md — Public API rules, @x cross-imports, shared/ui structure, circular imports
- code-smells.md — Desegmentation, generic folders anti-patterns
- examples.md — Full examples: layers, auth patterns, types, API requests
- react-query.md — React Query + FSD: Query Factory, pagination, QueryProvider
- monorepo.md — (Optional) Turborepo + FSD structure
Purpose
Feature-Sliced Design (FSD) is an architectural methodology for organizing frontend applications into a standardized, scalable structure. It provides clear separation of concerns through a layered hierarchy that prevents circular dependencies and promotes maintainability.
Why use FSD
- Scalability: Grows naturally as your application expands
- Maintainability: Clear boundaries make refactoring safer
- Team collaboration: Consistent structure enables parallel development
- Onboarding: New developers understand architecture quickly
Unified structure
Both Next.js App Router and FSD App layer live in
. Next.js recognizes
,
, etc. inside
, so all code stays under
without a root-level
folder, aligning with
FSD v2.1.
Custom 'views' layer
This skill uses 'views' instead of the standard FSD 'pages' layer. Page business logic goes in
; routing structure stays in
.
When to Use
Apply Feature-Sliced Design when:
- Starting new Next.js projects that require clear architectural boundaries
- Refactoring growing codebases that lack consistent structure
- Working with multi-developer teams needing standardized organization
- Building applications with complex business logic requiring separation of concerns
- Scaling applications where circular dependencies become problematic
- Creating enterprise applications with long-term maintenance requirements
- (Optional) Developing monorepo applications (Turborepo, etc.) — see monorepo.md
Core Principles (FSD v2.1)
Layer Hierarchy
FSD v2.1 organizes code into 7 layers (from most to least responsibility/dependency):
- app - App-wide matters (entrypoint, providers, global styles, router config)
- processes - Deprecated; move contents to and
- views - Page-level business logic (custom naming; standard FSD uses 'pages')
- widgets - Large self-sufficient UI blocks
- features - Main user interactions and business value
- entities - Business domain objects and models
- shared - Foundation (UI kit, API client, libs, config)
You don't have to use every layer — add only what brings value. Most projects use at least Shared, Pages (or views), and App.
FSD v2.1 pages-first: Start with pages/views; keep most logic there. Extract to features/entities only when code is reused across several pages.
Import rule: A module can only import from layers strictly below it.
┌─────────────────┐
│ app │ ← Can import from all layers below
├─────────────────┤
│ views │ ← Can import: widgets, features, entities, shared
├─────────────────┤
│ widgets │ ← Can import: features, entities, shared
├─────────────────┤
│ features │ ← Can import: entities, shared
├─────────────────┤
│ entities │ ← Can import: shared only
├─────────────────┤
│ shared │ ← Cannot import from any FSD layer
└─────────────────┘
'Views' vs 'Pages' Layer
- : Next.js routing + FSD App layer — , , route groups, providers, styles. imports from and renders.
- : Page business logic, component composition — View components, models, API calls. Composes widgets, features, entities.
Slices and Public API
Slices are domain-based partitions within layers (except app and shared). Examples:
,
,
,
.
- Zero coupling, high cohesion — Slices should be independent (no same-layer imports) and contain related code.
- Slice groups — Related slices can live in a folder, but no code sharing between them inside that folder.
- Each slice exports through . Use explicit exports — avoid . Consumers import from public API only.
See public-api.md for circular import rules, shared/ui structure, and @x cross-imports.
Segments
Segments group code by
purpose (why), not essence (what). Avoid
,
,
,
— use purpose-based names.
- ui/ - React components, visual elements
- model/ - Business logic, state management, TypeScript types
- api/ - API clients, data fetching, external integrations
- lib/ - One area of focus per library; document in README
- config/ - Configuration constants, feature flags
Shared layer segments: ,
,
,
,
,
Naming Conventions
| Target | Convention | Example |
|---|
| Folders, slices | kebab-case | , |
| Component files | kebab-case | , |
| Hook files | camelCase | , |
| Store files | camelCase | |
| Function/API collections | camelCase | , |
FSD with Next.js App Router
Next.js recognizes routing files inside
. All FSD layers live under
;
no root-level folder.
File organization:
my-nextjs-app/
├── src/
│ ├── app/ # Next.js routing + FSD App layer
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ ├── dashboard/page.tsx
│ │ ├── providers/
│ │ └── styles/
│ ├── views/
│ ├── widgets/
│ ├── features/
│ ├── entities/
│ └── shared/
│ ├── ui/
│ ├── lib/
│ └── api/
└── package.json
Routing pages import from views:
typescript
// src/app/dashboard/page.tsx
import { DashboardView } from '@/views/dashboard';
export default function DashboardPage() {
return <DashboardView />;
}
(Optional) Monorepo: See monorepo.md
For full directory structure and layer examples, see references.
Workflow
Step 1: Set Up Layer Directories
bash
mkdir -p src/{app,views,widgets,features,entities,shared}
mkdir -p src/app/{providers,styles,config}
mkdir -p src/shared/{ui,lib,api,config}
Step 2: Create First Entity
Start with entities (bottom layer). Define core business models in
and API in
. Export via
.
Step 3: Build Features Using Entities
Create features in
. Features import from entities and shared only.
Step 4: Compose Widgets from Features
Build composite widgets in
. Widgets can import from features, entities, shared.
Step 5: Assemble Views
Create page-level views in
. Views compose widgets, features, entities.
Step 6: Connect to App Router
Wire views to Next.js routing.
imports from
.
Import Rules
Allowed
- Layer importing from layer below
- Any layer importing from shared
- Slice importing different slice in lower layer
Forbidden
- Layer importing from same or higher layer
- Cross-slice imports within same layer
- Shared importing from FSD layers
Fixing Circular Dependencies
- Extract shared logic to lower layer (entities or shared)
- Create higher layer (widget) that imports both
- Review if slice should be split
Public API Enforcement
Always use
to control exports. Import from public API only:
typescript
// ✅ Correct
import { LoginForm } from '@/features/auth';
// ❌ Wrong (deep import)
import { LoginForm } from '@/features/auth/ui/LoginForm';
Migration Strategy (Bottom-up)
- Start with shared layer — extract UI, lib, API client
- Define entities — business domain objects
- Extract features — user interactions
- Build widgets — composite UI blocks
- Organize views — move page logic from page files
- Configure app layer — providers, styles
Migrate incrementally; run tests after each layer.
Best Practices
- No cross-slice imports within same layer
- Export through ; avoid ; use explicit exports
- shared/ui: per-component index for tree-shaking (see public-api.md)
- Avoid generic folders/files: , , — use domain names (see code-smells.md)
- Colocate tests next to implementation
- Keep slices focused; avoid "god slices"
- Name by domain: not
features/search-bar-component
- Use TypeScript strict mode
Troubleshooting
Import path issues: Configure path aliases in
— see Configuration below.
Build errors: Clear
, run
, restart dev server.
Configuration
TypeScript Path Aliases
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/app/*": ["src/app/*"],
"@/views/*": ["src/views/*"],
"@/widgets/*": ["src/widgets/*"],
"@/features/*": ["src/features/*"],
"@/entities/*": ["src/entities/*"],
"@/shared/*": ["src/shared/*"]
}
},
"include": ["src"]
}
ESLint (Optional)
javascript
'no-restricted-imports': ['error', {
patterns: [{
group: ['@/views/*', '@/widgets/*'],
message: 'Features cannot import from views or widgets',
}],
}]
Reference Files
Documentation Library
Load these resources as needed during development:
Core FSD Reference
- layers-and-segments.md — Layers, slices (zero coupling, slice groups), segments, @x cross-reference, migration (including v2.0→v2.1)
- public-api.md — Public API rules, @x cross-imports, circular imports, shared/ui tree-shaking, Steiger
- code-smells.md — Desegmentation, generic folder/file anti-patterns
Implementation Examples
- examples.md — Full examples: each layer, page layouts, auth, types/DTOs, API requests, domain-based files
Optional
- react-query.md — React Query + FSD: Query Factory, pagination, QueryProvider
- monorepo.md — Turborepo + FSD structure
External