The Template⚓︎
The template generates a package structure that reflects common best practices for Python projects. The layout shown below represents the full set of files and directories that may be created by the template. Depending on the configuration choices you made during setup, some of these files or components may be omitted automatically.
<PROJECT> ---------------------- # your freshly created project!
├── .copier-answers.yml -------- # Copier Answer to update project
├── .gitignore ----------------- #
├── .gitlab-ci.yml ------------- # Gitlab CI Config
├── .pre-commit-config.yml ----- #
├── .python-version ------------ #
├── CONTRIBUTING.md ------------ #
├── CHANGELOG.md --------------- #
├── Justfile ------------------- # Taskrunner
├── LICENSE -------------------- #
├── README.md ------------------ #
├── pyproject.toml ------------- # Project Config
├── src/<PROJECT> -------------- # Python Package
│ └── __init__.py ------------ #
├── tests ---------------------- # Tests for the Package
│ └── test_meta.py ----------- #
├── docs ----------------------- # Documentation pages
│ └── index.md --------------- #
├── zensical.toml -------------- #
└── .github -------------------- # Github CI Config
└── ... -------------------- #
Github CI⚓︎
The template includes a set of GitHub Actions workflows that automate common development and release tasks. These workflows ensure code quality, reliability, and consistency without requiring manual intervention.
Under .github/workflows, the configuration is split into focused pipelines:
- linting, formatting and typechecking with
ruffandty - running tests with coverage (also produces a coverage badge)
- validating the package across multiple platforms and Python versions
- publishing the documentation to GitHub Pages
- creating GitHub releases with version tagging
- releasing the package to PyPI
Together, these workflows provide a lightweight but complete CI/CD setup that supports the project from development through distribution.
└── .github -------------------- # Github CI Config
├── actions/setup ---------- #
│ └── action.yml --------- #
└── workflows -------------- #
├── code_quality.yml --- # Lint, Format and Typechecking
├── docs.yml ----------- # Documentation on Github Pages
├── publish.yml -------- # Publish to PyPi
├── release.yml -------- # GitHub release workflow
├── test_coverage.yml -- # Run tests with coverage
└── test_platform.yml -- # Test different platforms and versions
Task Orchestration with Justfile⚓︎
The template uses a Justfile to provide a simple and consistent interface for task orchestration. It groups common development, quality assurance, and release tasks behind short, memorable commands, reducing the need to remember long tool-specific invocations. Most commands are built on top of uv, ensuring fast and reproducible execution.
Here are some of the core tasks provided:
justLists all available tasks and aliases.just infoDisplay system and project information.just checkorjust qRun linting and formatting with ruff and type checking with ty.just testorjust tRun the test suite.just testallRun the test suite against all supported Python versions (3.10, 3.12, 3.14).just ci [python]Execute formatting, linting, type checks, and tests in a single command, mirroring the CI pipeline locally. Optionalpythonparameter specifies the Python version (default: 3.12).just cleanorjust cRemove build artifacts, caches, and test outputs.just venvInstall and synchronize all project dependencies into the local virtual environment.just updateUpdate all dependencies and upgrade the lockfile.just hooksorjust hInstall the pre-commit hooks.just changelogWrite the changelog using git-changelog.just release <target>Make a new release. The target can bemajor,minor,patch, or a specific semver version.just distorjust dBuild the source distribution and wheel.just docsServe the documentation locally.just initInitialize a Git repository, install dependencies and hooks, and create the initial commit.
One-time Initialization
The just init command is a one-time initialization recipe that:
- Initializes the git repository
- Installs dependencies (
venv) - Runs pre-commit hooks on all files to ensure code quality
- Removes itself (
init.just) from the project - Creates the initial commit
After running just init, the recipe file is automatically deleted since git is now initialized.
Pre-commit Hooks⚓︎
The template comes with a curated set of pre-commit hooks that enforce code quality and repository hygiene before changes are committed. These hooks run automatically on each commit, providing fast feedback and preventing common issues from entering the codebase. They are designed to align with the checks performed in CI, ensuring consistency between local development and automated pipelines.
Provided hooks include:
-
Ruff linting and formatting Automatically lint and format Python code using
ruff, applying fixes where possible to keep the codebase consistent. -
Dependency lockfile synchronization Ensures the
uvlockfile is kept up to date whenever dependencies change, preventing drift between configuration and resolved environments. -
Whitespace and file hygiene checks Prevent common formatting issues such as trailing whitespace and missing end-of-file newlines.
-
Repository safety checks Detects accidentally committed private keys and blocks unusually large files from being added to the repository.
Together, these hooks act as a first line of defense, catching errors early and reducing friction during code review and continuous integration.
Pre-commit hook versions are pinned in .pre-commit-config.yaml and should be updated periodically. To upgrade all hooks to their latest compatible versions, run:
If the prek tool is installed.
prek autoupdate
If the prek tool is not installed.
uvx prek autoupdate
GitLab CI⚓︎
The template includes a lightweight GitLab CI configuration that mirrors the most important quality checks performed locally and in GitHub Actions. It is designed to provide fast feedback while remaining easy to adapt to project-specific requirements.
The pipeline is split into two stages, test and build, and relies on containerized tools to ensure reproducible execution.
Key components include:
-
Stage-based pipeline A
teststage for executing the test suite and abuildstage for static analysis and formatting checks. -
uv-powered test job A dedicated job runs tests using uv inside an official container image, installing dependencies and executing the test suite with coverage reporting enabled.
-
Reusable Ruff base job A shared base configuration defines the ruff image and setup, reducing duplication across linting and formatting jobs.
-
Ruff linting with GitLab integration The linting job exports results in GitLab’s code quality format, allowing issues to be displayed directly in merge requests.
-
Ruff formatting checks A formatting job verifies that the codebase is properly formatted by running
ruff formatin diff mode.
Overall, this configuration provides a concise yet effective CI setup for GitLab, ensuring code quality and test coverage while keeping the pipeline easy to maintain.
Licenses⚓︎
The template allows you to choose between several widely used open-source licenses. Each option provides a different balance between permissiveness, attribution requirements, and legal protection. Selecting an appropriate license early helps set clear expectations for users and contributors of your project.
Choose a License
Checkout ChooseALicense to find more detailed explanations of the Licenses.
| License | Permissive | Requires Attribution | Patent Grant | Warranty Disclaimer | Typical Use Case |
|---|---|---|---|---|---|
| MIT | Yes | Yes | No | Yes | Simple, permissive licensing with minimal requirements |
| Apache 2.0 | Yes | Yes | Yes | Yes | Projects that want explicit patent protection and clear contribution terms |
| Unlicense | Yes | No | No | Yes | Public-domain–like release with no usage restrictions |
In short, MIT is a lightweight and popular choice, Apache 2.0 adds explicit patent protections, and Unlicense removes nearly all restrictions by dedicating the work to the public domain.
Copier Answers⚓︎
The template includes a .copier-answers.yml that records the choices you made when generating the project. This file allows the project to be updateable: when the template is updated in the future, Copier can reapply the changes to your existing project while preserving your customizations.
By maintaining this answers file, you ensure that updates to the template, such as new workflows, configuration improvements, or additional files, can be integrated safely and consistently without overwriting your work.
Pyproject⚓︎
The template includes a pyproject.toml configuration file that defines project-wide settings for tools like ruff. The linting rules follow a simple philosophy: enable all rules by default to maximize code quality, and disable only those that are non-sensical or conflict with project conventions.
This approach ensures comprehensive static analysis while minimizing unnecessary noise, helping maintain a clean and consistent codebase.
Changelog⚓︎
In order to keep a Changelog run the following command.
just changelog
For more details on the tool check out the Documentation of Git Changelog
Tip
For the Changelog to work correct, it is important to adhere to Conventional Commits