Writing a template
A Terox template is just a directory. It can live on your machine, in a
GitHub repository, or both. The only file Terox treats specially is
terox.json at the root, which declares the variables your template needs.
Anatomy
A minimal template:
my-template/
├── terox.json
└── {{.project_name}}/
├── README.md
└── .gitignore
When scaffolded with project_name=portfolio, the output is:
output/
└── portfolio/
├── README.md
└── .gitignore
- The manifest
terox.jsonis consumed by Terox and is not copied into the output. - Directory and file names are rendered as Go templates. The directory
{{.project_name}}/becomesportfolio/. - Text file contents are rendered the same way.
- Binary files (detected by content sniffing) are copied byte-for-byte and are never run through the template engine.
Variable syntax
Variables are referenced using standard Go text/template syntax:
# {{.project_name}}
By {{.author}}
Licensed under {{.license}}.
The keys you reference (project_name, author, license) must match the
name field of the corresponding entries in terox.json.
Conditional file paths
If a rendered file or directory name evaluates to an empty string, the file is skipped entirely. This lets you conditionally include files by gating them on a variable.
{{if eq .use_typescript "true"}}tsconfig.json{{end}}
When use_typescript is "true", the file is written as tsconfig.json.
When it is anything else, the rendered name is empty and the file is
skipped.
Files that contain {{ }} natively
Some file formats use {{ }} syntax for their own purposes — Vue
interpolations, GitHub Actions ${{ ... }} expressions, Helm charts. If
your template contains such files, escape the braces using Go template's
own escape:
- run: echo {{"${{"}} github.sha {{"}}"}}
This renders to:
- run: echo ${{ github.sha }}
A future release will add a "copy without rendering" list so this dance becomes optional.
Templates without a manifest
You do not have to write a terox.json at all. Any directory or public
GitHub repository can be scaffolded — Terox will copy the files as-is. This
is useful for snapshotting a repository without its git history, or for
turning an existing codebase into a "template" before you have time to add
variables.