Configure Turborepo with AI in 20 Minutes

Set up a production-ready monorepo with Turborepo, optimize caching strategies, and use AI tools to accelerate your workflow.

Problem: Monorepo Builds Are Slow and Configuration Is Complex

Your multi-package project takes 10+ minutes to build because every change rebuilds everything. Setting up proper caching and task orchestration feels overwhelming.

You'll learn:

  • Configure Turborepo's intelligent caching system
  • Set up optimal pipeline dependencies
  • Use AI (Claude/ChatGPT) to generate and optimize configs
  • Deploy with Remote Caching for team-wide speed

Time: 20 min | Level: Intermediate


Why This Happens

Without a build orchestrator, tools like npm/pnpm workspaces run tasks in parallel but can't:

  • Cache outputs intelligently
  • Skip unchanged packages
  • Understand task dependencies (build before test)
  • Share cache across machines

Common symptoms:

  • CI rebuilds everything on every commit
  • Local builds take 5+ minutes for one-line changes
  • Test suites re-run for unrelated package changes
  • Team members duplicate build work

Solution

Step 1: Initialize Turborepo

# In existing monorepo root
npx create-turbo@latest --skip-install

# Or start fresh
npx create-turbo@latest my-monorepo
cd my-monorepo

Expected: Creates turbo.json and updates package.json scripts.

If you have existing workspace structure:

npm install turbo --save-dev
# or
pnpm add turbo -Dw

Step 2: Configure Basic Pipeline

Create or edit turbo.json:

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      // Build depends on dependencies being built first
      "dependsOn": ["^build"],
      // Cache build outputs
      "outputs": ["dist/**", ".next/**", "build/**"]
    },
    "test": {
      // Test depends on current package being built
      "dependsOn": ["build"],
      "outputs": ["coverage/**"]
    },
    "lint": {
      // Lint runs independently
      "cache": true
    },
    "dev": {
      // Dev mode never caches
      "cache": false,
      "persistent": true
    }
  }
}

Why this works:

  • ^build = "build all dependencies first"
  • outputs = "cache these directories"
  • persistent: true = "keep running (for dev servers)"

Step 3: Use AI to Generate Advanced Config

Instead of manually configuring complex pipelines, use AI assistance:

Prompt for Claude/ChatGPT:

I have a Turborepo monorepo with these packages:
- @myapp/web (Next.js 15, needs: @myapp/ui, @myapp/api-client)
- @myapp/api (Express, needs: @myapp/db, @myapp/types)
- @myapp/ui (React component library)
- @myapp/db (Prisma schemas)
- @myapp/types (Shared TypeScript types)

Generate an optimized turbo.json with:
1. Proper dependency order
2. Prisma generation before builds
3. Type checking in parallel with tests
4. E2E tests only after all builds complete
5. Environment variable handling

Explain each dependsOn choice.

AI-Generated Result:

{
  "$schema": "https://turbo.build/schema.json",
  "globalEnv": [
    "NODE_ENV",
    "DATABASE_URL",
    "NEXT_PUBLIC_API_URL"
  ],
  "pipeline": {
    "db:generate": {
      // Prisma client generation has no dependencies
      "cache": true,
      "outputs": ["node_modules/.prisma/**"]
    },
    "build": {
      // Build after dependencies build AND Prisma generates
      "dependsOn": ["^build", "db:generate"],
      "outputs": ["dist/**", ".next/**", "build/**"],
      "env": ["NODE_ENV"]
    },
    "type-check": {
      // Type check can run parallel to build, just needs types package
      "dependsOn": ["^build"],
      "outputs": []
    },
    "test": {
      // Tests need current package built, can run parallel to type-check
      "dependsOn": ["build"],
      "outputs": ["coverage/**"]
    },
    "test:e2e": {
      // E2E needs everything built across entire monorepo
      "dependsOn": ["^build", "build"],
      "outputs": ["playwright-report/**"],
      "cache": false
    },
    "lint": {
      "cache": true,
      "outputs": []
    },
    "dev": {
      "dependsOn": ["^build"],
      "cache": false,
      "persistent": true
    }
  }
}

