EricXiao95/python-backend-template

FastAPI backend template powered by Copier and uv, with domain-driven structure, typed settings, structured logging, CI workflow, Docker support, and optional dev tools.

★ 0Forks 0PythonGitHub ↗Compare

README

Python Backend Template

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 (.env file 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

Prerequisites

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

Quick Start

1. Generate a Project

copier copy gh:EricXiao95/[email protected] ../my-backend

Pin to a specific Git tag (e.g. @v0.2.0) so that copier update has a clear baseline. See Versioning & Updates for details.

From a local clone:

copier copy . ../my-backend

Follow 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)

2. Install Dependencies

cd ../my-backend
make install        # runs uv sync

3. Start the Dev Server

make dev

Once running, visit:

Generated Project Structure

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)

Makefile Commands

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

Configuration

Generated projects use pydantic-settings for configuration. Override defaults via environment variables or a .env file.

cp .env.example .env

All 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

Docker Deployment

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 logs

The Dockerfile uses a multi-stage build with a built-in /health endpoint health check.

Versioning & Updates

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-backend

When a new template version is released, pull updates into your existing project:

cd ../my-backend
copier update

copier update reads the source tag from .copier-answers.yml to determine what changed. If conflicts arise:

  1. Resolve Git merge conflicts
  2. Run make lint (if Ruff is enabled) to verify code
  3. Run make test (if pytest is enabled) to ensure tests pass
  4. Commit the changes

Template Development

To work on this template itself:

uv sync                  # install dev dependencies
uv run pytest -q         # run template self-tests

Tests cover: default generation, conditional file toggles, project structure, configuration management, health check endpoint, CI workflow validation, and more.

FAQ

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.

License

MIT

Contributors

EricXiao95

Issues