---
name: turborepo
description: >-
  Turborepo monorepo build system guidance. Triggers on turbo.json, task pipelines, dependsOn, caching, remote cache, distributed caching, cache misses, self-hosted cache, turbo CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure, and boundaries. Use when configuring tasks or pipelines, creating packages, setting up a monorepo, debugging cache, or optimizing CI builds.
metadata:
  version: 2.8.1
enabled: false
source: github:JuanJoseGonGi/skills
imported-from: github:JuanJoseGonGi/skills
---

# Turborepo Skill

Build system for JavaScript/TypeScript monorepos. Turborepo caches task outputs and runs tasks in parallel based on dependency graph.

## IMPORTANT: Package Tasks, Not Root Tasks

**DO NOT create Root Tasks. ALWAYS create package tasks.**

1. Add the script to each relevant package's `package.json`
2. Register the task in root `turbo.json`
3. Root `package.json` only delegates via `turbo run <task>`

```json
// DO THIS: Scripts in each package
// apps/web/package.json
{ "scripts": { "build": "next build", "lint": "eslint .", "test": "vitest" } }
// packages/ui/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
```

```json
// turbo.json - register tasks
{
  "tasks": {
    "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
    "lint": {},
    "test": { "dependsOn": ["build"] }
  }
}
```

```json
// Root package.json - ONLY delegates
{ "scripts": { "build": "turbo run build", "lint": "turbo run lint", "test": "turbo run test" } }
```

Root Tasks (`//#taskname`) are ONLY for tasks that truly cannot exist in packages (rare).

## Secondary Rule: `turbo run` vs `turbo`

**Always use `turbo run` when written into code** (package.json, CI, scripts). The shorthand `turbo <tasks>` is ONLY for one-off terminal commands.

## Quick Decision Trees

### "I need to configure a task"

```
├─ Define task dependencies → references/configuration/tasks.md
├─ Lint/check-types (parallel + caching) → Use Transit Nodes pattern (see below)
├─ Specify build outputs → references/configuration/tasks.md#outputs
├─ Handle environment variables → references/environment/RULE.md
├─ Set up dev/watch tasks → references/configuration/tasks.md#persistent
├─ Package-specific config → references/configuration/RULE.md#package-configurations
└─ Global settings (cacheDir, daemon) → references/configuration/global-options.md
```

### "My cache isn't working"

```
├─ Outputs not restored → Missing `outputs` key
├─ Unexpected cache misses → references/caching/gotchas.md
├─ Debug hash inputs → Use --summarize or --dry
├─ Skip cache entirely → Use --force or cache: false
├─ Remote cache not working → references/caching/remote-cache.md
├─ Self-hosted cache setup → references/caching/remote-cache.md#self-hosted
└─ Environment causing misses → references/environment/gotchas.md
```

### "I want to run only changed packages"

```
├─ Changed packages + dependents (RECOMMENDED) → turbo run build --affected
├─ Custom base branch → --affected --affected-base=origin/develop
├─ Manual git comparison → --filter=...[origin/main]
└─ All filter options → references/filtering/RULE.md
```

### "I want to filter packages"

```
├─ Only changed → --affected
├─ By name → --filter=web
├─ By directory → --filter=./apps/*
├─ Package + dependencies → --filter=web...
├─ Package + dependents → --filter=...web
└─ Complex combinations → references/filtering/patterns.md
```

### "Environment variables aren't working"

```
├─ Vars not available at runtime → Strict mode filtering (default)
├─ Cache hits with wrong env → Var not in `env` key
├─ .env changes not causing rebuilds → .env not in `inputs`
├─ CI variables missing → references/environment/gotchas.md
└─ Framework vars (NEXT_PUBLIC_*) → Auto-included via inference
```

### "I need to set up CI"

```
├─ GitHub Actions → references/ci/github-actions.md
├─ Vercel deployment → references/ci/vercel.md
├─ Remote cache in CI → references/caching/remote-cache.md
├─ Only build changed packages → --affected flag
└─ Skip unnecessary builds → turbo-ignore (references/cli/commands.md)
```

### "I want to watch for changes during development"

```
├─ Re-run tasks on change → turbo watch (references/watch/RULE.md)
├─ Dev servers with dependencies → Use `with` key
├─ Restart on dep change → Use `interruptible: true`
└─ Persistent dev tasks → Use `persistent: true`
```

### "I need to create/structure a package"