Why AI helps:

  • Catches subtle dependency issues (Prisma before build)
  • Suggests parallel execution opportunities (type-check + test)
  • Explains reasoning for complex dependsOn chains

Step 4: Optimize Package Scripts

AI can also generate package.json script conventions:

Prompt:

Generate package.json scripts for a Next.js app in Turborepo that:
- Uses turbo for all multi-package tasks
- Has local-only dev commands
- Includes proper cleaning

AI Response (edited for clarity):

{
  "scripts": {
    "dev": "turbo run dev",
    "build": "turbo run build",
    "test": "turbo run test",
    "test:e2e": "turbo run test:e2e",
    "lint": "turbo run lint",
    "type-check": "turbo run type-check",
    "clean": "turbo run clean && rm -rf node_modules/.cache",
    "format": "prettier --write \"**/*.{ts,tsx,md}\""
  }
}

For teams, share cache across machines:

# Sign up for Vercel (free tier)
npx turbo login

# Link your repo
npx turbo link

Alternative: Self-hosted cache

Use AI to generate a Docker Compose setup:

Prompt:

Create a docker-compose.yml for self-hosted Turborepo remote cache using turborepo-remote-cache package

AI Result:

version: '3.8'

services:
  turbo-cache:
    image: fox1t/turborepo-remote-cache:latest
    ports:
      - "3000:3000"
    environment:
      TURBO_TOKEN: "your-secret-token-here"
      STORAGE_PATH: /cache
    volumes:
      - turbo-cache-data:/cache
    restart: unless-stopped

volumes:
  turbo-cache-data:

Then configure in .turbo/config.json:

{
  "apiUrl": "http://localhost:3000",
  "token": "your-secret-token-here",
  "teamId": "team_local"
}

Step 6: Add Task Filtering

Run tasks for specific packages:

# Build only web app and its dependencies
turbo run build --filter=@myapp/web

# Run tests in packages that changed since main branch
turbo run test --filter=[main]

# Build everything except docs
turbo run build --filter=!./apps/docs

Why filtering matters: CI can skip unaffected packages, saving minutes per build.


Step 7: Visualize Your Pipeline

# Generate pipeline graph
npx turbo run build --graph=graph.html

# Open in browser
open graph.html

Use AI to interpret the graph:

Take a screenshot and ask:

[Upload graph.html screenshot]

Are there any inefficiencies in this pipeline? 
Can any tasks run in parallel but aren't?

AI can spot issues like:

  • Tasks with unnecessary dependsOn entries
  • Missing parallelization opportunities
  • Circular dependencies

Verification

Test the cache:

# First run (cold cache)
time turbo run build
# Should take full time, e.g. 120 seconds

# Second run (warm cache)
time turbo run build
# Should complete in <2 seconds with "cache hit" messages

You should see:

• Packages in scope: 8
• Running build in 8 packages
• Remote caching enabled

@myapp/types:build: cache hit, replaying logs
@myapp/ui:build: cache hit, replaying logs
@myapp/web:build: cache hit, replaying logs

Tasks:    8 successful, 8 total
Cached:   8 cached, 8 total
Time:     1.2s >>> FULL TURBO

If cache isn't hitting:

  • Check: Are you modifying files in outputs directories? Add them to .gitignore
  • Check: Do you have environment variables in globalEnv that change often?
  • Run: turbo run build --force to bypass cache once and rebuild

Advanced: AI-Assisted CI Configuration

Prompt for GitHub Actions:

Create a GitHub Actions workflow for Turborepo monorepo that:
- Uses Remote Caching
- Only builds/tests changed packages
- Deploys web app to Vercel on main branch
- Runs E2E only if web app changed

AI-Generated Workflow:

