A Copier template for quickly scaffolding FastAPI + uv backend projects.
Generated projects are ready to run out of the box with:
- FastAPI web framework + uvicorn ASGI server
- uv for dependency management (replaces pip/poetry)
- pydantic-settings configuration management (
.envfile support) - Domain-organized project structure (
core/,health/, etc.) - Structured logging (JSON / console dual-mode)
- CORS middleware
- Optional: pytest test skeleton, Ruff linting, MyPy type checking, pre-commit hooks, Docker, GitHub Actions CI
| Tool | Version | Installation |
|---|---|---|
| Python | 3.11+ | python.org |
| uv | latest | curl -LsSf https://astral.sh/uv/install.sh | sh |
| Copier | 9.0+ | uv tool install copier |
copier copy gh:EricXiao95/[email protected] ../my-backendPin to a specific Git tag (e.g.
@v0.2.0) so thatcopier updatehas a clear baseline. See Versioning & Updates for details.
From a local clone:
copier copy . ../my-backendFollow the interactive prompts (or press Enter to accept defaults):
project_name Human-readable project name (default: "FastAPI Backend")
project_slug Python package name, derived from project_name (snake_case)
python_version Python version: 3.11 / 3.12 / 3.13
author_name Author or organization name
author_email Author email (optional)
use_ruff Enable Ruff linting/formatting (default: Yes)
use_mypy Enable MyPy type checking (default: No)
use_pytest Generate pytest test skeleton (default: Yes)
open_source_license License: MIT / Apache-2.0 / Proprietary
enable_pre_commit Generate pre-commit config (default: Yes)
fastapi_app_name FastAPI app object name (default: app)
include_docker Generate Dockerfile & docker-compose (default: No)
include_github_actions Generate GitHub Actions CI workflow (default: Yes)
cd ../my-backend
make install # runs uv syncmake devOnce running, visit:
- Application: http://127.0.0.1:8000
- API docs (Swagger UI): http://127.0.0.1:8000/docs
- Health check: http://127.0.0.1:8000/health
my-backend/
├── src/my_backend/
│ ├── __init__.py # Package version
│ ├── main.py # FastAPI app entry point + lifespan
│ ├── core/
│ │ ├── config.py # pydantic-settings configuration
│ │ └── logging.py # Structured logging setup
│ └── health/
│ ├── router.py # Health check route
│ └── schemas.py # Response schemas
├── tests/ # pytest tests (optional)
│ ├── conftest.py
│ └── test_health.py
├── pyproject.toml # Dependencies & tool config
├── Makefile # Common command shortcuts
├── README.md # Project readme
├── LICENSE # License file
├── .env.example # Environment variable reference
├── .editorconfig # Editor formatting rules
├── .gitignore # Git ignore rules
├── .copier-answers.yml # Copier generation metadata
├── ruff.toml # Ruff config (optional)
├── .pre-commit-config.yaml # pre-commit config (optional)
├── Dockerfile # Multi-stage build (optional)
├── .dockerignore # Docker ignore rules (optional)
├── docker-compose.yml # Docker Compose (optional)
└── .github/workflows/ci.yml # GitHub Actions CI (optional)
Available targets depend on the options chosen during generation. install and dev are always present; the rest appear only when the corresponding tool is enabled.
| Command | Description | Condition |
|---|---|---|
make install |
Install dependencies (uv sync) |
always |
make dev |
Start dev server with hot reload | always |
make test |
Run tests | use_pytest |
make lint |
Lint & format check | use_ruff |
make format |
Auto-format code | use_ruff |
make type-check |
Type check | use_mypy |
Generated projects use pydantic-settings for configuration. Override defaults via environment variables or a .env file.
cp .env.example .envAll settings use the APP_ prefix:
| Variable | Default | Description |
|---|---|---|
APP_NAME |
Project name | Application name |
APP_DEBUG |
false |
Debug mode |
APP_LOG_LEVEL |
INFO |
Log level |
APP_API_V1_STR |
/api/v1 |
API path prefix |
APP_CORS_ORIGINS |
["*"] |
Allowed CORS origins |
Enable include_docker during project generation to get Docker support:
docker compose up --build # build & start
docker compose up -d --build # run in background
docker compose logs -f # view logsThe Dockerfile uses a multi-stage build with a built-in /health endpoint health check.
Template versions are published as Git tags (e.g. v0.1.0, v0.2.0). Always pin to a tag when generating a project so that copier update has a clear baseline:
copier copy gh:EricXiao95/[email protected] ../my-backendWhen a new template version is released, pull updates into your existing project:
cd ../my-backend
copier updatecopier update reads the source tag from .copier-answers.yml to determine what changed. If conflicts arise:
- Resolve Git merge conflicts
- Run
make lint(if Ruff is enabled) to verify code - Run
make test(if pytest is enabled) to ensure tests pass - Commit the changes
To work on this template itself:
uv sync # install dev dependencies
uv run pytest -q # run template self-testsTests cover: default generation, conditional file toggles, project structure, configuration management, health check endpoint, CI workflow validation, and more.
Why does project_slug validation fail?
project_slug must be a valid snake_case Python package name: starts with a lowercase letter, followed by only lowercase letters, digits, and underscores.
How do I customize template defaults?
Edit defaults and validators in copier.yml. Generate into a temp directory to verify changes before tagging a release.
How do I add a new domain module?
Follow the health/ module pattern — create a new directory under src/<project_slug>/ with router.py, schemas.py, etc., then register the router in main.py.
MIT