Engineering

Turborepo Notes

✕

Turborepo Notes

✕

Project Creation Command

bunx create-turbo@latest
✕

Personal takeaways from exploring a real project, for future blog write-ups.

✕

1. What .npmrc Is

npm's runtime configuration file. Common uses: specifying registry mirrors, private-repo auth, workspace behavior, etc. In the current project .npmrc is empty, so npm falls back to global defaults.

✕

2. What turbo.json Does

It's not "install turbo and you must add turbo.json" — rather, a Turborepo project treats turbo.json as its core task-scheduling manifest. Without it, the turbo command has no idea what to do.

Top-Level Fields

FieldMeaning
$schemaEditor validation spec; wrong values get red squiggles
ui: "tui"Terminal UI style (Turborepo 2.0 dashboard look)
tasksCore section: defines every available task and its scheduling rules

Task Fields Explained

"build": {
  "dependsOn": ["^build"],           // ^ = dependency packages; build deps first, then self
  "inputs": ["$TURBO_DEFAULT$", ".env*"],  // rebuild only when these files change
  "outputs": [".next/**", "!.next/cache/**"] // build artifacts to cache; ! means exclude
}
FieldDescription
dependsOnTask dependency graph; ^ prefix means a dependency package's task
inputsSource file set that determines cache invalidation
outputsBuild artifact paths Turbo will cache; for non-Next projects use dist/** etc.
cache: falseDo not cache (useful for dev tasks that change in real time)
persistent: trueLong-running process; Turbo won't wait for it to finish

Why the dev Task Is Special

"dev": {
  "cache": false,
  "persistent": true
}
  • cache: false: during development code changes constantly, so caching is pointless
  • persistent: true: the process stays alive (e.g. next dev), so it can't be a prerequisite for other tasks
✕

3. Relationship Between workspaces and turbo.json

Key point: turbo does not define directory structure; it reuses npm workspaces' package discovery mechanism.

// root package.json
"workspaces": ["apps/*", "packages/*"]
  • npm workspaces answer "which packages exist"
  • turbo.json answers "how do we schedule scripts for those packages"

If you change workspaces to ["projects/*", "libs/*"], Turbo will look for packages there too. apps/ and packages/ are just community conventions.

✕

4. Task Names Are Script Names, Not Package Names

Task names in turbo.json (build, lint, check-types, dev) must match the keys in each sub-project's package.json scripts section.

What happens when you run turbo run <task>:

  1. Scan every package declared in workspaces
  2. Find packages that have a matching <task> script
  3. Topologically sort by dependsOn and execute in parallel
  4. Packages without the script are silently skipped

Verified Example

Packagedev scriptlint scriptcheck-types script
web✅✅✅
docs✅✅✅
@repo/ui❌✅✅
@repo/eslint-config❌❌❌
@repo/typescript-config❌❌❌

Conclusions:

  • turbo run dev → only starts web + docs
  • turbo run lint → web + docs + @repo/ui lint together
  • turbo run check-types → web + docs + @repo/ui type-check together
  • @repo/eslint-config has no scripts → ignored by every turbo task
✕

5. Startup Command and Log Output

Command

npm run dev
# equivalent to: turbo run dev

Sample Output

• Packages in scope: @repo/eslint-config, @repo/typescript-config, @repo/ui, docs, web
• Running dev in 5 packages
• Remote caching disabled

docs:dev: cache bypass, force executing a749f20663826bcc
web:dev: cache bypass, force executing 787819e83b8ceec9

docs:dev: > docs@0.1.0 dev
web:dev: > web@0.1.0 dev

web:dev: ▲ Next.js 16.2.0 (Turbopack)
docs:dev: ▲ Next.js 16.2.0 (Turbopack)

web:dev: - Local:   http://localhost:3000
web:dev: ✓ Ready in 221ms

docs:dev: - Local:   http://localhost:3001
docs:dev: ✓ Ready in 221ms

Note: "in scope" lists all 5 packages, but "Running dev" only executes docs and web because only they have a dev script.

✕

6. One-Sentence Summary

npm workspaces decide "which packages exist"; turbo.json decides "how to schedule scripts for those packages". Packages with matching scripts do the work; packages without them don't. outputs paths are fully customizable — set dist/** or .next/** according to your project type.

✕

Recorded: 2026-05-27
Project: my-turborepo (npm workspaces + Turborepo)
Package manager: npm@11.12.1
Turbo version: ^2.9.15