DEV Community

Cover image for Mastering Feature-Sliced Design: Lessons from Real Projects
Arjun
Arjun

Posted on

Mastering Feature-Sliced Design: Lessons from Real Projects

🌱 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/
Enter fullscreen mode Exit fullscreen mode

FSD promotes a more domain-driven structure:

src/
β”œβ”€β”€ app/
β”œβ”€β”€ pages/
β”œβ”€β”€ widgets/
β”œβ”€β”€ features/
β”œβ”€β”€ entities/
β”œβ”€β”€ shared/
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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:

  1. Separation of concerns β€” Teams could work on features/ and entities/ independently.
  2. High reusability β€” Shared logic (like authentication or API clients) became easier to reuse.
  3. Predictable structure β€” Every feature followed the same pattern, which made onboarding new developers faster.
  4. 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

  1. Introduce FSD gradually β€” don’t restructure everything at once.
  2. Keep feature definitions narrow β€” one clear responsibility per slice.
  3. Use lint rules like eslint-plugin-boundaries to enforce import order.
  4. Document the structure so the entire team follows the same conventions.
  5. 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


Top comments (0)