# turbo.json Configuration Overview Configuration reference for Turborepo. Full docs: https://turborepo.dev/docs/reference/configuration ## File Location Root `turbo.json` lives at repo root, sibling to root `package.json`: ``` my-monorepo/ ├── turbo.json # Root configuration ├── package.json └── packages/ └── web/ ├── turbo.json # Package Configuration (optional) └── package.json ``` ## Always Prefer Package Tasks Over Root Tasks **Always use package tasks. Only use Root Tasks if you cannot succeed with package tasks.** Package tasks enable parallelization, individual caching, and filtering. Define scripts in each package's `package.json`: ```json // packages/web/package.json { "scripts": { "build": "next build", "lint": "eslint .", "test": "vitest", "typecheck": "tsc --noEmit" } } // packages/api/package.json { "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest", "typecheck": "tsc --noEmit" } } ``` ```json // Root package.json - delegates to turbo { "scripts": { "build": "turbo run build", "lint": "turbo run lint", "test": "turbo run test", "typecheck": "turbo run typecheck" } } ``` When you run `turbo run lint`, Turborepo finds all packages with a `lint` script and runs them **in parallel**. **Root Tasks are a fallback**, not the default. Only use them for tasks that truly cannot run per-package (e.g., repo-level CI scripts, workspace-wide config generation). ```json // AVOID: Task logic in root defeats parallelization { "scripts": { "lint": "eslint apps/web && eslint apps/api && eslint packages/ui" } } ``` ## Basic Structure ```json { "$schema": "https://turborepo.dev/schema.v2.json", "globalEnv": ["CI"], "globalDependencies": ["tsconfig.json"], "tasks": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "dev": { "cache": false, "persistent": true } } } ``` The `$schema` key enables IDE autocompletion and validation. ## Configuration Sections **Global options** - Settings affecting all tasks: - `globalEnv`, `globalDependencies`, `globalPassThroughEnv` - `cacheDir`, `daemon`, `envMode`, `ui`, `remoteCache` **Task definitions** - Per-task settings in `tasks` object: - `dependsOn`, `outputs`, `inputs`, `env` - `cache`, `persistent`, `interactive`, `outputLogs` ## Package Configurations Use `turbo.json` in individual packages to override root settings: ```json // packages/web/turbo.json { "extends": ["//"], "tasks": { "build": { "outputs": [".next/**", "!.next/cache/**"] } } } ``` The `"extends": ["//"]` is required - it references the root configuration. **When to use Package Configurations:** - Framework-specific outputs (Next.js, Vite, etc.) - Package-specific env vars - Different caching rules for specific packages - Keeping framework config close to the framework code ### Extending from Other Packages You can extend from config packages instead of just root: ```json // packages/web/turbo.json { "extends": ["//", "@repo/turbo-config"] } ``` ### Adding to Inherited Arrays with `$TURBO_EXTENDS$` By default, array fields in Package Configurations **replace** root values. Use `$TURBO_EXTENDS$` to **append** instead: ```json // Root turbo.json { "tasks": { "build": { "outputs": ["dist/**"] } } } ``` ```json // packages/web/turbo.json { "extends": ["//"], "tasks": { "build": { // Inherits "dist/**" from root, adds ".next/**" "outputs": ["$TURBO_EXTENDS$", ".next/**", "!.next/cache/**"] } } } ``` Without `$TURBO_EXTENDS$`, outputs would only be `[".next/**", "!.next/cache/**"]`. **Works with:** - `dependsOn` - `env` - `inputs` - `outputs` - `passThroughEnv` - `with` ### Excluding Tasks from Packages Use `extends: false` to exclude a task from a package: ```json // packages/ui/turbo.json { "extends": ["//"], "tasks": { "e2e": { "extends": false // UI package doesn't have e2e tests } } } ``` ## `turbo.jsonc` for Comments Use `turbo.jsonc` extension to add comments with IDE support: ```jsonc // turbo.jsonc { "tasks": { "build": { // Next.js outputs "outputs": [".next/**", "!.next/cache/**"] } } } ```