Templates
pypreset uses Jinja2 templates to generate
project files. Templates live in src/pypreset/templates/ and are referenced by
preset YAML files.
Available Templates
Core project files:
Template |
Output |
|---|---|
|
Poetry-based |
|
uv/hatchling-based |
|
Project README |
|
|
CI workflows (Poetry / uv / setuptools variants):
Template |
Output |
|---|---|
|
GitHub Actions CI for Poetry projects (test + lint jobs) |
|
GitHub Actions CI for uv projects (uses |
|
GitHub Actions CI for setuptools projects (uses |
|
Dependabot configuration (pip + GitHub Actions ecosystems) |
|
GitHub Pages deployment workflow for documentation |
Preset-specific templates:
Template |
Used by |
|---|---|
|
|
|
|
|
|
|
|
Docker & devcontainer templates:
Template |
Output |
|---|---|
|
Multi-stage Dockerfile for Poetry projects (src and flat layout aware) |
|
Multi-stage Dockerfile for uv projects |
|
Multi-stage Dockerfile for setuptools projects (pip install) |
|
|
|
|
Documentation templates:
Template |
Output |
|---|---|
|
Sphinx |
|
Sphinx |
|
MkDocs |
|
MkDocs |
Configuration templates:
Template |
Output |
|---|---|
|
|
|
|
|
|
Augment templates (in templates/augment/):
Used by pypreset augment to add components to existing projects. These are
separate from the create templates because they need to adapt to the detected
tooling of an existing project rather than using preset-defined settings.
Template |
Output |
|---|---|
|
GitHub Actions test workflow (adapts to detected package manager and test framework) |
|
GitHub Actions lint workflow (adapts to detected linter and type checker) |
|
Dependabot configuration |
|
Template test file for |
|
pytest |
|
PyPI publish workflow using OIDC trusted publishing |
|
Python-specific |
Template Context
All templates receive a context dict built by template_engine.get_template_context().
The primary variable is project, which is the ProjectConfig Pydantic model
serialized to a dict:
{{ project.name }} {# "my-app" #}
{{ project.package_name }} {# "my_app" #}
{{ project.metadata.version }} {# "0.1.0" #}
{{ project.layout }} {# "src" or "flat" #}
{{ project.package_manager }} {# "poetry" or "uv" #}
{# Dependencies #}
{% for dep in project.dependencies.main %}
{{ dep }}
{% endfor %}
{# Testing #}
{% if project.testing.enabled %}
{{ project.testing.framework }} {# "pytest" #}
{% endif %}
{# Type checker #}
{{ project.type_checker }} {# "mypy", "ty", or "none" #}
{{ project.typing_level }} {# "none", "basic", or "strict" #}
{# Entry points #}
{% for ep in project.entry_points %}
{{ ep.name }} = {{ ep.module }}
{% endfor %}
{# Docker #}
{% if docker.enabled %}
{{ docker.base_image }} {# "python:3.11-slim" (auto-resolved) #}
{{ docker.devcontainer }} {# true or false #}
{% endif %}
{# Documentation #}
{% if documentation.enabled %}
{{ documentation.tool }} {# "sphinx" or "mkdocs" #}
{{ documentation.deploy_gh_pages }}
{% endif %}
{# Extras dict (preset-specific data) #}
{{ project.extras.cli_framework }} {# "typer" for cli-tool preset #}
Package Manager Selection
The generator picks template variants based on project.package_manager:
Poetry (default):
pyproject.toml.j2+github_ci.yaml.j2+Dockerfile.j2uv:
pyproject_uv.toml.j2+github_ci_uv.yaml.j2+Dockerfile_uv.j2setuptools:
pyproject_setuptools.toml.j2+github_ci_setuptools.yaml.j2+Dockerfile_setuptools.j2
The uv variant uses PEP 621 [project] tables with hatchling as the build
backend, and CI workflows use astral-sh/setup-uv instead of snok/install-poetry.
The setuptools variant uses PEP 621 [project] tables with setuptools.build_meta
as the build backend, dev dependencies in [project.optional-dependencies], and
CI workflows use plain pip install -e ".[dev]".
README Template
The README.md.j2 template generates a full README with badges, installation
instructions, usage examples, a features list, and development commands. It is
used by both the create and augment pipelines.
Key context variables used by the template:
project.name,project.description,project.repository_url,project.licensetesting.enabled,testing.coverage_config.enabledformatting.tool,formatting.type_checkertyping_level("none","basic", or"strict")entry_points(list of{name, module}dicts)docker.enabled,docker.devcontainerdocumentation.enabled,documentation.toolpackage_manager("poetry"or"uv")
Badge generation relies on project.repository_url containing a GitHub URL.
When present, CI, PyPI version, Python version, and (optionally) Codecov badges
are rendered. A license badge is added when project.license is set.
Preset override: set metadata.readme_template in a preset YAML to use a
custom template instead of the default README.md.j2:
metadata:
readme_template: my_readme.j2
The pypreset badges CLI command and the generate_badges MCP tool provide
standalone badge generation from pyproject.toml without rendering the full
README template.
Writing Custom Templates
Create a
.j2file insrc/pypreset/templates/Reference it in a preset YAML under
structure.files[].templateUse the
projectcontext variable for all project metadata
Example preset entry:
structure:
files:
- path: "src/{{ project.package_name }}/config.py"
template: config.py.j2
The path field itself is a Jinja2 expression, so you can use template
variables like {{ project.package_name }} in file paths.