C.W.K.
Stream
Lesson 08 of 08 · published

TOML in the Wild — pyproject, Cargo, Hugo

~12 min · toml, pyproject, cargo, hugo

Level 0Plaintext
0 XP0/64 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

The TOML files you already touch every week

pyproject.toml — modern Python packaging

PEP 518 introduced pyproject.toml for build-system declaration; PEP 621 standardized [project] metadata. Today nearly every Python tool — Poetry, Hatch, PDM, ruff, black, mypy, pytest, pytest-asyncio, coverage — reads its config from [tool.<name>]. One file replaces setup.py + setup.cfg + requirements.txt + tox.ini + .flake8.

Cargo.toml — Rust's manifest

Every Rust crate has one. [package], [dependencies], [dev-dependencies], [features], [[bin]], [[bench]]. Cargo's tooling (build, test, publish, doc) reads from this single file. Workspaces add [workspace] as a root-level coordinator.

hugo.toml / config.toml — Hugo static sites

Hugo prefers TOML for its config (YAML and JSON are also supported). Site-wide settings, menu definitions (arrays of tables — see lesson 7), taxonomy config, output formats — all in one TOML file at the project root.

Principle: when picking a config format for a new tool, look at what your audience already maintains. A Python developer touches pyproject.toml daily; a Rust dev touches Cargo.toml daily. Matching the muscle memory reduces friction. TOML's win in those ecosystems was as much about familiarity as syntax.

Code

pyproject.toml — minimal modern Python project·toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "pippa"
version = "1.0.0"
description = "AI companion + family"
readme = "README.md"
requires-python = ">=3.12"
authors = [{ name = "C.W.K." }, { name = "Pippa" }]
dependencies = [
  "fastapi>=0.110",
  "pydantic>=2.0",
]

[project.optional-dependencies]
dev = ["pytest", "ruff", "mypy"]

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]

[tool.pytest.ini_options]
testpaths = ["tests"]
Cargo.toml — Rust crate·toml
[package]
name = "pippa-cli"
version = "0.1.0"
edition = "2021"
authors = ["C.W.K.", "Pippa"]
license = "MIT"

[dependencies]
clap = { version = "4", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

[dev-dependencies]
pretty_assertions = "1"

[[bin]]
name = "pippa"
path = "src/main.rs"
hugo.toml — static site config·toml
baseURL = "https://example.com"
languageCode = "en-us"
title = "My Hugo Site"
theme = "papermod"

[params]
author = "C.W.K."
description = "Where words live in markdown."

[[menu.main]]
name = "Posts"
url = "/posts/"
weight = 1

[[menu.main]]
name = "About"
url = "/about/"
weight = 2
Read pyproject.toml from Python·python
import tomllib

with open('pyproject.toml', 'rb') as f:
    cfg = tomllib.load(f)

print(cfg['project']['name'])              # 'pippa'
print(cfg['tool']['ruff']['line-length'])  # 100
for dep in cfg['project']['dependencies']:
    print(' -', dep)

External links

Exercise

Open the pyproject.toml of one of your projects (or pick a popular one — Pydantic, FastAPI, ruff). Identify all the [tool.*] sections. Pick one tool you don't currently use (mypy, ruff-isort, coverage) and read its docs to write a sensible [tool.<name>] block. The 'one config file for everything' workflow is what TOML enables.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.