Project Structure¶
After generating your package, you'll have a project that looks like this:
my-package/
├── .github/
│ ├── dependabot.yml
│ ├── ISSUE_TEMPLATE.md
│ └── workflows/
│ ├── ci.yml # Lint, type check, test
│ ├── docs.yml # Build and deploy docs
│ └── publish.yml # Publish to PyPI on tag
├── docs/
│ ├── api.md # Auto-generated API reference
│ ├── index.md # Docs landing page
│ ├── installation.md
│ └── usage.md
├── src/
│ └── my_package/
│ ├── __init__.py
│ ├── __main__.py # Enables `python -m my_package`
│ ├── cli.py # Typer CLI
│ ├── py.typed # Type annotation marker (PEP 561)
│ └── utils.py # Placeholder, rename or delete
├── tests/
│ └── test_my_package.py
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── CHANGELOG/ # One file per release (e.g. v0.1.0.md)
├── justfile # Task runner commands
├── LICENSE
├── pyproject.toml # Package metadata and tool config
├── README.md
└── zensical.toml # Documentation site config
Source code (src/)¶
The project uses a src layout, where your package code lives under src/ rather than at the root. This prevents accidentally importing local code during testing, which is a common source of subtle bugs.
Put your code in src/my_package/. The utils.py file is a placeholder to get you started. Rename it, delete it, or add new modules alongside it.
CLI (cli.py)¶
Your package includes a Typer command-line interface. After uv sync, you can run it three ways:
uv run my-package # via the entry point
uv run my-package --help # show help
uv run python -m my_package # via __main__.py
The entry point is configured in pyproject.toml under [project.scripts]. To add commands, add new functions decorated with @app.command() in cli.py. See the Typer docs for details.
Justfile commands¶
Run just list to see all available commands. The key ones:
| Command | What it does |
|---|---|
just qa |
Format, lint, type-check, and test (the daily driver) |
just test |
Run tests only |
just testall |
Run tests on Python 3.12, 3.13, and 3.14 |
just type-check |
Type-check with ty |
just type-check-watch |
Type-check in watch mode |
just docs-serve |
Preview docs locally at http://localhost:8000 |
just docs-build |
Build docs |
just coverage |
Run tests with coverage and generate HTML report |
just tag |
Tag the current version and push to GitHub |
just build |
Build sdist and wheel |
GitHub Actions workflows¶
Your project includes CI, publish, documentation, and Dependabot workflows, all security-hardened out of the box. See GitHub Actions Workflows for details.
Documentation site¶
The docs site is built with Zensical and configured in zensical.toml. It uses the Material theme with light/dark mode.
The API reference page (docs/api.md) auto-generates documentation from your docstrings using mkdocstrings. Write docstrings in your code and they'll appear on the docs site automatically.
To enable deployment, go to your repo's Settings > Pages and set the source to GitHub Actions. See the Tutorial for details.
Configuration (pyproject.toml)¶
Tool configuration lives in pyproject.toml:
- Dependency groups:
dev(includes lint, test, typecheck),docs(zensical, mkdocstrings) - Ruff: line length 120, rules for pycodestyle, Pyflakes, isort, flake8-bugbear, pyupgrade
- ty: all rules enabled as errors by default. To relax a rule, uncomment the example in
[tool.ty] - uv: package mode enabled, dev groups installed by default