Official Feature-Sliced Design (FSD) v2.1 skill for applying the methodology to frontend projects. Use when the task involves organizing project structure with FSD layers, deciding where code belongs, defining public APIs and import boundaries, resolving cross-imports or evaluating the @x pattern, deciding whether logic should remain local or be extracted, migrating from FSD v2.0 or a non-FSD codebase, integrating FSD with frameworks, or implementing common patterns such as auth, API handling, Redux, and React Query within FSD.
Source: fsd.how | Strictness can be adjusted based on project scale and team context.
FSD v2.1 core principle: "Start simple, extract when needed."
Place code in pages/ first. Duplication across pages is acceptable and does
not automatically require extraction to a lower layer. Extract only when the
team agrees it is necessary.
Not all layers are required. Most projects can start with only shared/,
pages/, and app/. Add widgets/, features/, entities/ only when they
provide clear value. Do not create empty layer folders "just in case."
FSD uses 6 standardized layers with a strict top-down import direction:
app/ → App initialization, providers, routing
pages/ → Route-level composition, owns its own logic
widgets/ → Large composite UI blocks reused across multiple pages
features/ → Reusable user interactions (only when used in 2+ places)
entities/ → Reusable business domain models (only when used in 2+ places)
shared/ → Infrastructure with no business logic (UI kit, utils, API client)
Import rule: A module may only import from layers strictly below it. Cross-imports between slices on the same layer are forbidden.
// ✅ Allowed
import { Button } from "@/shared/ui/Button" // features → shared
import { useUser } from "@/entities/user" // pages → entities
// ❌ Violation
import { loginUser } from "@/features/auth" // entities → features
import { likePost } from "@/features/like-post" // features → features
Note: The processes/ layer is deprecated in v2.1. For migration
details, read references/migration-guide.md.
When writing new code, follow this tree:
Step 1 — Where is this code used?
pages/ slice.insignificant-slice).Step 2 — Is it reusable infrastructure with no business logic?
shared/ui/shared/lib/shared/api/ or shared/config/shared/auth/shared/api/Step 3 — Is it a complete user action reused in 2+ places, and does the team agree to extract it?
features/Step 4 — Is it a business domain model reused in 2+ places, and does the team agree to extract it?
entities/Step 5 — Is it app-wide configuration?
app/Golden Rule: When in doubt, keep it in pages/. Extract only when the
team agrees.
| Scenario | Single use | Multi-use (with team agreement) |
|---|---|---|
| User profile form | pages/profile/ui/ProfileForm.tsx | features/profile-form/ |
| Product card | pages/products/ui/ProductCard.tsx | entities/product/ui/ProductCard.tsx |
| Product data fetching | pages/product-detail/api/fetch-product.ts | entities/product/api/ |
| Auth token/session | shared/auth/ (always) | shared/auth/ (always) |
| Auth login form | pages/login/ui/LoginForm.tsx | features/auth/ |
| CRUD operations | shared/api/ (always) | shared/api/ (always) |
| Generic Card layout | — | shared/ui/Card/ |
| Modal manager | — | shared/ui/modal-manager/ |
| Modal content | pages/[page]/ui/SomeModal.tsx | — |
| Date formatting util | — | shared/lib/format-date.ts |
These rules are the foundation of FSD. Violations weaken the architecture. If you must break a rule, ensure it is an intentional design decision — document the reason and obtain team consensus.
app → pages → widgets → features → entities → shared.
Upward imports and cross-imports between slices on the same layer are
forbidden.
External consumers may only import from a slice's index.ts. Direct imports
of internal files are forbidden.
// ✅ Correct
import { LoginForm } from "@/features/auth"
// ❌ Violation — bypasses public API
import { LoginForm } from "@/features/auth/ui/LoginForm"
RSC / meta-framework exception: In environments with distinct client/server
boundaries, split entry points are permitted (index.client.ts,
index.server.ts). See references/framework-integration.md for details.
If two slices on the same layer need to share logic, follow the resolution order in Section 7. Do not create direct imports.
Name files after the business domain they represent, not their technical role.
Technical-role names like types.ts, utils.ts, helpers.ts mix unrelated
domains in a single file and reduce cohesion.
// ❌ Technical-role naming
model/types.ts ← Which types? User? Order? Mixed?
model/utils.ts
// ✅ Domain-based naming
model/user.ts ← User types + related logic
model/order.ts ← Order types + related logic
api/fetch-profile.ts ← Clear purpose
Shared contains only infrastructure: UI kit, utilities, API client setup,
route constants, assets. Business calculations, domain rules, and workflows
belong in entities/ or higher layers.
// ❌ Business logic in shared
// shared/lib/userHelpers.ts
export const calculateUserReputation = (user) => { ... };
// ✅ Move to the owning domain
// entities/user/lib/reputation.ts
export const calculateUserReputation = (user) => { ... };
Place code in pages/ first. Extract to lower layers only when truly needed.
When extraction seems worthwhile, discuss with the team — this is a design
decision that affects the whole project.
What stays in pages:
Evolution pattern: Start with everything in pages/profile/. When another
page needs the same user data and the team agrees, extract the shared model to
entities/user/. Keep page-specific API calls and UI in the page.
The entities layer is highly accessible — almost every other layer can import from it, so changes propagate widely.
shared/ + pages/ + app/ is valid FSD.
Thin-client apps rarely need entities.shared/api and logic in the current slice's model/ segment may
be sufficient.shared/api/. CRUD is infrastructure, not entities.shared/auth/ or shared/api/. Tokens and login
DTOs are auth-context-dependent and rarely reused outside authentication.// ✅ Valid minimal FSD project
src/
app/ ← Providers, routing
pages/ ← All page-level code
shared/ ← UI kit, utils, API client
// Add layers only when the team decides they are needed:
// + widgets/ ← UI blocks reused in 2+ pages
// + features/ ← User interactions reused in 2+ pages
// + entities/ ← Domain models reused in 2+ pages/features
Steiger is the official FSD linter. Key rules:
insignificant-slice: Suggests merging an entity/feature into its page
if only one page uses it.excessive-slicing: Suggests merging or grouping when a layer has too
many slices.npm install -D @feature-sliced/steiger
npx steiger src
shared/api/. Consider entities only
for complex transactional logic.user entity just for auth data. Tokens and login DTOs
belong in shared/auth/ or shared/api/.user-management/ into
auth/, profile-edit/, password-reset/).When two slices on the same layer need to share code, try these strategies in order. Always attempt earlier strategies first.
entities/. Keep UI in features/widgets.For detailed code examples of each strategy, read
references/cross-import-patterns.md.
Segments group code within a slice by technical purpose:
ui/ — UI components, styles, display-related codemodel/ — Data models, state stores, business logic, validationapi/ — Backend integration, request functions, API-specific typeslib/ — Internal utility functions for this sliceconfig/ — Configuration, feature flagsAlways use domain-based names that describe what the code is about:
model/user.ts ← User types + logic + store
model/order.ts ← Order types + logic + store
api/fetch-profile.ts ← Profile fetching
api/update-settings.ts ← Settings update
If a segment has only one domain concern, the filename may match the slice
name (e.g., features/auth/model/auth.ts).
Shared contains infrastructure with no business logic. It is organized by segments only (no slices). Segments within shared may import from each other.
Allowed in shared:
ui/ — UI kit (Button, Input, Modal, Card)lib/ — Utilities (formatDate, debounce, classnames)api/ — API client, route constants, CRUD helpers, base typesauth/ — Auth tokens, login utilities, session managementconfig/ — Environment variables, app settingsassets/ — Images, fonts, iconsShared may contain application-aware code (route constants, API endpoints, branding assets, common types). It must never contain business logic, feature-specific code, or entity-specific code.
app → pages → widgets → features → entities → sharedapp/ + pages/ + shared/user.ts, order.ts). Never technical-role
(types.ts, utils.ts).references/migration-guide.md.Read the following reference files only when the specific situation applies. Do not preload all references.
When creating, reviewing, or reorganizing folder and file structure for
FSD layers and slices (e.g., "set up project structure", "where does this
folder go"):
→ Read references/layer-structure.md
When resolving cross-import issues between slices on the same layer,
evaluating the @x pattern, or dealing with excessive entity coupling:
→ Read references/cross-import-patterns.md
When migrating from FSD v2.0 to v2.1, converting a non-FSD codebase to
FSD, or deprecating the processes layer:
→ Read references/migration-guide.md
When integrating FSD with a specific framework (Next.js, Nuxt, Vite,
CRA) or configuring path aliases:
→ Read references/framework-integration.md
When implementing concrete code patterns for authentication, API request
handling, type definitions, or state management (Redux, React Query) within
FSD structure:
→ Read references/practical-examples.md
Note: If you already loaded layer-structure.md in this conversation,
avoid loading this file simultaneously. Address structure first, then load
patterns in a follow-up step if needed.