Generating Code

Purpose and Scope

Code generation in Turborepo is for teams that want monorepo structure to stay consistent as the repository grows. A monorepo often starts with a small set of apps and shared packages, but over time teams need to add packages, modules, route handlers, UI components, and tool configuration repeatedly. Turborepo’s generator workflow gives those repetitive actions a project-aware command surface: it can create an empty workspace, copy an existing workspace as a template, or run custom generators defined inside the repository. The goal is not to replace framework CLIs; it is to make scaffolding fit the package graph, workspace layout, and conventions that already exist in the repo.

Sources: apps/docs/content/docs/guides/generating-code.mdx

The generator guide positions package splitting as a way to organize code, speed up tasks, and improve local development experience. In that model, generated code should not be treated as a one-off artifact. A generated package becomes part of the same build, test, lint, and dependency workflow as every other workspace. That is why the guide connects simple workspace creation, copying templates, and custom Plop-based generators under one task-oriented page. A team can start with turbo gen workspace and then graduate to repository-specific generators when naming, file layout, dependency choices, or task configuration need to be standardized.

Sources: apps/docs/content/docs/guides/generating-code.mdx

Relevant Source Files

  • apps/docs/content/docs/guides/generating-code.mdx — Defines the first-party guide for built-in workspace generation, copying packages, custom generator discovery, TypeScript generator support, and the turbo/generators/config.ts convention.
  • apps/docs/content/blog/free-vercel-remote-cache.mdx — Provides lifecycle context for how generated workspaces can later participate in Remote Caching on Vercel, other CI providers, and local machines.
  • apps/docs/content/blog/joining-vercel.mdx — Supplies project context for Turborepo’s Vercel-backed remote caching direction and the open-source CLI milestone.
  • apps/docs/content/docs/guides/ci-vendors/github-actions.mdx — Shows how repository scripts such as build and test map to turbo run in CI after generated workspaces are added.
  • apps/docs/content/docs/guides/ci-vendors/vercel.mdx — Documents Vercel’s zero-config Turborepo integration, useful when generated apps are deployed as Vercel projects.
  • apps/docs/content/docs/reference/turbo-codemod.mdx — Documents codemods and migrations, which complement generators by automating repetitive repository changes during upgrades.

Core Primitives

The first primitive is the workspace generator. A workspace is an app or package managed by the repository’s package manager and understood by Turborepo as part of the monorepo. To add a new empty app or package, run the built-in command from the repository context. The guide uses the short alias gen, and the reference evidence explains that turbo gen is an alias for turbo generate; the run subcommand is the default for custom generators, while workspace is the built-in subcommand for creating workspaces. Use this built-in path when the repository needs a new package shell and the team does not yet need custom prompts or file mutations.

Terminal
turbo gen workspace

Sources: apps/docs/content/docs/guides/generating-code.mdx

The second primitive is copying. Instead of starting empty, turbo gen workspace --copy lets an existing local workspace act as a template for a new app or package. The same workflow can also copy a remote workspace from a GitHub URL, including a branch and subdirectory when supplied in the URL. Copying is useful when the desired package is not just a folder with package.json, but a working pattern: shared config, source structure, scripts, and package metadata. The guide explicitly notes that remote sources require care because Turborepo cannot verify that the destination repository has every dependency or the same package manager assumptions.

Terminal
turbo gen workspace --copy
Terminal
turbo gen workspace --copy https://github.com/vercel/turborepo/tree/main/examples/with-tailwind/packages/tailwind-config

Sources: apps/docs/content/docs/guides/generating-code.mdx

The third primitive is a custom generator. Turborepo generators are built on Plop configuration, but the repository does not need to install plop as a dependency just to run them. Turborepo automatically detects generator configurations, makes them available from the command line, organizes them by workspace, runs them from the root of the workspace where they are defined, and allows invocation from anywhere in the repository. TypeScript generators are supported with zero configuration, and TypeScript authors can install @turbo/gen as a development dependency to access the PlopTypes type definitions used by generator configuration files.

Sources: apps/docs/content/docs/guides/generating-code.mdx

Custom Generator Layout and TypeScript

A custom generator normally starts with turbo gen. If no generator exists yet, Turborepo prompts the user to select an existing generator or create one. The guide also documents the manual configuration convention: place a configuration file at turbo/generators/config.ts or turbo/generators/config.js at the repository root, or place one inside any workspace. That workspace-aware placement matters because large monorepos often have different scaffolding needs for apps, documentation, design-system packages, and service packages. Keeping a generator near the workspace that owns the convention makes the generator easier to maintain and easier for Turborepo to present in context.

Terminal
turbo gen

Sources: apps/docs/content/docs/guides/generating-code.mdx

