flowchart TB
subgraph User["User Interaction"]
CLI["uvx create-awesome-python-app\n--template <slug> --addons <ext>"]
end
subgraph Registry["Template Registry"]
JSON["templates.json\n(categories, templates, extensions)"]
end
subgraph Merge["Merge Process"]
Template["Base Template\n(template/type)"]
Ext1["Extension 1\n(ext/type)"]
Ext2["Extension 2\n(ext/type)"]
Merged["Merged Project\nCopy-only semantics"]
end
subgraph Result["Generated Output"]
Project["~/my-new-project\n(pyproject.toml, src/, tests/, docs/)"]
Git["git init\n(skipped if CPA_SKIP_GIT=1)"]
Install["uv sync\n(requires pyproject.toml,\n skipped with --no-install)"]
end
CLI --> JSON
JSON --> Template
Template --> Ext1
Ext1 --> Ext2
Ext2 --> Merged
Merged --> Project
Project --> Git
Project --> Install
style CLI fill:#e1f5fe
style JSON fill:#f3e5f5
style Merged fill:#e8f5e9
style Project fill:#fff3e0
style Git fill:#ffe0b2
style Install fill:#ffe0b2
A user runs:
uvx create-awesome-python-app --template <slug> --addons <ext1> <ext2>CPA resolves each slug to a url in templates.json, downloads the directories, merges them with copy-only semantics, and writes the final project to disk. The merge order is: base template files → each extension in order (later layers overwrite).
Three top-level keys: categories, templates, extensions.
Every template and extension requires: name, slug, description, url, type, category, labels.
Interactive options live in cpa.config.json inside the template directory (not in templates.json).
type connects templates to extensions. A template has a single string type. An extension has a string or array of strings. An extension is compatible with a template when the template's type appears in the extension's type list.
compatible = [ext.type].flat().includes(template.type)
| Slug | Type |
|---|---|
fastapi-starter |
fastapi-backend |
cli-starter |
cli-app |
celery-worker |
celery-worker |
django-api |
django-backend |
uv-workspace-starter |
uv-workspace |
mlops-sklearn-starter |
mlops-sklearn |
- Resolve
urlfor template and each selected extension fromtemplates.json(orfile:/// GitHub URL) - Clone or open the source directory (cached under
~/.cache/cpafor remote repos) - For each layer, copy files from
template/subdirectory when present, otherwise from the layer root - Run
uv syncwhenpyproject.tomlexists (unless--no-install) - Initialize a git repository (unless
CPA_SKIP_GIT=1)
| Feature | CNA | CPA |
|---|---|---|
EJS / Jinja .template files |
EJS | Jinja2 in create-python-app-core (rolling out) |
.append files |
Yes | Rolling out in core |
| Manifest merge for extensions | package/index.js |
pyproject.toml merge in core (rolling out) |
Bracket [dir]/ renaming |
Yes | Planned |
Compose file naming matches CNA: prefer compose.yml, not docker-compose.yml.
cpa-templates/
├── templates.json # Registry (served to CLI via raw GitHub URL)
├── templates.schema.json # JSON Schema for templates.json
├── templates/ # Base project starters
├── extensions/ # Optional layers
├── scripts/ # CI helpers (validate-registry.py, generate-matrix.py)
├── ci/ # Curated L3 profiles
├── .github/ # Workflows, issue templates, dependabot
└── docs/ # Authoring and testing guides
- create-python-app — CLI monorepo (
create-awesome-python-app,create-python-app-core) - cpa-templates (this repo) — template and extension bank
Operational runbooks for CI, dependencies, security, releases, and template work live under docs/MAINTENANCE_RUNBOOK.md.