--- url: https://toolchain.deltabox.studio/guide/templates.md --- # Templates Templates scaffold projects, workspaces, applications, folders, tooling or pipelines. They can be **offline** (builtin, or a local `template.json` directory) or **online** (npm `@scope/create` manifests, git repos, and Vite+ templates). ## Kinds Every template declares a `kind`, used by `template:list --kind` and `create --kind`: | Kind | Produces | | ------------- | -------------------------------------- | | `project` | A single-package project. | | `workspace` | A package inside an existing monorepo. | | `application` | A runnable application package. | | `folder` | A bare folder of files. | | `tooling` | Toolchain config/pipeline files. | | `pipeline` | A CI/pipeline template. | ## List + create ```sh dbx template:list dbx template:list --kind application # filter by kind dbx template:list --online # also resolve npm/git sources dbx template:list --registry # only the .dbx/toolchain sources dbx template:list --json # machine-readable (used by the editor) dbx create --template project --name my-app --out ./my-app dbx create --kind folder --name scratch --out ./scratch dbx create --template mytpl --name acme --var port=4000 ``` With no `--template`, `create --kind ` picks the first matching template. An unlisted `--template` id is treated as a Vite+ template (`vp create `). On an interactive terminal, a bare `dbx create` (no `--template`/`--kind`/`--name`) prompts for the template, name and scope instead (Ctrl-C cancels). ## Builtin templates | id | Kind | Description | | ----------------------- | ------------- | ---------------------------------------------- | | `project` | `project` | A single-package TypeScript project. | | `application` | `application` | A runnable application package. | | `folder` | `folder` | A bare folder (a README). | | `monorepo` | `project` | A monorepo root (no example workspace). | | `monorepo-example` | `project` | A monorepo root + one example workspace. | | `workspace` | `workspace` | A workspace package into an existing monorepo. | | `vite-plus` | `project` | `vp create` (interactive or templated). | | `vite-plus-monorepo` | `project` | `vp create vite:monorepo`. | | `vite-plus-application` | `application` | `vp create vite:application`. | | `vite-plus-library` | `project` | `vp create vite:library`. | | `vite-plus-generator` | `project` | `vp create vite:generator` (monorepo only). | The offline builtins (`project`, `application`, `folder`, `monorepo`, `monorepo-example`, `workspace`) scaffold a generic, current project: a `dbx.config.ts` with `project` metadata, a runnable `src/index.ts` + smoke test, and a `package.json` that depends on the same `@deltabox/toolchain` version as the CLI. There is no Turbo (Vite Task replaces it). They ask for a **package manager** (default `yarn`) and write that manager's catalog file (see [Package catalogs](/guide/catalogs)). The `vite-plus*` builtins delegate to `vp create` and need network access. The root-oriented builtins (`project`, `application`, `monorepo`, `monorepo-example`) also write `.oxfmtrc.json` / `.oxlintrc.json` and opt in with `fmt.oxc` / `lint.oxc`. A nested `project`/`application` scaffold instead detects an ancestor that already owns those files and omits both the local files and the config opt-ins, so it inherits the root formatting/linting. `folder` and `workspace` never create Oxc files. Existing files are never overwritten unless `dbx create --force` is passed. ## Inputs (variables) A template can declare **inputs** — values prompted for (and substituted) when it is scaffolded. Declare them in `template.json`: ```json [template.json] { "variables": [ { "name": "name", "prompt": "Project name", "default": "app", "required": true }, { "name": "port", "prompt": "Dev port", "default": "4000" }, { "name": "includeDocker", "prompt": "Include a Dockerfile?", "options": ["yes", "no"] } ] } ``` * `name` — the token name (also `{{ name }}` in files). * `prompt` — the prompt text (defaults to the name). * `default` — the value used when nothing is entered. * `options` — a fixed list of choices: the value is picked from a select. * `required` — whether a value must be provided. Files and directory names may contain `{{ token }}` placeholders, resolved while copying: ``` src/{{name}}.ts -> src/acme.ts ``` The **same input pipeline** runs everywhere: * **CLI** — `dbx create` prompts for each input on an interactive terminal (the standard `name`/`scope` first, then the template's own inputs). Pass `--var key=value` (repeatable) to skip a prompt. * **Programmatic API** — `scaffoldTemplate(template, { cwd, tokens, variables })`. * **VS Code** — **Create from template…** prompts for each input (a quick pick when `options` is set). The builtin templates use the same pipeline (they declare `name`, `scope`, `packageManager` and `includeConfig` inputs). ## Actions After the files are written, a template can run **actions** — extra steps such as installing dependencies. Declare them in `template.json`: ```json [template.json] { "actions": [ { "id": "install", "prompt": "Install dependencies?", "builtin": "install" }, { "id": "setup", "prompt": "Run the setup script?", "module": "action.mjs" }, { "id": "post", "command": "node scripts/post-scaffold.mjs" } ] } ``` * `id` — the action id (also the `--action ` key). * `prompt` — the prompt text (defaults to `Run ?`). * `default` — whether it runs by default (**default false** — opt-in). * `builtin` — a built-in action. `install` runs ` install` in the output directory. * `module` — a JS module (relative to the template directory) whose default export is `async (ctx) => void`. The module is **not** copied to the output. The context is `{ cwd, templateDir, tokens, variables, packageManager, log }`. * `command` — a shell command run in the output directory. Actions run through the same pipeline everywhere: the CLI prompts (or takes `--action `, repeatable), the extension prompts, and the programmatic API passes `actions: string[]` to `scaffoldTemplate`. The builtin templates declare an opt-in **Install dependencies?** action (`builtin: 'install'`, off by default). ## Local templates A local template is a directory with a `template.json`. Turn any folder into one with `template:init` (and register it in one step with `--add`): ```sh dbx template:init ./templates/acme-service \ --kind application --name "Acme service" --var name --tag service --add ``` ```json [template.json] { "name": "Acme service", "description": "A service package", "kind": "application", "tags": ["service"], "variables": [{ "name": "name", "default": "service" }], "ignore": ["fixtures"] } ``` Register sources so they are picked up automatically: ```sh dbx template:add ./templates # local dir (auto-inits if needed) dbx template:add @acme/create # npm @scope/create dbx template:add git:https://github.com/acme/tpl.git dbx template:remove local:./templates # drop a source ``` `template:add` records them in `.dbx/toolchain/templates.json`; `template:remove` takes an id or a `type:locate` key. Sources can also be declared in the config: ```ts [dbx.config.ts] export default defineConfig({ toolchain: { templates: { sources: [ { type: 'local', locate: './templates', kind: 'application' }, { type: 'npm', locate: '@acme/create', online: true }, ], }, }, }); ``` ## Global templates A template registered with `template:init --add` or `template:add` is **also** stored in the global registry at `~/.dbx/toolchain/.registry/templates`, so it is available in every project (and in the VS Code extension). Pass `--no-global` to keep it project-only: ```sh dbx template:init ./templates/acme --kind application --name "Acme" --add # local + global dbx template:add ./templates --no-global # project only ``` Global templates are merged with the project's own; a project template wins on an id clash. The global search paths default to `~/.dbx/toolchain/.registry/templates`, and each path may be a directory or an `http(s)` **remote registry** (a JSON `{ "sources": [...] }` or an array of sources): ```sh dbx template:registry # list the resolved paths dbx template:registry --add ~/shared/templates --add https://acme.dev/templates.json dbx template:registry --set ~/shared/templates dbx template:registry --remove ~/shared/templates dbx template:registry --clear # reset to the default ``` The paths live in the CLI config `~/.dbx/toolchain/cli/config.json` (`registrySearchPaths`, a string or array) and are kept in sync with the VS Code setting `deltabox.registrySearchPaths`: the extension records the VS Code user dir in that config and mirrors setting changes into it, and the CLI writes the setting back when you change the paths. `vscodeDir` in the CLI config points at the VS Code user directory (the one containing `settings.json`). The project-scoped registries are stored in `.dbx/toolchain/registries.json` and default to `.dbx/toolchain/.registry/templates`. `dbx registry [--json]` lists the detected template/provider registries, and `dbx registry --add --scope global|project` (or `--remove`) manages them. A remote (`http(s)`) registry is a JSON `{ "sources": [...] }` / array of sources. The VS Code **Registries** view (below **Templates**) shows the Providers/Templates roots with **New registry…** / **Remove registry…** actions; remote registries open in the browser. `dbx template:remove --global ` removes a stored global template. ## Online templates Online sources are resolved with `--online` (or `dbx template:add`): * **npm** — a published create package whose `package.json` has a `createConfig.templates` (or `dbx.templates`) manifest. Scoped (`@acme/create`) and unscoped (`create-acme`, `acme-create`) packages are supported; individual templates are listed and created through `vp create`. The registry defaults to the project package manager's registry (`.yarnrc.yml` `npmRegistryServer`, `.npmrc` `registry`, ...). Override it per source with `--registry`: ```sh dbx template:add @acme/create dbx template:add create-acme dbx template:add create-acme --registry https://registry.example.com ``` * **git** — a repository (optionally with a `ref` and/or `subdir`) listed as a template and created through `vp create`: ```sh dbx template:add git:https://github.com/acme/templates --ref v1.2.0 --subdir apps/web ``` * **remote** — an `http(s)` JSON source registry (`{ sources }`, `{ templates }` or an array of sources). Its sources are merged into the registry; each is then loaded by its own type: ```sh dbx template:add remote:https://example.com/dbx-templates.json ``` * **Vite+** — set `create.defaultTemplate` in the `dbx.config.*`'s `vite` section (the full Vite+ config) to make a scope the default for `vp create`. Sources and registries can be restricted with host/path globs (checked for local paths and remote URLs, which also guards SSRF): ```ts [dbx.config.ts] toolchain: { registry: { templates: { allow: ['*.example.com', 'https://registry.example.com/**', '**/templates/**'], deny: ['*.internal.example.com'], }, }, } ``` ## VS Code The extension drives the same CLI: **From template…** runs `template:list --json` then `create`; **Add template…** runs `template:init --add` on a folder you pick and asks whether to add it to the **global** registry (yes by default); **Remove template…** runs `template:list --registry` then `template:remove`. The `deltabox.registrySearchPaths` setting controls the global search paths (see [Global templates](#global-templates)).