For TypeScript generator authors, the public @turbo/gen package supplies type definitions rather than a separate runtime concept. The official reference example imports PlopTypes from @turbo/gen and defines a default function that receives a PlopTypes.NodePlopAPI. Inside that function, authors call plop.setGenerator with a name, description, prompts, and actions. Turborepo also injects a turbo object into generator action answers. That object exposes path context such as the invocation directory, repository root, and containing workspace, plus parsed Turbo configuration records for discovered turbo.json and turbo.jsonc files. Those variables let a generator write files relative to the right place instead of hard-coding repository assumptions.

./turbo/generators/my-generator.ts
import type { PlopTypes } from "@turbo/gen";
 
export default function generator(plop: PlopTypes.NodePlopAPI): void {
  plop.setGenerator("Generator name", {
    description: "Generator description",
    prompts: [],
    actions: [],
  });
}

System-to-Code Mapping

Reader taskTurborepo surfaceSource-backed behavior
Add a new empty app or packageturbo gen workspaceCreates an empty workspace through the built-in generator path.
Create from an existing local templateturbo gen workspace --copyCopies a workspace already present in the monorepo.
Create from a remote templateturbo gen workspace --copy <GitHub URL>Copies a workspace from another repository, with manual dependency and package-manager validation left to the user.
Run repository-specific scaffoldingturbo gen or turbo generate run [generator-name]Discovers custom Plop configurations and exposes them from the command line.
Author TypeScript generators@turbo/gen typesProvides PlopTypes for generator configuration files and access to Turborepo-injected context.
Keep generated work fast in CIturbo run build, turbo run test, Remote CachingGenerated workspaces participate in the same task and cache workflow once their scripts and outputs are configured.

A generator is only the first step in the lifecycle of new code. After a workspace is created, it should be integrated into normal repository tasks. The GitHub Actions guide shows a root package.json where build and test scripts delegate to turbo run build and turbo run test, and a turbo.json where build declares outputs and a ^build dependency. That pattern is important for generated packages because new workspaces should not bypass the package graph. Once a generated workspace has scripts and task outputs aligned with the repo, Turborepo can schedule and cache it consistently in local development and CI.

Sources: apps/docs/content/docs/guides/ci-vendors/github-actions.mdx

Remote caching is a related concern rather than a generator feature, but it affects the practical outcome of generation. The Vercel Remote Cache blog describes Remote Caching as a distributed caching layer that helps developers and CI avoid doing the same work twice. It also documents local setup with npx turbo login and npx turbo link, and CI setup with TURBO_TOKEN and TURBO_TEAM for providers outside Vercel. The Vercel CI guide adds that Vercel’s Turborepo integration automatically understands monorepos and pre-configures projects for Vercel Remote Cache. Generated apps and packages benefit from that infrastructure once they join the normal Turborepo task graph.

Sources: apps/docs/content/blog/free-vercel-remote-cache.mdx, apps/docs/content/docs/guides/ci-vendors/vercel.mdx, apps/docs/content/blog/joining-vercel.mdx

Command and Option Reference

Use the workspace command when the user story is “create a package.” The relevant options from the public command reference are --name <name> for the new package.json name, --empty for an empty workspace, --copy <name>/<url> for local or GitHub-based templates, --destination <path> for placement, --type <app/package> for workspace kind, --root <path> for the repository root, and --show-all-dependencies when dependency filtering by workspace type should be disabled. The guide’s examples intentionally start with minimal commands because the interactive prompts can collect details when flags are omitted.

Use the custom-generator command when the user story is “apply repository-specific rules.” The public command shape is turbo gen run [generator-name], with turbo gen also serving as the interactive entry point. Important options are --args for directly passing prompt answers, --config <path> for choosing a generator configuration file, and --root <path> for invoking a generator against a repository root from another working directory. Those flags make custom generators useful both for developers running interactively and for scripted workflows that need deterministic answers.

Workflow Guidance and Next Steps

Start simple: use turbo gen workspace for a new empty package when the structure is still being decided, and use turbo gen workspace --copy when an existing package already encodes the right conventions. Prefer local copy sources when possible because the repository already shares package-manager and dependency assumptions with the template. If a remote GitHub source is useful, treat the generated result as a starting point and review package manager metadata, dependency declarations, scripts, and task outputs before committing. This mirrors the guide’s warning that Turborepo cannot validate every remote dependency or package-manager requirement for you.

When patterns repeat, promote them into a custom generator. Put the generator at the root if it expresses repository-wide conventions, or inside a workspace if it is owned by a specific area such as docs, web, or a shared UI package. Install @turbo/gen for TypeScript types, define prompts and actions with Plop’s API, and use Turborepo’s injected context to locate the root, current working directory, workspace, and discovered Turbo configs. After generation, update task configuration and CI expectations so the new files participate in turbo run and Remote Caching. For upgrade-time repetitive changes, use @turbo/codemod separately; codemods automate migrations such as schema URL updates, package-name additions, glob cleanup, and configuration key renames rather than scaffolding new product code.

Sources: apps/docs/content/docs/guides/generating-code.mdx, apps/docs/content/docs/reference/turbo-codemod.mdx