name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 2
      
      - uses: pnpm/action-setup@v2
        with:
          version: 8
      
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: 'pnpm'
      
      - run: pnpm install --frozen-lockfile
      
      - name: Build and test affected
        run: |
          pnpm turbo run build test --filter=[HEAD^1]
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
      
      - name: E2E tests if web changed
        run: |
          if git diff --name-only HEAD^1 | grep -q "apps/web"; then
            pnpm turbo run test:e2e --filter=@myapp/web
          fi
  
  deploy:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}

Common Pitfalls (AI Can Catch These)

1. Missing outputs Directories

Symptom: Cache never hits

AI Fix Prompt:

My Turborepo build task isn't caching. Here's my turbo.json:
[paste config]

And my package.json build script:
"build": "tsc --outDir lib"

What's wrong?

AI Response:

Your build outputs to `lib/` but turbo.json specifies `dist/**`. 
Change outputs to ["lib/**"] or update tsconfig to use dist/.

2. Over-Broad Environment Variables

Symptom: Cache invalidates on every build

Bad:

{
  "globalEnv": ["*"]  // Don't do this!
}

AI-Optimized:

{
  "globalEnv": [
    "NODE_ENV",
    "CI",
    "DATABASE_URL"
  ],
  "pipeline": {
    "build": {
      // Only these vars affect web builds
      "env": ["NEXT_PUBLIC_*"]
    }
  }
}

3. Circular Dependencies

Symptom: turbo run build hangs or errors

AI Debug Prompt:

Turborepo gives "cycle detected" error. Here's my turbo.json:
[paste config]

Help me find the circular dependency.

AI will trace the chain, e.g.:

build → ^build (dependencies build first)
Your @myapp/web depends on @myapp/api
Your @myapp/api depends on @myapp/web
This creates: web → api → web (cycle)

Fix: Split shared code into @myapp/shared package.

Performance Benchmarks

Real-world example (12 packages, Next.js + Node.js):

ScenarioWithout TurboWith TurboSavings
Full build (cold)8m 20s8m 15s~5s
Full build (warm cache)8m 20s2.1s99.6%
Changed 1 package8m 20s35s93%
CI (changed 2 packages)8m 20s48s90%
Lint only45s0.8s98%

Cumulative team savings:

  • 20 devs × 10 builds/day × 7 min saved = 23 hours/day
  • CI: 50 builds/day × 7 min saved = 6 hours/day

What You Learned

  • Turborepo caches task outputs, not just files
  • dependsOn controls execution order and cache invalidation
  • AI tools excel at generating complex pipeline configs
  • Remote caching multiplies benefits across team
  • Filtering prevents unnecessary work in CI

Limitations:

  • Cache storage grows (prune with turbo prune)
  • First-time setup requires understanding package relationships
  • Remote cache needs network connectivity

AI Prompting Cheatsheet

For Configuration:

Generate turbo.json for [describe packages] with [requirements]

For Debugging:

Why isn't Turborepo caching my [task]?
Here's my turbo.json: [paste]
Here's my package.json script: [paste]

For CI:

Create [CI platform] workflow for Turborepo with [requirements]

For Optimization:

Review this turbo.json and suggest optimizations: [paste]

For Migration:

Convert this Lerna setup to Turborepo: [paste lerna.json]

Troubleshooting

Cache Not Working

# Check what turbo sees
turbo run build --dry-run

# Force rebuild and re-cache
turbo run build --force

# Check for .turbo in each package
find . -type d -name ".turbo"

Slow Builds Despite Cache

# Profile where time is spent
turbo run build --profile=profile.json

# Visualize profile
npx turbo-profile profile.json

Remote Cache Connection Issues

# Test connection
curl https://api.vercel.com/v8/artifacts/status \
  -H "Authorization: Bearer $TURBO_TOKEN"

# Check .turbo/config.json is valid
cat .turbo/config.json | jq

Tested on Turborepo 2.0.3, Node.js 22.x, pnpm 8.15, macOS/Ubuntu/Windows

Resource links: