Feature-Sliced Design - Another Option for Frontend Architecture
As frontend projects grow larger, folder structure becomes one of the first things you start worrying about. You begin with just components, pages, and utils, but before you know it, dozens of files pile up in your components folder and you keep asking yourself, "Where should I put this?"
While improving the Flowworks frontend, I faced this exact problem. While researching Atomic Design, which structures projects around UI components, I discovered a different approach: Feature-Sliced Design (FSD).
What is Feature-Sliced Design?
Feature-Sliced Design is an architectural methodology for structuring frontend applications. While Atomic Design divides code based on UI component size and complexity, FSD organizes code based on business domains and scope of influence.
The core goal is clear: keep the project understandable and stable even as business requirements constantly change. The aim is to create a structure where it's obvious where code should go when adding new features or modifying existing ones, while minimizing impact on other parts of the codebase.
Three Core Concepts
FSD structures projects using three concepts.
1. Layers
Code is separated into 7 layers based on scope of influence. Going from top to bottom, code becomes more general-purpose and reusable.
- app: Application entry point, global configuration (router, store, global styles)
- pages: Route-based pages (1:1 mapping with URLs)
- widgets: Independent UI blocks (large units like header, sidebar)
- features: User scenarios (functionality like login, add to cart, like)
- entities: Business entities (domain models like User, Product, Order)
- shared: Reusable utilities (UI kit, API client, helper functions)
2. Slices
Within each layer, code is separated by domain. For example, within the features layer, you'd have slices like auth, cart, and wishlist.
3. Segments
Within slices, code is separated by technical purpose.
- ui: React components
- model: State management (store, hooks)
- api: API call functions
- lib: Utilities specific to that slice
Folder Structure Example
In an actual project, it looks something like this:
src/
├── app/ # App entry point
│ ├── providers/ # Global Providers (Redux, Router)
│ ├── styles/ # Global styles
│ └── index.tsx
├── pages/ # Pages layer
│ ├── home/
│ ├── product-detail/
│ └── checkout/
├── widgets/ # Widgets layer
│ ├── header/
│ └── footer/
├── features/ # Features layer
│ ├── auth/ # Authentication feature
│ │ ├── ui/ # Login form component
│ │ ├── model/ # Auth state management
│ │ └── api/ # Login API
│ ├── add-to-cart/ # Add to cart feature
│ │ ├── ui/
│ │ └── model/
│ └── wishlist/
├── entities/ # Entities layer
│ ├── user/ # User domain
│ │ ├── ui/ # UI like UserCard
│ │ ├── model/ # User type definitions
│ │ └── api/ # User API
│ └── product/
└── shared/ # Shared layer
├── ui/ # Common components like Button, Input
├── api/ # axios instance
└── lib/ # Utility functions
Core Rule: Unidirectional Dependencies
The most important rule in FSD is the direction of dependencies.
-
Higher layers can only reference lower layers
pages→ can referencefeatures,entities,sharedfeatures→ can referenceentities,sharedentities→ can only referenceshared- Reverse direction is not allowed
-
Slices within the same layer cannot reference each other
features/auth→ cannot referencefeatures/cart- Each slice must be independent
Following these rules naturally achieves high cohesion and low coupling. You end up with a structure where modifying one feature doesn't affect others.
How is it Different from Atomic Design?
I discovered FSD while researching Atomic Design, and the two methodologies take quite different approaches.
Atomic Design divides UI components based on size and complexity. It builds up from Atoms (buttons, inputs) → Molecules (search bar) → Organisms (header) → Templates → Pages. It's intuitive for UI-focused projects or building design systems, with a focus on component reusability.
FSD divides based on business domain and scope of influence. The criteria are "how far does this code's impact reach" and "what business feature is this." It excels at managing dependencies between modules in applications with complex business logic.
One isn't better than the other—you choose based on your project's nature. If UI component reusability is important, Atomic Design might be better. If you need to manage complex business logic and features, FSD might be more suitable.
When Should You Use It?
FSD isn't right for every project.
Good fit:
- Complex projects or those requiring long-term maintenance
- Large teams with multiple people developing simultaneously
- Products where business logic changes frequently
Not a good fit:
- Prototypes that need to be built quickly
- Small projects or simple landing pages
- Teams unfamiliar with FSD concepts where learning cost is a concern
Currently, FSD is being used in projects dealing with complex business logic like banking, fintech, B2B SaaS, and e-commerce.
Who Actually Uses It?
While they may not explicitly mention FSD, some companies structure their projects using similar principles.
- Shopify - Domain-based layer separation in Polaris design system
- Atlassian - Feature-based structure in Jira, Confluence, Trello
- IBM - Business domain-centric structure in Carbon Design System
Wrapping Up
There's no single right answer for frontend architecture. Atomic Design, FSD, or even just splitting things into components and pages—it's all fine if it fits your project.
However, if your project is getting more complex and you keep asking "where should I put this?", it might be worth looking into methodologies like FSD. Even if you don't adopt it right away, knowing that this kind of structuring approach exists can help later.
I'm not sure yet if I'll apply FSD directly to Flowworks, but at least I've found a good reference for thinking about "how to structure a frontend."