Project Checklist

This checklist helps verify whether a small Python project has a clean and maintainable foundation.

It is not a strict certification.

It is a practical self-review tool.

Repository basics

A good project should have basic repository files:

  • [ ] README.md
  • [ ] .gitignore
  • [ ] LICENSE
  • [ ] CONTRIBUTING.md
  • [ ] pull request template
  • [ ] clear project roadmap or development notes

These files help people understand what the project is, how to work with it, and how it may grow.

Project structure

The project should have a clear structure:

  • [ ] source code is separated from repository metadata
  • [ ] tests are separated from source code
  • [ ] documentation has a dedicated place
  • [ ] GitHub-specific files are stored in .github/
  • [ ] generated local files are ignored

Example:

modern-python-project-guide/
├── .github/
├── docs/
├── src/
├── tests/
├── .gitignore
├── .pre-commit-config.yaml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── mkdocs.yml
├── pyproject.toml
└── uv.lock

The exact structure may differ between projects.

The important part is that the structure is understandable.

Python project configuration

The project should clearly define how Python and dependencies are managed:

  • [ ] pyproject.toml exists
  • [ ] project name is defined
  • [ ] project version is defined
  • [ ] supported Python version is defined
  • [ ] a build system is defined when the project is installable
  • [ ] runtime dependencies are listed
  • [ ] development dependencies are separated from runtime dependencies
  • [ ] uv.lock is committed
  • [ ] .venv/ is ignored

This makes the project easier to reproduce on another machine.

Source code

The source code should be easy to find and understand:

  • [ ] package code is inside src/
  • [ ] package name is clear
  • [ ] modules have focused responsibilities
  • [ ] public functions have readable names
  • [ ] simple docstrings explain non-obvious modules or functions
  • [ ] code avoids unnecessary complexity

The goal is not to make the code clever.

The goal is to make it readable and maintainable.

Tests

The project should include automated tests:

  • [ ] tests are stored in tests/
  • [ ] test files use clear names
  • [ ] test functions use clear names
  • [ ] tests check behavior, not implementation details
  • [ ] tests include important edge cases
  • [ ] tests can be run with one command

In this guide, tests are run with:

uv run pytest

Good tests make future changes safer.

Linting and formatting

The project should use automated code quality tools:

  • [ ] Ruff is installed as a development dependency
  • [ ] Ruff is configured in pyproject.toml
  • [ ] linting can be run locally
  • [ ] formatting can be checked locally
  • [ ] formatting can be fixed automatically
  • [ ] ignored rules are intentional and documented when needed

In this guide, the local commands are:

uv run ruff check .
uv run ruff format --check .
uv run ruff format .

The goal is not to satisfy tools blindly.

The goal is to keep the project clean and consistent.

Type checking

The project should check whether code follows its type annotations:

  • [ ] mypy is installed as a development dependency
  • [ ] mypy is configured in pyproject.toml
  • [ ] source code and tests use readable type annotations
  • [ ] type checking can be run locally
  • [ ] strictness settings are understood rather than copied blindly

In this guide, type checking runs with:

uv run mypy

Type checking complements tests and Ruff; it does not replace them.

Test coverage

The project should use coverage as a diagnostic tool:

  • [ ] pytest-cov is installed as a development dependency
  • [ ] coverage is limited to production source code
  • [ ] statement and branch coverage are measured
  • [ ] missing lines are visible in the terminal report
  • [ ] a percentage is not treated as proof of test quality

In this guide, tests and coverage run together:

uv run pytest --cov=text_toolkit --cov-report=term-missing

There is no minimum percentage gate.

pre-commit hooks

The project may automate fast checks before a commit:

  • [ ] pre-commit is installed as a development dependency
  • [ ] .pre-commit-config.yaml is committed
  • [ ] hooks focus on fast, repeatable checks
  • [ ] contributors know that hooks must be installed in each clone
  • [ ] hooks do not replace the complete local checks or CI

In this guide, install and run the hooks with:

uv run pre-commit install
uv run pre-commit run --all-files

Markdown linting

Documentation should have lightweight automated checks:

  • [ ] rumdl is installed as a development dependency
  • [ ] Markdown rules are configured deliberately
  • [ ] project-specific exceptions are narrow and explained
  • [ ] linting runs locally, in pre-commit, and in CI
  • [ ] link checking and human review remain separate checks

