Template Tasks with Handlebars
The template task type supports powerful templating capabilities using Handlebars, enabling you to generate files from templates with advanced features like conditionals, loops, and helpers.
Overview
Template tasks can use two different templating approaches:
- Simple Interpolation (default): Basic `` replacement for inline templates and non-
.hbsfiles - Handlebars: Full Handlebars templating engine for files with
.hbsextension
Templates can be defined in two ways:
- Inline: Template string directly in the task configuration (simple interpolation only)
- File-based: External template file (relative to project root or template source).
.hbsfiles automatically use Handlebars
Note: When using configuration inheritance with remote configurations,
templateFilepaths are automatically resolved relative to the remote configurationβs location. This allows remote configurations to reference their own template files hosted alongside them.
Configuration Options
Basic Options
file(required): Path to the output file to create or overwritetemplate(optional): Inline template string using simple `` syntaxtemplateFile(optional): Path to external template file (relative to project root, or for remote templates, relative to the templateβs URL)condition(optional): JavaScript expression to conditionally execute the task
Important: You must specify either template OR templateFile, but not both.
Automatic Handlebars Detection
Handlebars is automatically enabled for any template file ending in .hbs. No configuration needed!
File-based Handlebars Example
Template file (templates/readme.hbs):
#
>
is a modern TypeScript project.
## π₯ Author
## β¨ Features
-
## π License MIT
Task configuration:
{
"id": "clean-readme",
"name": "Clean README",
"description": "Create a fresh README for the new project",
"required": true,
"enabled": true,
"type": "write",
"config": {
"file": "README.md",
"templateFile": "templates/readme.hbs"
}
}
Simple Interpolation (Default)
When using inline templates or template files that donβt end in .hbs, simple `` replacement is used.
Inline Template Example
{
"id": "simple-readme",
"name": "Simple README",
"type": "write",
"config": {
"file": "README.md",
"template": "# \n\nAuthor: \nRepository: "
}
}
File-based Simple Template Example
Template file (templates/simple-readme.txt):
#
Author:
Repository:
Task configuration:
{
"id": "simple-readme-file",
"name": "Simple README from File",
"type": "write",
"config": {
"file": "README.md",
"templateFile": "templates/simple-readme.txt"
}
}
Handlebars Features
Conditionals
Author:
This is a public package
Loops
## Packages
- ****:
Else Blocks
No description available
Comments
Built-in Helpers
Handlebars includes many built-in helpers:
,,,(with custom helper registration)
See Handlebars documentation for complete details.
Available Variables
All configuration variables from your InitConfig are available in templates:
projectName: Repository nameowner: Repository ownerrepoUrl: Full repository URLauthor: Author namerepoUrl: Base repository URLorgName: Organization name- Plus any variables collected from prompts
Best Practices
When to Use Simple vs. Handlebars
Use Simple Interpolation when:
- You only need basic variable replacement
- Template is very simple
- Using inline templates
- Backwards compatibility is important
Use Handlebars when:
- You need conditionals or loops
- Template has complex logic
- You want cleaner, more readable templates
- Using external
.hbstemplate files
Inline vs. File-based Templates
Use Inline Templates when:
- Template is short (< 5 lines)
- Quick prototyping
- Template is specific to one use case
Use File-based Templates when:
- Template is long or complex
- Template might be reused
- You want syntax highlighting and better editing experience
- You need Handlebars features (use
.hbsextension)
File Organization
Recommended structure for template files:
project-root/
βββ .scaffoldfy/
β βββ templates/
β βββ readme.hbs # Handlebars template
β βββ package-json.hbs # Handlebars template
β βββ license.txt # Simple template
β βββ contributing.md # Simple template
βββ config-tasks.json
Complete Example
Task configuration (config-tasks.json):
{
"tasks": [
{
"id": "clean-readme",
"name": "Generate README",
"description": "Create README using Handlebars template",
"required": true,
"enabled": true,
"type": "write",
"config": {
"file": "README.md",
"templateFile": ".scaffoldfy/templates/readme.hbs"
}
},
{
"id": "update-package-json",
"name": "Update package.json",
"description": "Generate package.json from simple template",
"required": true,
"enabled": true,
"type": "write",
"config": {
"file": "package.json",
"templateFile": ".scaffoldfy/templates/package-json.hbs"
}
},
{
"id": "inline-license",
"name": "Create LICENSE",
"description": "Create simple license file",
"required": false,
"enabled": true,
"type": "write",
"config": {
"file": "LICENSE",
"template": "MIT License\n\nCopyright (c) \n\nPermission is hereby granted..."
}
}
]
}
Handlebars template (.scaffoldfy/templates/readme.hbs):
#
>
> A modern TypeScript project
## π Quick Start ```sh # Install dependencies pnpm install # Build pnpm build # Test pnpm
test
β¨ Features
π₯ Author
π License
MIT
## Error Handling
### Missing Template File
If a `templateFile` is specified but doesn't exist, the task will throw an error:
β Failed to read template file: templates/missing.hbs β Error: Template file not found: templates/missing.hbs
### Invalid Handlebars Syntax
If Handlebars syntax is invalid in a `.hbs` file, you'll get a compilation error:
β Failed to compile Handlebars template β Error: Parse error on line 5: β¦
### Both template and templateFile
You cannot specify both options:
β Template task cannot have both βtemplateβ and βtemplateFileβ specified. Use one or the other.
## Migration from Previous Versions
### From useHandlebars flag
**Before (with flag)**:
```json
{
"templateFile": "readme.hbs",
"useHandlebars": true
}
After (automatic):
{
"templateFile": "readme.hbs"
}
From inline Handlebars
Before (inline Handlebars):
{
"template": "# \nAuthor: ",
"useHandlebars": true
}
After (file-based only):
{
"templateFile": "readme.hbs"
}