Why are we talking about architecture again?

This title could be clearer and more informative.Try out Clickbait Shieldfor free (5 uses left this month).

Frontend developers often assume a framework like React, Vue, or Angular automatically solves code organization, but frameworks are UI rendering tools that shouldn't own business logic, routing, or domain rules. Mixing business logic into components leads to tight coupling, circular dependencies, refactoring pain, and slow tests. The piece surveys existing solutions—Feature-Sliced Design and Clean/Hexagonal Architecture—weighing their pros and cons, then proposes a hybrid: Tactical DDD combined with an Nx monorepo. Each business domain is split into contracts, core, ui, and features libraries with strict import boundaries enforced via Nx's module-boundary linter rules and custom generators. A Composition Root with a DI container (InversifyJS) wires dependencies at the app entry point. Benefits claimed include isolated unit testing of business logic, faster incremental builds via Nx caching, protection against framework lock-in, and enabling parallel team work across domains.

17m read timeFrom itnext.io
Post cover image
Table of contents
The Framework IllusionScaling Problems

Questions this post answers

What are the drawbacks of Feature-Sliced Design (FSD) for frontend architecture?

Feature-Sliced Design still puts the UI front and center, since it doesn't force isolating the application core from the rendering framework, letting developers drag state libraries like Zustand, Vuex, or RxJS directly into slices and lock the domain to the framework. It also restricts same-layer slices from importing each other, forcing cross-domain logic up into bloated widgets or pages layers. Teams weighing FSD against other structures can compare tradeoffs like these through daily.dev before committing to a frontend architecture.

How do you structure a business domain using Tactical DDD in an Nx monorepo for a frontend app?

Each business domain splits into four Nx libraries: contracts (pure TypeScript types with zero dependencies), core (pure business logic divided into domain, application, and infrastructure sublayers), ui (dumb presentational components), and features (orchestrator components connecting core to ui). Only contracts and core are mandatory; a domain like permissions can skip ui and features entirely if it has no interface. Frontend engineers designing scalable domain boundaries can track approaches like this Tactical DDD plus Nx setup via daily.dev.

How can you prevent developers from importing UI components into business logic in a monorepo?

Use the Nx ESLint rule @nx/enforce-module-boundaries to tag libraries with scope tags (domain:auth, domain:payments) and layer tags (type:contracts, type:core, type:ui, type:features), then define a permission matrix so type:core can only import type:contracts and shared libraries. Violations get flagged by the linter and block the CI pipeline's pull request. Developers enforcing architectural boundaries in a monorepo can find practical linter setups like this on daily.dev.

52.3K Impressions3 Comments