Builder CLI Commands Since 3.5.0
The Site Builder provides four CLI commands: scaffolding from starters, installing a frontend asset pipeline, inspecting registered routes, and managing template version history.
| Command | Purpose |
|---|---|
builder:init | Scaffold a new site from a starter template |
builder:frontend | Install a Vite-based frontend asset pipeline |
builder:routes | List every route the page router would serve, with conflicts flagged |
builder:history | List, view, or restore template snapshot versions |
All commands accept --json for machine-readable output.
builder:init
Section titled “builder:init”Scaffold a new site from a bundled starter template.
tcms builder:init businesstcms builder:init --listtcms builder:init blog --forcetcms builder:init --jsonWhat It Does
Section titled “What It Does”- Copies template files (layouts, pages, partials) from the starter into
tcms-data/builder/ - Creates the
builder-pagescollection with thebuilder-pageschema (if it doesn’t exist) - Imports the starter’s
jumpstart.json— pages, plus any supporting schemas, collections, and sample objects - (with
--frontend) installs the Vite frontend scaffold — same as runningtcms builder:frontend
Arguments
Section titled “Arguments”| Argument | Required | Description |
|---|---|---|
starter | No | Starter template name. Omit to list available starters. |
Options
Section titled “Options”| Option | Description |
|---|---|
--list, -l | List available starters and exit |
--force, -f | Overwrite existing template files (existing page records in the collection are left alone — JumpStart skips objects that already exist) |
--frontend | Also install the Vite frontend scaffold (equivalent to running tcms builder:frontend) |
--json | Output result as JSON |
Starter Data
Section titled “Starter Data”Every starter includes a jumpstart.json next to its manifest.json. The CLI runs it through the JumpStart importer after templates are copied so pages and any seed content land in the right places. For the blog starter that means 5 pages + 5 sample posts; for business that means 5 pages + a service schema + a services collection + 4 sample services.
If the import fails (e.g., schema validation), the scaffold itself still succeeds — templates are already on disk, and you can re-run the import manually with tcms jumpstart:import resources/builder/starters/<name>/jumpstart.json.
--frontend Behavior
Section titled “--frontend Behavior”Convenience flag for the greenfield happy path. Runs tcms builder:frontend immediately after the scaffold completes, installing the Vite scaffold into <projectRoot>/frontend/. If you don’t pass --frontend, you can always add the pipeline later — see builder:frontend.
--force Behavior
Section titled “--force Behavior”By default, scaffolding aborts if any page templates already exist. With --force:
- Template files are overwritten (existing files replaced with the starter’s versions)
- Asset files in the docroot are overwritten as well
Page records and the order file are left alone — the JumpStart importer skips objects that already exist, so a re-init won’t clobber edits made in the admin. To reset a page, delete it first then re-run, or import the page directly with tcms jumpstart:import.
--force is destructive against template files — back up your project first if you’ve made customizations.
Available Starters
Section titled “Available Starters”| Starter | Pages | Description |
|---|---|---|
minimal | Home | Single page with clean layout |
business | Home, About, Services, Contact | Professional business site |
blog | Home, Blog, Blog Post, About | Blog-focused site with dynamic post routing |
portfolio | Home, Work, About, Contact | Portfolio site with project cards |
Example Workflow
Section titled “Example Workflow”# See what's availabletcms builder:init --list
# Scaffold a business sitetcms builder:init business
# Visit your site — routing is automatic, no generation step neededSince the Site Builder uses middleware-based routing, pages are routed dynamically from the collection data. There is no generation or deployment step — pages work immediately after creating them in the admin.
builder:frontend
Section titled “builder:frontend”Install a Vite-based frontend asset pipeline scaffold into your project. Idempotent — safe to re-run, won’t overwrite customizations unless you pass --force.
tcms builder:frontendtcms builder:frontend --forcetcms builder:frontend --jsonWhat It Does
Section titled “What It Does”Copies the contents of resources/builder/frontend/ into <projectRoot>/frontend/:
vite.config.js— emits hashed assets to../public/assets/with manifestpackage.json—dev/build/watchscripts; Vite as the only dependencysrc/css/style.css— minimal starter stylesheetsrc/js/app.js— minimal entry pointREADME.md— quick reference for the install/build workflow.gitignore— excludesnode_modules/,dist/, etc.
After running, cd frontend && npm install && npm run build produces compiled assets at public/assets/ that T3’s cms.builder.css() and cms.builder.js() Twig helpers automatically resolve via the manifest.
Options
Section titled “Options”| Option | Description |
|---|---|
--force, -f | Overwrite existing files in frontend/ (use with care — any customizations are lost) |
--json | Output result as JSON |
Idempotency
Section titled “Idempotency”The default behavior is skip files that already exist, so re-running builder:frontend is safe — it only adds missing files. The result tells you what was skipped and reminds you to re-run with --force if you want a hard reset.
When to Use This vs. --frontend on builder:init
Section titled “When to Use This vs. --frontend on builder:init”| Scenario | Use |
|---|---|
| Greenfield project, scaffolding for the first time | tcms builder:init <starter> --frontend |
| Existing project, adding a frontend pipeline now | tcms builder:frontend |
| Pull missing files after the scaffold was edited | tcms builder:frontend (skips existing) |
| Reset the scaffold to upstream defaults | tcms builder:frontend --force |
See Frontend Assets for the full asset-pipeline reference (Sass, Tailwind, etc.).
builder:routes
Section titled “builder:routes”Print every route the page router would serve, in priority order, with duplicates flagged. Useful for auditing a site, hunting down route conflicts, and confirming that a collection URL is actually being matched the way you expect.
tcms builder:routestcms builder:routes --jsonWhat It Shows
Section titled “What It Shows”For each route:
| Column | Description |
|---|---|
| Route | The effective pattern the router would match |
| Source | page (builder page) or collection (collection URL) |
| ID | Page id or collection id |
| Template | Template path that gets rendered on a match |
| Status | HTTP status code the page returns |
| Notes | draft if excluded from routing, ⚠ duplicate if another route declares the same pattern |
Effective Routes for Collections
Section titled “Effective Routes for Collections”Collection URLs are normalized for display so you see what the router actually matches:
| Stored URL | Effective Route |
|---|---|
/blog | /blog/{id} (router auto-appends an id segment) |
/blog/{{ id }} | /blog/{id} (Twig syntax → standard) |
/products/{{ category }}/{{ id }} | /products/{category}/{id} |
This makes it easy to spot when a builder page route like /blog/{id} collides with a collection URL /blog — both produce /blog/{id} and the duplicate flag fires.
Example Output
Section titled “Example Output”Route Source ID Template Status Notes/ page home pages/index.twig 200/about page about pages/about.twig 200/blog page blog-list pages/blog-list.twig 200/blog/{id} page blog-post pages/blog-post.twig 200/blog/{id} collection blog pages/blog.twig 200 ⚠ duplicate/maintenance page offline pages/503.twig 503 draft
1 duplicate route(s) detected.The duplicate above means both a builder page (/blog/{id}) and the blog collection’s URL (also /blog/{id} after normalization) compete for the same pattern. The builder page wins because it’s checked first, but the collection URL is unreachable — pick one or the other.
builder:history
Section titled “builder:history”List, view, or restore snapshot versions of a builder template. Every template save captures a snapshot of the previous content; this command exposes that history at the CLI.
# List versionstcms builder:history pages/about
# View a specific snapshottcms builder:history pages/about --show=1714588200
# Restore the snapshottcms builder:history pages/about --restore=1714588200Arguments
Section titled “Arguments”| Argument | Required | Description |
|---|---|---|
path | Yes | Template path without extension (e.g. pages/about, layouts/default, partials/nav) |
Options
Section titled “Options”| Option | Description |
|---|---|
--show=<timestamp> | Print the snapshot’s contents to stdout |
--restore=<timestamp> | Restore the snapshot — overwrite the current template file |
--json | Output result as JSON |
List Mode (default)
Section titled “List Mode (default)”With no options, lists all snapshots for the template, newest first:
Versions for pages/about:
Timestamp Date Age---------- ------------------- ----------1714588200 2026-05-01 10:30:00 2h ago1714501800 2026-04-30 10:30:00 1d ago1714415400 2026-04-29 10:30:00 2d ago
Restore with: tcms builder:history pages/about --restore=<timestamp>Show Mode (--show)
Section titled “Show Mode (--show)”Prints the verbatim contents of the snapshot to stdout — useful for diffing against the current file:
tcms builder:history pages/about --show=1714501800 > /tmp/old.twigdiff /tmp/old.twig tcms-data/builder/pages/about.twigRestore Mode (--restore)
Section titled “Restore Mode (--restore)”Restores the snapshot to be the current template content. The restore is reversible — saving captures a fresh snapshot of the current contents before overwriting, so you can always undo a restore by restoring the new newest timestamp.
# Roll back to yesterday's versiontcms builder:history pages/about --restore=1714501800# → Restored to version 2026-04-30 10:30:00
# Decide it was a mistake — list to find the snapshot from the restoretcms builder:history pages/about
# Restore the version that was current before the rollbacktcms builder:history pages/about --restore=<that-newest-timestamp>Storage and Retention
Section titled “Storage and Retention”Snapshots live at tcms-data/builder/.history/{path}/{timestamp}.twig. The 50 newest snapshots per template are retained; older ones are pruned automatically on each save. You don’t need to manage them manually.
See Template History for the same workflow from the admin UI perspective.