π± Intro
When building complex front-end applications, architecture decisions can make or break your projectβs scalability. One approach that truly stood out to me after working on multiple React projects is Feature-Sliced Design (FSD) β a structured way to organize frontend code by features and business logic, not by file types.
After implementing FSD in production, Iβve seen how it can bring incredible clarity to large projects β but also how it can slow down smaller ones. This post breaks down my experience, what worked, what didnβt, and where I believe FSD really shines.
π§© What Is Feature-Sliced Design?
Feature-Sliced Design (FSD) is an architectural methodology that helps organize frontend projects around business capabilities rather than UI elements or utilities.
Instead of grouping files like this:
src/
βββ components/
βββ hooks/
βββ pages/
FSD promotes a more domain-driven structure:
src/
βββ app/
βββ pages/
βββ widgets/
βββ features/
βββ entities/
βββ shared/
Each layer represents a specific level of abstraction:
- App β Application-level setup (providers, routing, config).
 - Pages β Route-level compositions.
 - Widgets β Complex UI blocks.
 - Features β Units of user-facing functionality.
 - Entities β Core domain logic or data models.
 - Shared β Common utilities and base components.
 
This hierarchy enforces direction β higher layers (like pages) can depend on lower layers (like entities), but not the other way around.
βοΈ How It Works in Practice
Letβs imagine a Fintech Dashboard β something similar to Revolut or Wise.
Using FSD, you might structure it like this:
src/
 ββ app/
 β   ββ providers/
 β       ββ AuthProvider.tsx
 β       ββ ThemeProvider.tsx
 ββ pages/
 β   ββ home/
 β   ββ transactions/
 β   ββ payments/
 ββ widgets/
 β   ββ account-summary/
 β   ββ transaction-table/
 ββ features/
 β   ββ filter-transactions/
 β   ββ make-payment/
 β   ββ export-statement/
 ββ entities/
 β   ββ user/
 β   ββ transaction/
 ββ shared/
     ββ ui/
     ββ api/
     ββ lib/
Hereβs what each layer does:
- app/ β Setup code like providers and routing.
 - pages/ β Entry points connected to routes.
 - widgets/ β Complex UI blocks composed of multiple features or entities.
 - features/ β User-driven actions (e.g., filtering, exporting).
 - entities/ β Domain models like User, Account, or Transaction.
 - shared/ β Reusable utilities, UI components, and constants.
 
π‘ My Experience Using FSD
In one of my recent React + Next.js projects, I used FSD to manage a financial transaction portal with multiple teams contributing to different modules.
Before adopting FSD, we constantly ran into issues like:
- Unclear ownership of modules
 - Duplicated logic across pages
 - Difficulty in reusing UI components
 
After restructuring the app with FSD, we saw these key benefits:
- 
Separation of concerns β Teams could work on 
features/andentities/independently. - High reusability β Shared logic (like authentication or API clients) became easier to reuse.
 - Predictable structure β Every feature followed the same pattern, which made onboarding new developers faster.
 - 
Clean imports β With proper path aliases, we avoided deep relative imports like 
../../../Button. 
A small but meaningful example:
We moved the βDownload Reportβ feature into its own folder (features/download-report) β complete with its UI button with dropdown options, generating PDF logic, and hooks. Later, we reused that same feature on many listing pages without duplication. That kind of modularity simply wasnβt possible before.
π Why Itβs Great for Large Projects
When your project spans multiple domains or teams, FSD helps in three big ways:
1. Scalability
Each feature is self-contained β you can add or remove functionality without refactoring other parts.
2. Parallel Development
Different teams can safely work in parallel, since features are isolated.
3. Easy Abstraction
You can extract features or entities into a component library later with minimal changes.
For example, a shared auth module or a user entity can later be moved into an internal library for reuse across microfrontends.
π Read more: Understanding Layers in FSD
π‘ Why I Found FSD Valuable in Large Projects
In one of my SaaS projects, we had multiple independent modules β Dashboard, Listing Page (with features like filtering and exporting), and Reports. Each module had its own logic, UI, and state management.
By applying FSD, each feature became a self-contained slice with clear boundaries. This had huge benefits:
- Developers could work independently without touching unrelated parts of the codebase.
 - Each feature could later be published as a standalone package or reused in another project.
 - Refactoring became predictable β no mysterious side effects.
 
The level of reusability and modularity we achieved was far better than any flat folder structure could offer.
βοΈ Challenges and Real-World Lessons
While FSD works beautifully at scale, applying it effectively requires discipline and experience. Here are some lessons I learned along the way:
1. Defining Feature Boundaries Is Hard
The hardest part of FSD is figuring out where one feature ends and another begins. In theory, features should represent user actions like βlog inβ or βview reports.β But in practice, things like authentication, permissions, or logging donβt fit neatly into any one feature.
I learned to treat such cross-cutting concerns as infrastructure or shared context, not as individual features. This helps keep feature slices clean and focused.
2. Over-Slicing Early Is a Trap
Early in my FSD journey, I tried slicing everything β even small UI interactions. That quickly became unmanageable. Many slices were too small to justify their existence, and navigating the file tree became a chore.
The better approach was to start simple and slice only when the need arises. When a piece of functionality grows enough to deserve isolation, thatβs when it becomes a feature.
3. Grouping Related Features Works β With Caution
For larger domains like Authentication, grouping sub-features (login, signup, reset password) made sense. But I also learned that grouping can blur boundaries if not carefully managed.
When a sub-feature grows beyond its parent domain, itβs often better to promote it into a standalone feature. Trying to over-organize can sometimes cause more friction than it solves.
4. The βSharedβ Layer Can Become a Dumping Ground
Every team Iβve worked with eventually faces the same issue: the shared/ folder starts to collect everything. Itβs easy to fall into the trap of putting unrelated utilities or UI elements there.  
To avoid this, I adopted a simple rule β if itβs not reusable in multiple independent contexts, it doesnβt belong in shared/. That discipline helps prevent the βshared messβ problem that many large teams encounter.
5. Itβs Not for Every Project Size
For small apps or prototypes, FSD is simply too much. Setting up layers and enforcing boundaries adds unnecessary boilerplate when your app only has a few pages.
I now apply FSD only when I know the project will grow β typically when working on SaaS platforms, dashboards, or modular systems. For smaller side projects, a simpler structure like Bulletproof React works perfectly.
π§ Practical Tips That Worked for Me
- Introduce FSD gradually β donβt restructure everything at once.
 - Keep feature definitions narrow β one clear responsibility per slice.
 - Use lint rules like eslint-plugin-boundaries to enforce import order.
 - Document the structure so the entire team follows the same conventions.
 - Keep shared minimal β it should serve the app, not own it.
 
π My Takeaway
Feature-Sliced Design is one of the most effective architectures Iβve used for scaling front-end projects. It encourages separation of concerns, reusability, and parallel development. However, itβs not a silver bullet.
In my experience:
β
 It excels in large, domain-heavy projects.
β It feels heavy-handed and slow in smaller applications.  
If you expect your app to grow, FSD gives you a foundation thatβs easy to maintain, scale, and evolve. If not, you might just be over-engineering the problem.
π Further Reading
- Official documentation: https://feature-sliced.design/
 - ESLint boundaries plugin: https://www.npmjs.com/package/eslint-plugin-boundaries
 
              
    
Top comments (0)