Skip to main content

Migrating from Turborepo

Turborepo orchestrates package.json scripts across a monorepo using a turbo.json pipeline. Nadle covers the same ground — task graph, caching, workspace scoping — but the task bodies and their wiring live in TypeScript instead of being split between turbo.json and each package's scripts.

How concepts map​

TurborepoNadle
turbo.json tasks (formerly pipeline)task definitions in nadle.config.ts
"dependsOn": ["^build"] (upstream packages)workspace dependencies + task dependsOn
"dependsOn": ["build"] (same package)dependsOn: ["build"] on the task
"outputs": ["dist/**"]outputs on the task
"inputs": ["src/**"]inputs on the task
turbo run buildnadle build
per-package scriptsper-workspace tasks.register
remote cachelocal cache (see the caching concept)

The ^ upstream-dependency operator has no single keyword in Nadle: a task depending on its workspace dependencies' build is expressed by declaring those workspace deps and depending on their tasks explicitly. Most pipelines only need same-package dependsOn, which is a direct rename.

Before / after​

turbo.json:

{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"test": { "dependsOn": ["build"] },
"lint": {}
}
}

nadle.config.ts (in the package that owns these tasks):

import { tasks, ExecTask, Inputs, Outputs } from "nadle";

tasks.register("build", {
run: ExecTask,
options: { command: "tsc" },
inputs: [Inputs.dirs("src")],
outputs: [Outputs.dirs("dist")]
});

tasks.register("test", {
run: ExecTask,
options: { command: "vitest", args: ["run"] },
dependsOn: ["build"]
});

tasks.register("lint", { run: ExecTask, options: { command: "eslint", args: ["."] } });

Run nadle build across the monorepo the same way turbo run build did; declared inputs/outputs make the result cacheable. See Monorepo for workspace setup.

Migrate with an agent​

Paste this prompt into your coding agent with turbo.json and the package scripts open:

Convert my Turborepo setup to Nadle.

For each entry in turbo.json's `tasks` (or `pipeline`):
- Create a tasks.register(name, { run: ExecTask, options: { command, args }, ... }) where the
command/args come from that package's matching package.json script.
- Map "dependsOn": ["x"] (same-package) to dependsOn: ["x"].
- Map "outputs" to outputs: [Outputs.dirs(...)] / Outputs.files(...) and "inputs" to inputs: [Inputs.dirs(...)].
- For "^build" (upstream) deps, leave a TODO comment noting it must be wired via workspace
dependencies, and ask me which workspaces the package depends on.
- Put each package's tasks in that package's nadle.config.ts.

Import only the tasks/helpers you use from "nadle". Show me the files you produced.