Skip to content

How the template works

template.json at the repository root defines which paths belong to which client stack:

Key Meaning
placeholder Placeholder project name used in the template (acme, Acme). Its uppercase form (ACME) is also replaced
defaultTheme Theme whose color ramps are stored in design/tokens/palette.json in the template repository
exclude Repository paths that stay in this template repository and are never embedded in the binary
common Paths included in every generated project
shared Named groups of paths shared by multiple targets, such as js-workspace
targets Per-stack definitions: id, title, stack, platforms, paths, requires (names of shared groups), outputs (kinds of generated token files the stack reads, matching the keys of design/build.json), format (the command that formats its code, if any), and run (commands shown after create)

Shared configuration files use conditional comment blocks to include lines only when specific targets are selected. A comment line @if <target ids> opens a block and @endif closes it:

[tools]
node = "26.13.1"
# @if web-react mobile-react-native
pnpm = "12.19.0"
# @endif
# @if desktop-gpui
rust = { version = "1.99.1", components = "rustfmt,clippy" }
# @endif
  • A conditional block is kept when any of its listed targets is selected. The marker lines themselves are stripped from the generated project.
  • Blocks can be nested and can wrap individual elements inside multi-line arrays.
  • Each marker must occupy its own full comment line. #, //, <!-- -->, and /* */ comment styles are supported; cli/src/markers.rs lists them.
  • @if template marks lines needed only in this repository, such as the cli workspace member and the CLI’s CI job. template is never selected in generated projects.
  • A marker that references an unknown target ID is an error, and the test suite renders every combination of targets so a typo cannot silently drop a block.

Within this repository, marker lines act as ordinary comments so every block remains active.

Files under cli/overlay are written over the generated project root with the same conditional block filtering and placeholder renaming. That is where the generated project’s README.md, AGENTS.md, and CLAUDE.md come from.

design/components.json is cut down like design/build.json: a project gets the components its clients have, each with the source files of those clients only.

Binary files (detected by a NUL byte within the first 8 KB) are copied verbatim.

  1. Add the client code, using the acme placeholder for names in both file contents and file paths.
  2. If the stack consumes a new format of generated token file, add an emitter to tools/design-build and an entry to design/build.json.
  3. Add a target entry to template.json: its paths, the shared groups it requires, the outputs it reads, and its run commands. Include a format command if the stack has a formatter enforced by mise run check.
  4. Wrap any stack-specific additions to the shared root files (mise.toml, .github/workflows/ci.yml, .gitignore, .gitattributes, Cargo.toml, pnpm-workspace.yaml, cli/overlay/README.md) in @if <id> blocks.
  5. List the stack’s components in design/components.json, with the source file and the symbol of each.
  6. Run cargo test -p xds. The tests fail if any repository file belongs to no target, shared group, common, or exclude; if any conditional marker is unbalanced or references an unknown target; or if mise.toml or Cargo.toml is not valid TOML for any combination of targets. Add the new target’s expectations to shared_files_are_valid_for_every_combination_of_targets in cli/src/tests.rs.

No Rust code changes are needed when adding a stack that follows this structure.