In this guide, Markdown linting runs with:

uv run rumdl check .

Documentation site

When the documentation set grows, a generated site can improve navigation:

  • [ ] MkDocs is installed as a development dependency
  • [ ] mkdocs.yml defines explicit navigation
  • [ ] docs/index.md provides a site landing page
  • [ ] source Markdown remains readable directly on GitHub
  • [ ] generated site/ files are ignored
  • [ ] strict site builds run locally and in CI
  • [ ] building and publishing are treated as separate operations
  • [ ] a dedicated deployment workflow publishes only from main
  • [ ] generated output is uploaded as an artifact instead of committed
  • [ ] deployment permissions are limited to the deployment job
  • [ ] the public site contains no secrets or private material

Preview and validate the site with:

uv run mkdocs serve
uv run mkdocs build --strict

Continuous integration

The project should run checks automatically in CI:

  • [ ] GitHub Actions workflow exists
  • [ ] CI runs on pull requests
  • [ ] CI runs on pushes to main
  • [ ] CI installs dependencies from the lockfile
  • [ ] CI runs linting
  • [ ] CI checks formatting
  • [ ] CI lints Markdown
  • [ ] CI builds the documentation site strictly
  • [ ] CI runs tests with coverage reporting
  • [ ] CI runs type checking
  • [ ] CI builds a wheel and source distribution
  • [ ] CI status is visible in the README

Continuous deployment

If the documentation is published automatically:

  • [ ] GitHub Pages uses GitHub Actions as its source
  • [ ] the deployment workflow runs after relevant changes reach main
  • [ ] pull requests validate the site without publishing it
  • [ ] build and deploy jobs pass the generated site as an artifact
  • [ ] the deployment uses the github-pages environment
  • [ ] the published site is checked after deployment

CI helps protect the main branch from broken changes.

Git workflow

The project should use a clear Git workflow:

  • [ ] changes are made on branches
  • [ ] branch names are descriptive
  • [ ] commits are small and focused
  • [ ] commit messages are readable
  • [ ] meaningful changes go through pull requests
  • [ ] pull requests explain what changed and why
  • [ ] pull requests include information about checks
  • [ ] merged branches are deleted

A good workflow keeps history understandable.

Pull requests

A good pull request should answer:

  • [ ] What changed?
  • [ ] Why was it changed?
  • [ ] How was it checked?

Before opening a pull request, review:

  • [ ] the changed files
  • [ ] the diff
  • [ ] the pull request title
  • [ ] the pull request description
  • [ ] local check results
  • [ ] whether the change is small enough

Small pull requests are easier to review and safer to merge.

Local command checklist

For code changes, run:

uv run ruff check .
uv run ruff format --check .
uv run rumdl check .
uv run mkdocs build --strict
uv run pytest --cov=text_toolkit --cov-report=term-missing
uv run mypy
uv build --no-sources

If formatting fails, run:

uv run ruff format .

Then repeat:

uv run ruff check .
uv run ruff format --check .
uv run rumdl check .
uv run mkdocs build --strict
uv run pytest --cov=text_toolkit --cov-report=term-missing
uv run mypy
uv build --no-sources

For documentation-only changes, code checks may not always be necessary.

However, review the rendered Markdown on GitHub.

Red flags

The project may need cleanup if:

  • [ ] many unrelated changes appear in one pull request
  • [ ] commit messages are vague
  • [ ] tests are missing
  • [ ] CI is failing
  • [ ] generated files are committed
  • [ ] dependencies are installed manually but not recorded
  • [ ] configuration files are copied without being understood
  • [ ] the project cannot be set up from a clean clone

These are not reasons to panic.

They are signals that the workflow needs attention.

Minimal healthy project

A small healthy Python project should answer these questions:

What is this project?
How do I install it?
Where is the code?
Where are the tests?
How do I run the tests?
How do I inspect test coverage?
How do I check formatting and linting?
How do I lint Markdown documentation?
How do I preview and validate the documentation site?
How do I check type annotations?
How do I build distribution files?
What happens before code is merged?

If the repository answers these questions clearly, it has a strong foundation.

Rule of thumb

A clean project is not necessarily a large project.

A clean project is one where another person can understand the structure, run the checks, and make a small change safely.

Start simple.

Keep changes small.

Explain decisions.

Let the project grow gradually.

Continue