```
├─ Create an internal package → references/best-practices/packages.md
├─ Repository structure → references/best-practices/structure.md
├─ Dependency management → references/best-practices/dependencies.md
├─ JIT vs Compiled packages → references/best-practices/packages.md#compilation-strategies
└─ Sharing code between apps → references/best-practices/RULE.md#package-types
```

### "I want to enforce architectural boundaries"

```
├─ Check for violations → turbo boundaries
├─ Tag packages → references/boundaries/RULE.md#tags
├─ Restrict imports → references/boundaries/RULE.md#rule-types
└─ Prevent cross-package file imports → references/boundaries/RULE.md
```

## Critical Anti-Patterns

### Using `turbo` Shorthand in Code

```json
// WRONG                              // CORRECT
{ "scripts": { "build": "turbo build" } }  →  { "scripts": { "build": "turbo run build" } }
```

### Root Scripts Bypassing Turbo

Root `package.json` scripts MUST delegate to `turbo run`, not run tasks directly.

### Using `&&` to Chain Turbo Tasks

Don't chain turbo tasks with `&&`. Use `turbo run build && changeset publish` (non-turbo after turbo is OK).

### `prebuild` Scripts That Manually Build Dependencies

Scripts like `prebuild` that `cd` into other packages bypass Turborepo's dependency graph. Fix: declare workspace dependencies and use `dependsOn: ["^build"]`.

### Overly Broad `globalDependencies`

`globalDependencies` affects ALL tasks in ALL packages. Prefer task-level `inputs` when possible.

### Package-Specific Task Overrides in Root turbo.json

Use **Package Configurations** (`turbo.json` in each package with `"extends": ["//"]`) instead of cluttering root with `package#task` overrides.

### Using `../` in `inputs`

Use `$TURBO_ROOT$/shared-config.json` instead of `../../shared-config.json`.

### `^build` vs `build` Confusion

```json
{
  "tasks": {
    "build": { "dependsOn": ["^build"] },    // ^ = DEPENDENCIES (other packages)
    "test": { "dependsOn": ["build"] },       // no ^ = SAME PACKAGE
    "deploy": { "dependsOn": ["web#build"] }  // pkg#task = specific package
  }
}
```

### Missing `outputs` for File-Producing Tasks

Check what the task actually produces before flagging. Common outputs:
- Next.js: `[".next/**", "!.next/cache/**"]`
- Vite/Rollup: `["dist/**"]`
- tsc: `["dist/**"]` or custom `outDir`
- tsc with `incremental: true` + `--noEmit`: still produces `.tsbuildinfo`

### Environment Variables Not Hashed

```json
// WRONG: API_URL changes won't cause rebuilds
{ "tasks": { "build": { "outputs": ["dist/**"] } } }
// CORRECT: declare env vars
{ "tasks": { "build": { "outputs": ["dist/**"], "env": ["API_URL"] } } }
```

### `.env` Files Not in Inputs

Turbo does NOT load `.env` files — your framework does. But Turbo needs to know about changes:

```json
{ "tasks": { "build": { "inputs": ["$TURBO_DEFAULT$", ".env", ".env.*"] } } }
```

### Root `.env` File

A `.env` at repo root is an anti-pattern. Place `.env` files in packages that need them.

### NOT an Anti-Pattern: Large `env` Arrays

A large `env` array (even 50+) is fine — it means thorough environment tracking. Do not flag this.

### Shared Code in Apps

Extract shared code into `packages/` instead of keeping it in `apps/`.

### Too Many Root Dependencies

Root `package.json` should only have repo tools (`turbo`, `prettier`, etc.), not app dependencies.

## Common Task Configurations

### Standard Build Pipeline

```json
{
  "$schema": "https://turborepo.dev/schema.v2.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
    },
    "dev": { "cache": false, "persistent": true }
  }
}
```

### Transit Nodes for Parallel Tasks with Cache Invalidation

Tasks that can run in parallel but must invalidate cache when dependency source changes:

```json
{
  "tasks": {
    "transit": { "dependsOn": ["^transit"] },
    "my-task": { "dependsOn": ["transit"] }
  }
}
```

### With Environment Variables

```json
{
  "globalEnv": ["NODE_ENV"],
  "globalDependencies": [".env"],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"],
      "env": ["API_URL", "DATABASE_URL"]
    }
  }
}
```

### Dev Task with `^dev` Pattern (for `turbo watch`)

