software = science + art + people
This file is the single source of truth for working in this repository.
CLAUDE.md,GEMINI.md, etc. are thin redirects here. Read this first. The live, tickable task list lives in ROADMAP.md. The exact metadata schema and ID convention live in docs/conventions.md.
A collection of ~124 essays written years ago by Daniel Hardman about software architecture and the craft of programming. They were authored on WordPress, exported, and converted to Markdown. They are published as a Jekyll site on GitHub Pages at codecraft.co (CC BY 4.0).
The repo is mid-transformation: from a date-ordered WordPress blog export into a
curated, professional anthology of essays. A sister repo, ../papers,
already exhibits the target patterns (categorized index, stable per-item IDs,
per-document PDFs, a tested Python toolkit, requirements-checking CI). Much of
the work here is porting and adapting that proven system.
scripts/) + pytest suite (tests/) that
proves every goal above. pytest green == publication-ready.item_id, it never changes — not
when the filename, slug, category, or status changes. See
docs/conventions.md.scripts/ and the prover test in tests/. CI runs the tests
and the --check-only mode of the scripts.redirect_from entries in frontmatter map old
WordPress URLs to current pages; they carry the site’s existing search equity.
Never drop them.gh api repos/dhh1128/codecraft.co/dependabot/alerts --jq '.[] | select(.state=="open")';
if anything is open, triage and fix it (bump the dependency to its first
patched version) rather than letting it linger. When authoring or editing a
GitHub Actions workflow, pin actions to a non-vulnerable, node24-runtime
version up front so you don’t create a new alert. Verify a tag’s runtime with
curl -sL https://raw.githubusercontent.com/<org>/<action>/<tag>/action.yml | grep -E '^\s*using:'
(want node24, composite, or docker — never node20).own / generate / redraw / drop.
Not a bulk transform. Driven by a triage manifest (see workflow).status: cleaned → published → book: true. Retired essays stay
in the repo and git history but are excluded from the index, sitemap, and PDFs.Gemfile — it uses Pages’ built-in Jekyll, so there are no Ruby gem
dependencies for Dependabot to track; the only dependency surface is the
Actions workflows). Jekyll is blog-oriented; the author is migrating newer
static sites to Zensical (an actively-maintained successor to MkDocs,
MkDocs-API-compatible, more publication- than blog-oriented). A Zensical
migration is under consideration for this repo — see ../tti/home for a
working example (requirements.txt pins zensical, build.sh runs
zensical build, published via .github/workflows/publish.yml). Not decided;
do not migrate without an explicit decision. Note this is orthogonal to
dependency hygiene — the link-check action must be kept current regardless of
the SSG.*.md essays (one file per essay; slug == filename)
index.md / README.md table of contents (README currently a flat list; to be replaced)
assets/ owned images (target: ALL images live here)
_layouts/ Jekyll layouts (default.html renders essays + comments)
_includes/ Jekyll partials
_config.yml Jekyll config (minimal remote theme, plugins)
scripts/ durable maintenance/polish toolkit (Python) — see scripts/README.md
tests/ pytest suite that proves the goals — see tests/README.md
docs/ conventions (frontmatter schema, item-id convention)
tools/ LEGACY one-shot migration scripts (1convert.py…). Do not
extend; new tooling goes in scripts/.
.github/workflows/ CI (link-check today; requirements-check to be added)
ROADMAP.md the tickable project plan
Canonical definition in docs/conventions.md. In brief,
each essay’s YAML frontmatter should carry: title, date (original
publication), slug, item_id (CC-YYMMOO), tags (1+ from the controlled
vocabulary), redirect_from, keywords, abstract, version,
revision_date, status (published | retired), optional book: true,
optional series, and the existing comments list. Essays are classified by
multi-valued tags, not a single mutually-exclusive category — see
docs/conventions.md.
scripts/inventory_images.py → writes assets/image-triage.yml: one row per
external <img> (essay, line, URL, host, alt-text, alive/dead, blank
disposition).disposition per image: own (download & localize),
generate (AI replacement + prompt seed), redraw (→ owned diagram), or
drop (remove tag, reflow prose).scripts/apply_image_triage.py executes the manifest.assets/CREDITS.yml records provenance/rights for every final image (origin,
license, and generation model+prompt if AI-made).scripts/validate_frontmatter.py).pytest before committing; CI is the backstop.-s (the author works in DCO-enforced repos).node24-runtime versions
(actions/checkout@v4 and friends default to deprecated node20).