$npx -y skills add wshobson/agents --skill turborepo-cachingConfigure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.
| 1 | # Turborepo Caching |
| 2 | |
| 3 | Production patterns for Turborepo build optimization. |
| 4 | |
| 5 | ## When to Use This Skill |
| 6 | |
| 7 | - Setting up new Turborepo projects |
| 8 | - Configuring build pipelines |
| 9 | - Implementing remote caching |
| 10 | - Optimizing CI/CD performance |
| 11 | - Migrating from other monorepo tools |
| 12 | - Debugging cache misses |
| 13 | |
| 14 | ## Core Concepts |
| 15 | |
| 16 | ### 1. Turborepo Architecture |
| 17 | |
| 18 | ``` |
| 19 | Workspace Root/ |
| 20 | ├── apps/ |
| 21 | │ ├── web/ |
| 22 | │ │ └── package.json |
| 23 | │ └── docs/ |
| 24 | │ └── package.json |
| 25 | ├── packages/ |
| 26 | │ ├── ui/ |
| 27 | │ │ └── package.json |
| 28 | │ └── config/ |
| 29 | │ └── package.json |
| 30 | ├── turbo.json |
| 31 | └── package.json |
| 32 | ``` |
| 33 | |
| 34 | ### 2. Pipeline Concepts |
| 35 | |
| 36 | | Concept | Description | |
| 37 | | -------------- | -------------------------------- | |
| 38 | | **dependsOn** | Tasks that must complete first | |
| 39 | | **cache** | Whether to cache outputs | |
| 40 | | **outputs** | Files to cache | |
| 41 | | **inputs** | Files that affect cache key | |
| 42 | | **persistent** | Long-running tasks (dev servers) | |
| 43 | |
| 44 | ## Templates |
| 45 | |
| 46 | ### Template 1: turbo.json Configuration |
| 47 | |
| 48 | ```json |
| 49 | { |
| 50 | "$schema": "https://turbo.build/schema.json", |
| 51 | "globalDependencies": [".env", ".env.local"], |
| 52 | "globalEnv": ["NODE_ENV", "VERCEL_URL"], |
| 53 | "pipeline": { |
| 54 | "build": { |
| 55 | "dependsOn": ["^build"], |
| 56 | "outputs": ["dist/**", ".next/**", "!.next/cache/**"], |
| 57 | "env": ["API_URL", "NEXT_PUBLIC_*"] |
| 58 | }, |
| 59 | "test": { |
| 60 | "dependsOn": ["build"], |
| 61 | "outputs": ["coverage/**"], |
| 62 | "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"] |
| 63 | }, |
| 64 | "lint": { |
| 65 | "outputs": [], |
| 66 | "cache": true |
| 67 | }, |
| 68 | "typecheck": { |
| 69 | "dependsOn": ["^build"], |
| 70 | "outputs": [] |
| 71 | }, |
| 72 | "dev": { |
| 73 | "cache": false, |
| 74 | "persistent": true |
| 75 | }, |
| 76 | "clean": { |
| 77 | "cache": false |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | ``` |
| 82 | |
| 83 | ### Template 2: Package-Specific Pipeline |
| 84 | |
| 85 | ```json |
| 86 | // apps/web/turbo.json |
| 87 | { |
| 88 | "$schema": "https://turbo.build/schema.json", |
| 89 | "extends": ["//"], |
| 90 | "pipeline": { |
| 91 | "build": { |
| 92 | "outputs": [".next/**", "!.next/cache/**"], |
| 93 | "env": ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_ANALYTICS_ID"] |
| 94 | }, |
| 95 | "test": { |
| 96 | "outputs": ["coverage/**"], |
| 97 | "inputs": ["src/**", "tests/**", "jest.config.js"] |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | ``` |
| 102 | |
| 103 | ### Template 3: Remote Caching with Vercel |
| 104 | |
| 105 | ```bash |
| 106 | # Login to Vercel |
| 107 | npx turbo login |
| 108 | |
| 109 | # Link to Vercel project |
| 110 | npx turbo link |
| 111 | |
| 112 | # Run with remote cache |
| 113 | turbo build --remote-only |
| 114 | |
| 115 | # CI environment variables |
| 116 | TURBO_TOKEN=your-token |
| 117 | TURBO_TEAM=your-team |
| 118 | ``` |
| 119 | |
| 120 | ```yaml |
| 121 | # .github/workflows/ci.yml |
| 122 | name: CI |
| 123 | |
| 124 | on: |
| 125 | push: |
| 126 | branches: [main] |
| 127 | pull_request: |
| 128 | |
| 129 | env: |
| 130 | TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} |
| 131 | TURBO_TEAM: ${{ vars.TURBO_TEAM }} |
| 132 | |
| 133 | jobs: |
| 134 | build: |
| 135 | runs-on: ubuntu-latest |
| 136 | steps: |
| 137 | - uses: actions/checkout@v4 |
| 138 | |
| 139 | - uses: actions/setup-node@v4 |
| 140 | with: |
| 141 | node-version: 20 |
| 142 | cache: "npm" |
| 143 | |
| 144 | - name: Install dependencies |
| 145 | run: npm ci |
| 146 | |
| 147 | - name: Build |
| 148 | run: npx turbo build --filter='...[origin/main]' |
| 149 | |
| 150 | - name: Test |
| 151 | run: npx turbo test --filter='...[origin/main]' |
| 152 | ``` |
| 153 | |
| 154 | ### Template 4: Self-Hosted Remote Cache |
| 155 | |
| 156 | ```typescript |
| 157 | // Custom remote cache server (Express) |
| 158 | import express from "express"; |
| 159 | import { createReadStream, createWriteStream } from "fs"; |
| 160 | import { mkdir } from "fs/promises"; |
| 161 | import { join } from "path"; |
| 162 | |
| 163 | const app = express(); |
| 164 | const CACHE_DIR = "./cache"; |
| 165 | |
| 166 | // Get artifact |
| 167 | app.get("/v8/artifacts/:hash", async (req, res) => { |
| 168 | const { hash } = req.params; |
| 169 | const team = req.query.teamId || "default"; |
| 170 | const filePath = join(CACHE_DIR, team, hash); |
| 171 | |
| 172 | try { |
| 173 | const stream = createReadStream(filePath); |
| 174 | stream.pipe(res); |
| 175 | } catch { |
| 176 | res.status(404).send("Not found"); |
| 177 | } |
| 178 | }); |
| 179 | |
| 180 | // Put artifact |
| 181 | app.put("/v8/artifacts/:hash", async (req, res) => { |
| 182 | const { hash } = req.params; |
| 183 | const team = req.query.teamId || "default"; |
| 184 | const dir = join(CACHE_DIR, team); |
| 185 | const filePath = join(dir, hash); |
| 186 | |
| 187 | await mkdir(dir, { recursive: true }); |
| 188 | |
| 189 | const stream = createWriteStream(filePath); |
| 190 | req.pipe(stream); |
| 191 | |
| 192 | stream.on("finish", () => { |
| 193 | res.json({ |
| 194 | urls: [`${req.protocol}://${req.get("host")}/v8/artifacts/${hash}`], |
| 195 | }); |
| 196 | }); |
| 197 | }); |
| 198 | |
| 199 | // Check artifact exists |
| 200 | app.head("/v8/artifacts/:hash", async (req, res) => { |
| 201 | const { hash } = req.params; |
| 202 | const team = req.query.teamId || "default"; |
| 203 | const filePath = join(CACHE_DIR, team, hash); |
| 204 | |
| 205 | try { |
| 206 | await fs.access(filePath); |
| 207 | res.status(200).end(); |
| 208 | } catch { |
| 209 | res.status(404).end(); |
| 210 | } |
| 211 | }); |
| 212 | |
| 213 | app.listen(3000); |
| 214 | ``` |
| 215 | |
| 216 | ```json |
| 217 | // turbo.json for self-hosted cache |
| 218 | { |
| 219 | "remoteCache": { |
| 220 | "signature": false |
| 221 | } |
| 222 | } |
| 223 | ``` |
| 224 | |
| 225 | ```bash |
| 226 | # Use self-hosted cache |
| 227 | turbo build --api="http://localhost:3000" --token="my-token" --team="my-team" |
| 228 | ``` |
| 229 | |
| 230 | ### Template 5: Filtering and Scoping |
| 231 | |
| 232 | ```bash |
| 233 | # Build specific package |
| 234 | turbo build --fil |