Muhammad Tabarak - Home
Frontend Architecture

npm Workspaces Monorepo: 3 Next.js Apps + Express API

How we engineered a unified npm workspaces monorepo coordinating 3 Next.js 16 micro-frontends with a shared Express API and unified TypeScript contracts.

Muhammad Tabarak
Muhammad TabarakFounder & Software Engineer
October 29, 2026
3 min read
npm Workspaces Monorepo: 3 Next.js Apps + Express API

Maintaining multiple decoupled repositories for a full-stack platform frequently leads to dependency drift, out-of-sync API interfaces, and fractured deployment scripts. For Curved Lab, our platform encompasses three dedicated frontends—the public marketing portal, the creator campaign dashboard, and the administrative console—backed by a high-throughput Node.js Express REST API.

Rather than maintaining four separate repositories with duplicated UI components and manually synchronized TypeScript interfaces, we consolidated the entire ecosystem into a high-performance npm workspaces monorepo. Here is how we structured the dependency graph, eliminated circular references, and streamlined development.

Monorepo Package Topology

A successful monorepo hinges on clean layer separation. Leaf packages (UI components, utility libraries, shared types) must never import from host applications. Host applications depend on shared packages, while shared packages remain completely agnostic of consumer runtime environments.

Package Topology
Rendering interactive flow...
Figure: Curved Lab Monorepo Dependency Graph

Eliminating Dependency Hoisting and Build Conflicts

One of the primary hazards in JavaScript monorepos is package hoisting ambiguity. When Next.js 16 and Express both depend on varying versions of packages like typescript or zod, npm's hoisting algorithm places one version at the root node_modules and leaves nested duplicates in individual packages.

In our architecture, we strictly centralized dev-tooling at the monorepo root (TypeScript, ESLint, Prettier, Tailwind CSS) while locking application-specific runtime dependencies within their respective workspace folders. Furthermore, we configured TypeScript Project References to compile internal packages in watch mode, enabling instant HMR across frontend apps whenever a shared type or UI component is modified.

Build Pipeline
Rendering interactive flow...
Figure: Unified Monorepo Build and Type-Checking Lifecycle

Key Architectural Wins

  • Single Source of Truth for Data Contracts: Modifying a campaign payout schema in @curvedlab/types immediately flags compile-time errors across both the Express backend route and the Next.js React forms.
  • Instant Local Development: Running a single command boots all micro-frontends and the backend API concurrently, with real-time hot module replacement across shared design systems.
  • Atomic Versioning: Feature pull requests encompass both backend schema migrations and frontend view updates in a single commit, eliminating out-of-sync API deployments.
Enjoyed this article?Add this site as a preferred source so Google surfaces my posts first — in Search & AI Mode.
Add as preferred source→