Create Templates
Learn how to create reusable project templates with Angreal’s Tera templating engine.
- Angreal installed and working
- Basic understanding of file structures
- Familiarity with TOML format
Every Angreal template follows this structure:
my-template/
├── angreal.toml # Template configuration
├── {{ variable_name }}/ # Templated directories
├── static_file.txt # Static files (copied as-is)
├── templated_file.md.tera # Templated files
└── .angreal/ # Optional: template tasks
├── init.py # Post-initialization script
└── task_*.py # Template-specific tasks
The angreal.toml
file defines variables that users will provide:
# Required template metadata
[template]
name = "my-awesome-template"
description = "A template for awesome projects"
version = "1.0.0"
# Template variables with defaults
project_name = "my-project"
author_name = "Anonymous"
license = "MIT"
use_docker = false
Angreal supports several variable types:
# String variables
project_name = "default-name"
description = "Default description"
# Boolean variables
use_docker = false
include_tests = true
# Numeric variables
port = 8080
timeout = 30
# Choice variables (user selects from options)
license = "MIT" # Could be MIT, Apache-2.0, GPL-3.0, etc.
Use Tera syntax in directory names:
mkdir "{{ project_name }}"
mkdir "{{ project_name }}/src"
mkdir "{{ project_name }}/tests"
When initialized with project_name = "my-app"
, creates:
my-app/
my-app/src/
my-app/tests/
Files can also use template variables:
touch "{{ project_name }}.py"
touch "test_{{ project_name }}.py"
Create README.md
:
# {{ project_name }}
{{ description }}
## Author
Created by {{ author_name }}
## License
This project is licensed under the {{ license }} license.
Use Tera’s conditional syntax:
{{ project_name }}
{{ description }}
{% if use_docker %}
## Docker
This project includes Docker support.
```bash
docker build -t {{ project_name }} .
docker run {{ project_name }}
```
{% endif %}
{% if include_tests %}
## Testing
Run tests with:
```bash
python -m pytest tests/
```
{% endif %}
Define lists in angreal.toml
:
dependencies = ["requests", "click", "pydantic"]
Use in templates:
# requirements.txt
{% for dep in dependencies %}
{{ dep }}
{% endfor %}
Or for more complex structures:
# setup.py
install_requires = [
{% for dep in dependencies %}
"{{ dep }}",
{% endfor %}
]
Tera provides useful filters:
# {{ project_name | title }}
Package name: {{ project_name | lower | replace(from=" ", to="-") }}
Class name: {{ project_name | title | replace(from=" ", to="") }}
Common filters:
upper
/lower
- Change casetitle
- Title casereplace(from="x", to="y")
- Replace texttrim
- Remove whitespacelength
- Get length
For files that contain Tera-like syntax that you don’t want to be processed, use the {% raw %}
tag:
# Template file: package.json
{% raw %}
{
"name": "{{ project_name }}",
"version": "1.0.0",
"scripts": {
{% if include_tests %}
"test": "jest"
{% endif %}
}
}
{% endraw %}
The {% raw %}
tag tells Tera to treat everything between the tags as literal text, preventing any template processing within that block. This is particularly useful for:
- JSON files that might contain curly braces
- Template files you keep as part of a task
- Configuration files with Tera-like syntax
- Documentation files that need to show template examples
- Any file where you want to preserve the exact syntax
Create .angreal/init.py
to run code after template processing:
"""Post-initialization script."""
import os
import subprocess
def init():
"""Run after template is rendered."""
# Get template variables
context = angreal.get_context()
project_name = context.get('project_name', 'project')
print(f"Initializing {project_name}...")
# Initialize git repository
subprocess.run(['git', 'init'], cwd=project_name)
# Install dependencies if specified
if context.get('install_dependencies', False):
print("Installing dependencies...")
subprocess.run(['pip', 'install', '-r', 'requirements.txt'],
cwd=project_name)
print("Template initialization complete!")
print(f"Next steps:")
print(f" cd {project_name}")
print(f" # Start developing!")
Add tasks that are useful for projects created from your template:
# .angreal/task_setup.py
import angreal
import subprocess
@angreal.command(name="setup", about="Set up development environment")
@angreal.argument(name="install_deps", long="install-deps", is_flag=True,
help="Install Python dependencies")
def setup_project(install_deps=False):
"""Set up the development environment."""
if install_deps:
print("Installing dependencies...")
subprocess.run(['pip', 'install', '-r', 'requirements.txt'])
print("Creating virtual environment...")
subprocess.run(['python', '-m', 'venv', '.venv'])
print("Setup complete!")