My opinionated scaffolding for modern Python projects
Python is a pragmatic programming language and asks for very little to get started. A text file with valid code, conventionally ending in .py and forming a “module” in Python jargon, is already a small program (a script); we run it with python <file> and we are done. But when that simple piece of code needs to grow into more files or deserves to be distributed —maybe because it will be a dependency of another project or simply because someone else might benefit— then it needs some structure and metadata.
That is not exclusive to Python: when you start a software project there is always a basic set of files and structures that serve as a starting point; the minimum set of files, folders, configs, and "basic" code you need when you want to share code as an app or library: the project boilerplate. The boilerplate does not define logic, but it does lay the technical foundation—often based on conventions and sometimes on personal taste—on which everything else will be built.
This article details the decisions I made for the template and automated scaffolding I created for my projects, based on Copier.
In short:
- 🐍 Modern Python package (3.12+)
- 📦 Build and dependency management with uv, split by groups (dev/qa/docs)
- 🧹 Linting and formatting via Ruff with a broad set of rules enabled
- ✅ Type checking via ty
- 🧪 Tests with pytest, coverage.py and extensions
- 📚 Docs with Sphinx, MyST and a few extensions, deployed to GitHub Pages
- 🤖 GitHub project creation automated through GitHub CLI
- ⚙️ CI workflow on GitHub Actions
- 🚀 Automated releases via Trusted Publishing
- 🧠 Sensible defaults via introspection to minimize answers in the initial questionnaire
- 🛠️ Makefile with shortcuts for common tasks
- 📄 Generation of generic docs such as LICENSE/CODE_OF_CONDUCT/AGENTS.md, etc.
- 🌀 Initial setup of the development environment and git repo
- ♻️ Projects updatable with
copier update
And a bunch more details I am surely forgetting.
