docs/How dist.town thinks
How dist.town thinks
Six ideas carry the whole system. None of them is complicated, and together they explain every URL and command.
Projects
A project is a name in your repo: lowercase letters, digits, and hyphens. Names can nest with / — dist-town/cli is a component of dist-town — and nesting is never required. An umbrella project gets a landing page listing its children automatically; hierarchy lives in the name itself, nothing else to manage.
Publishing a version creates its project automatically. disttown project create exists for bare umbrellas, and disttown project rename renames safely: the old name becomes a permanent alias that forwards visitors to the successor, so no link ever breaks.
Releases
A release is an immutable record: a version string (semver, dates, whatever your project uses — dist.town doesn’t interpret it), artifacts with sizes, platforms, and sha256 digests, and lifecycle status. Once published, a release never changes — corrections are new releases, and problems are handled by status:
- yank — do-not-newly-adopt. Anyone pinned to the version keeps working; channel resolution stops offering it.
- deprecate / archive — softer signals, carried on every page and response that shows the release.
Pointers
Pointers are the mutable names — latest, next, whatever channels you define. mytool@latest resolves through the pointer; mytool@1.0.0 names a version directly. Publishing moves latest by default (--pointer, --no-pointers to steer). A pointer never resolves to a yanked release; a pinned version always resolves.
Changelogs and publications
Release notes are markdown, published as standard.site documents — plain records any standard.site reader renders with no dist.town involvement. Attach them at publish time (publish --notes) or later (disttown changelog set); one document can describe several releases, and re-running the command edits in place.
A publication groups a family of components’ changelogs into one coherent feed with a name and identity — created once with disttown publication set, anchored at your umbrella project, linked from as many components as you like. Documents are auto-tagged by component so readers can filter.
Source
A release can say which source snapshot it corresponds to: publish --tag v1.2.3 pins the git commit — and, for annotated tags, the tag object — into the release record. Because git is content-addressed, that one hash pins the entire source tree. The tag name is just a label (tags can be force-moved; hashes can’t), so tooling trusts the hashes and displays the name.
Prefer annotated tags (git tag -a): only they have a tag object, and the tag object hash is what forge integration keys on. Set your project’s source once (it accepts an at:// record URI or an https:// forge URL) and every release inherits it; a release only states its own repo when it differs.
Be clear about what this claims: association, not build provenance. A source link says “this release corresponds to that snapshot,” not “these bytes were built from it” — that would take reproducible builds, which no registry gives you today. One thing is checked structurally: when your project’s source is a record in your own repo (a Tangled repository, say), the link is signed by the same key as the release, and pages badge it same-repo. An https:// source renders as the plain claim it is.
Tangled artifacts
If your CI already uploads artifacts to Tangled, dist.town treats them as first-class locations rather than a rival copy:
- At publish time,
publish --tagfinds yoursh.tangled.repo.artifactrecords for that tag and offers to attach them (--attach-tangledskips the prompt in CI). The CLI downloads each blob and hashes it locally — every digest in your release is your own measurement, never the forge’s claim — and the release stores only a reference to the Tangled record. - Afterward, if a Tangled upload’s bytes match a digest your release already declares, it simply becomes another verified download location — including for releases published before the upload existed.
- Order matters: upload to Tangled first, then cut the release. The record is immutable, so later uploads can never join it — they appear on the release page under an explicit “not in the record” caveat instead, unverifiable by construction.
dist.town reads Tangled’s records; it never trusts them. If their schema drifts, discovery degrades — verification doesn’t.
The lens
Here’s the part worth understanding once: dist.town holds none of this. Every project, release, pointer, and changelog is a record in your repo, signed by your identity. Artifacts live on your PDS or storage you choose. Downloads redirect to your storage; checksums derive from your signed records; every page the site renders is built from data anyone can fetch without asking dist.town.
That has practical consequences. Your releases resolve even if dist.town is down — the chain from your handle to verified bytes needs no dist.town service. If your storage dies, you can repair every historical release without editing a record. And anything this site shows, your own tools can fetch the same way — there is no private API.
dist.town is a lens over data you already own. The convenience is the product; the custody was never ours.