Tech4 min read

Mastering Monorepos: Set Up with Turborepo

EP

Ezeikel Pemberton

March 30, 2026

Mechanical keyboard with colorful keys and whimsical animal figurines on desk.

Photo: Pexels

Hey there, fellow developer! If you're reading this, chances are you're intrigued by the concept of monorepos and want to know how to set up a robust, production-ready environment using Turborepo. You've come to the right place. In this post, I'll guide you through the process, sharing practical insights and actionable advice to make your monorepo journey as smooth as possible.

Why Monorepos?

Before diving into the setup, let's quickly touch on why you might want to use a monorepo in the first place. Monorepos can be a game-changer for teams of any size. They allow you to:

  • Centralize code: Manage multiple projects within a single repository.
  • Share code easily: Reuse libraries and utilities across projects without duplication.
  • Simplify dependencies: Handle all dependencies in one place, reducing version conflicts.
  • Streamline CI/CD: Run tests and deploys across all projects from a single pipeline.

Introduction to Turborepo

Turborepo is a modern build system that optimizes the development and build processes for monorepos. It leverages caching, parallel execution, and smart task scheduling to make builds lightning-fast. Let's get started with setting up a production-ready monorepo using Turborepo.

Step 1: Setting Up Your Monorepo

First things first, let's create your monorepo structure. We'll use Next.js with TypeScript for our projects, as it's a popular choice for web applications. Open your terminal and run the following commands:

mkdir my-monorepo
cd my-monorepo
npx create-turbo

The create-turbo command initializes a new monorepo with Turborepo. It creates a default setup with a few basic folders and configuration files. Now, let's structure our projects.

Step 2: Creating Projects Within the Monorepo

In a monorepo, you can have multiple projects. Let's set up a simple Next.js application and a shared library.

npx create-next-app apps/web
mkdir packages/ui

Setting Up the Next.js App

Navigate to the apps/web directory and open the package.json file. Add TypeScript support if it's not already there:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "tsc": "tsc --noEmit"
  },
  "dependencies": {
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
  "devDependencies": {
    "typescript": "latest",
    "@types/react": "latest",
    "@types/node": "latest"
  }
}

Creating a Shared Library

Move to the packages/ui folder and initialize a new library:

cd packages/ui
npm init -y

Now, create a simple Button component:

// packages/ui/src/Button.tsx
type ButtonProps = {
  label: string;
  onClick: () => void;
};

const Button = ({ label, onClick }: ButtonProps) => {
  return (
    <button onClick={onClick}>
      {label}
    </button>
  );
};

export default Button;

Don't forget to add TypeScript configuration here too. Create a tsconfig.json:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "jsx": "react-jsx",
    "declaration": true,
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

Step 3: Configuring Turborepo

With our basic structure in place, it's time to configure Turborepo. Open the turbo.json file at the root of your monorepo:

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

This configuration tells Turborepo to build each project, respecting dependencies, and cache the outputs for faster subsequent builds.

Step 4: Running and Testing

To test everything is working, return to the root directory of your monorepo and run:

npm run build

Turborepo should build all projects, leveraging caching for efficiency. You can also run the Next.js app:

cd apps/web
npm run dev

Visit http://localhost:3000 to see your application in action. Use the shared Button component from the ui package to verify that everything is interconnected.

Step 5: Advanced Configuration

Adding More Projects

To add more projects, simply create new folders under apps/ or packages/ and configure them similarly. Turborepo will handle the rest, ensuring dependencies are correctly managed.

Customizing the Build Process

Turborepo allows customization of the build pipeline. For instance, you can add custom scripts for testing or linting:

{
  "pipeline": {
    "build": {},
    "lint": {
      "dependsOn": ["^lint"]
    },
    "test": {
      "dependsOn": ["^test"]
    }
  }
}

Setting Up CI/CD

Integrating your monorepo with CI/CD is straightforward. Most CI/CD platforms, like GitHub Actions or GitLab CI, can execute Turborepo commands. Create a .github/workflows/ci.yml file for GitHub Actions as an example:

name: CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '16'
      - run: npm install
      - run: npm run build

Conclusion

And there you have it! You've set up a production-ready monorepo using Turborepo. With this powerful tool, you can manage multiple projects with ease, speeding up your development and build processes. Remember, the key to mastering monorepos is to keep your projects organized and configurations consistent.

Now, go forth and build amazing things! Whether you're an indie hacker or part of a larger team, Turborepo can help streamline your workflow and boost productivity. If you have any questions or run into issues, feel free to leave a comment below or reach out on Twitter. Happy hacking!

Tags

Tech

Share this article

Enjoyed this article?

Subscribe to get notified when I publish new posts about building products, coding, and indie hacking.

Subscribe to newsletter