Monorepo with Turborepo or Nx – Managing Multiple React Apps

Table of Contents

  1. Introduction
  2. What is a Monorepo?
  3. Benefits of Using a Monorepo for React Projects
  4. Turborepo vs Nx: Feature Comparison
  5. Setting Up a Monorepo with Turborepo
  6. Setting Up a Monorepo with Nx
  7. Organizing Apps, Packages, and Shared Libraries
  8. Using React, Tailwind, and Shared UI Components
  9. Build Caching, Task Pipelining, and Dependency Graphs
  10. Versioning and Publishing Packages
  11. Best Practices and Scaling Tips
  12. Conclusion

1. Introduction

As frontend projects grow more complex, developers often find themselves working on multiple apps (admin panel, landing page, dashboard) and packages (UI components, utilities, shared logic). Managing these in separate repositories becomes a nightmare. The solution? Monorepos.

This module covers the why, when, and how of using Turborepo or Nx to manage React apps and libraries within a single monorepo. You’ll learn how to share code, streamline builds, reduce duplication, and improve overall developer experience.


2. What is a Monorepo?

A monorepo (monolithic repository) is a single Git repository that contains multiple projects—apps, packages, libraries—all maintained together.

Examples:

  • apps/web, apps/admin, packages/ui, packages/utils

3. Benefits of Using a Monorepo for React Projects

  • Code Reuse: Share components, hooks, and utilities across apps.
  • Single Source of Truth: All code lives together, easier to coordinate.
  • Atomic Changes: Refactor across apps and packages in one commit.
  • Optimized Builds: Tools like Turborepo and Nx enable smart caching and parallel builds.
  • Developer Productivity: Better collaboration, fewer integration issues.

4. Turborepo vs Nx: Feature Comparison

FeatureTurborepoNx
EcosystemJavaScript-first (by Vercel)Full-stack (JS, TS, Go, etc.)
UIMinimal CLIPowerful GUI + CLI
Build CacheLocal + Remote (via Vercel)Local + Remote (via Nx Cloud)
Dependency GraphYesYes + Visual Graph
Community/SupportLightweight, focusedEnterprise-grade, extensible
Plugins for FrameworksManual setupBuilt-in React, Next.js, Nest

5. Setting Up a Monorepo with Turborepo

bashCopyEditnpx create-turbo@latest

Directory structure:

pgsqlCopyEditmy-turbo-repo/
├── apps/
│   ├── web/
│   └── admin/
├── packages/
│   ├── ui/
│   └── utils/
├── turbo.json

Install dependencies:

bashCopyEditcd my-turbo-repo
npm install

Example turbo.json:

jsonCopyEdit{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "lint": {},
    "test": {}
  }
}

Run all builds:

bashCopyEditnpx turbo run build

6. Setting Up a Monorepo with Nx

bashCopyEditnpx create-nx-workspace@latest

Choose:

  • Monorepo setup
  • Add React when prompted

You’ll get:

perlCopyEditmy-nx-workspace/
├── apps/
│   ├── web/
├── libs/
│   ├── ui/
│   └── utils/
├── nx.json

Add another app:

bashCopyEditnx generate @nrwl/react:application admin

Add a shared lib:

bashCopyEditnx generate @nrwl/react:library ui

7. Organizing Apps, Packages, and Shared Libraries

Common structure:

markdownCopyEditapps/
  - web/        → Main frontend app
  - admin/      → Admin dashboard
packages/
  - ui/         → Shared component library (Button, Modal)
  - utils/      → Shared functions, hooks
  - config/     → ESLint, Tailwind, Prettier

Importing shared packages:

tsxCopyEditimport { Button } from '@myorg/ui';

Use path aliases via tsconfig.json.


8. Using React, Tailwind, and Shared UI Components

In your shared ui package:

tsxCopyEditexport const Button = ({ children }) => (
  <button className="bg-blue-500 px-4 py-2 rounded text-white">{children}</button>
);

Configure Tailwind in each app to use shared styles.

Make a tailwind-config package and extend it:

jsCopyEdit// packages/tailwind-config/index.js
module.exports = {
  theme: { extend: {} },
  plugins: [],
};

In apps:

jsCopyEditconst config = require('@myorg/tailwind-config');
module.exports = {
  presets: [config],
};

9. Build Caching, Task Pipelining, and Dependency Graphs

  • Turborepo uses content-aware hashing and smart pipelines.
  • Nx offers task orchestration and a visual graph (nx graph).
  • Both support remote caching to reuse builds across CI pipelines.

Example:

bashCopyEditnpx turbo run build --filter=web

10. Versioning and Publishing Packages

Use Changesets:

bashCopyEditnpm install @changesets/cli
npx changeset init

Automated version bumps, changelogs, and package publishing.

Or manually:

bashCopyEditcd packages/ui
npm version patch
npm publish --access public

11. Best Practices and Scaling Tips

  • Use Yarn Workspaces or pnpm for faster dependency installs.
  • Keep packages atomic and loosely coupled.
  • Use Nx generators to automate common tasks.
  • Separate CI/CD workflows for apps and packages.
  • Integrate storybook in your UI library.
  • Enforce linting and formatting at root with shared configs.

12. Conclusion

Monorepos streamline the development of large-scale React applications, allowing code sharing, better organization, and more efficient builds. With Turborepo or Nx, you gain powerful build tools, dependency graphs, and dev tooling to take your productivity to the next level.

Choose Turborepo if you prefer minimal setup and Vercel integration. Go with Nx if you want rich tooling, extensibility, and support for multiple frameworks.