```json
// Root turbo.json
{ "tasks": { "dev": { "dependsOn": ["^dev"], "cache": false, "persistent": false } } }
// Apps override: apps/web/turbo.json
{ "extends": ["//"], "tasks": { "dev": { "persistent": true } } }
```

Run with `turbo watch dev`. Packages have one-shot `"dev": "tsc"` scripts; apps have persistent dev servers.

## Caching Overview

Turborepo's core: **never do the same work twice**. `fingerprint(inputs) → stored outputs`.

- **Local cache**: `.turbo/cache/` (add `.turbo` to `.gitignore`)
- **Remote cache**: Share across team/CI via Vercel or self-hosted server
- **Cache key**: determined by source files, `env` vars, `globalDependencies`, lockfile, task config, and dependent task hashes
- **Cached artifacts**: file outputs (from `outputs` key) + task logs (stdout/stderr)

### Quick Remote Cache Setup

```bash
npx turbo login && npx turbo link   # Local dev with Vercel
```

```bash
# CI: set TURBO_TOKEN and TURBO_TEAM environment variables
```

For self-hosted cache servers, see `references/caching/remote-cache.md#self-hosted`.

### Debugging Cache

```bash
turbo build --summarize      # JSON with all hash inputs
turbo build --dry=json       # See what would run without executing
turbo build --force          # Skip cache, re-execute all
turbo build --verbosity=2    # Verbose output with hashes
```

See `references/caching/gotchas.md` for the full debugging checklist.

## Reference Index

### Configuration

| File | Purpose |
|------|---------|
| [configuration/RULE.md](./references/configuration/RULE.md) | turbo.json overview, Package Configurations |
| [configuration/tasks.md](./references/configuration/tasks.md) | dependsOn, outputs, inputs, env, cache, persistent |
| [configuration/global-options.md](./references/configuration/global-options.md) | globalEnv, globalDependencies, cacheDir, daemon, envMode |
| [configuration/gotchas.md](./references/configuration/gotchas.md) | Common configuration mistakes |

### Caching

| File | Purpose |
|------|---------|
| [caching/RULE.md](./references/caching/RULE.md) | How caching works, hash inputs, local cache |
| [caching/remote-cache.md](./references/caching/remote-cache.md) | Vercel Remote Cache, self-hosted servers, artifact signing |
| [caching/gotchas.md](./references/caching/gotchas.md) | Debugging cache misses, --summarize, --dry |

### Environment Variables

| File | Purpose |
|------|---------|
| [environment/RULE.md](./references/environment/RULE.md) | env, globalEnv, passThroughEnv |
| [environment/modes.md](./references/environment/modes.md) | Strict vs Loose mode, framework inference |
| [environment/gotchas.md](./references/environment/gotchas.md) | .env files, CI issues |

### Filtering

| File | Purpose |
|------|---------|
| [filtering/RULE.md](./references/filtering/RULE.md) | --filter syntax overview |
| [filtering/patterns.md](./references/filtering/patterns.md) | Common filter patterns |

### CI/CD

| File | Purpose |
|------|---------|
| [ci/RULE.md](./references/ci/RULE.md) | General CI principles |
| [ci/github-actions.md](./references/ci/github-actions.md) | Complete GitHub Actions setup |
| [ci/vercel.md](./references/ci/vercel.md) | Vercel deployment, turbo-ignore |
| [ci/patterns.md](./references/ci/patterns.md) | --affected, caching strategies |

### CLI

| File | Purpose |
|------|---------|
| [cli/RULE.md](./references/cli/RULE.md) | turbo run basics |
| [cli/commands.md](./references/cli/commands.md) | turbo run flags, turbo-ignore, other commands |

### Best Practices

| File | Purpose |
|------|---------|
| [best-practices/RULE.md](./references/best-practices/RULE.md) | Monorepo best practices overview |
| [best-practices/structure.md](./references/best-practices/structure.md) | Repository structure, workspace config |
| [best-practices/packages.md](./references/best-practices/packages.md) | Internal packages, JIT vs Compiled, exports |
| [best-practices/dependencies.md](./references/best-practices/dependencies.md) | Dependency management, version sync |

### Watch Mode

| File | Purpose |
|------|---------|
| [watch/RULE.md](./references/watch/RULE.md) | turbo watch, interruptible tasks, dev workflows |

### Boundaries (Experimental)

| File | Purpose |
|------|---------|
| [boundaries/RULE.md](./references/boundaries/RULE.md) | Package isolation, tag-based dependency rules |

## Source Documentation

Based on official Turborepo docs at https://turborepo.dev/docs
