Docs / Guides

Publishing & versions

Every publish is kept forever. Going live is one pointer moving to a version; rolling back is the same pointer moving again. Nothing is ever overwritten.

What a publish is

A publish uploads a directory as a gzipped tar. Each file is stored by the SHA-256 of its contents, so a file that has been uploaded before — by any site in your workspace — is not stored twice. The set of files becomes an immutable version, and the site’s live pointer moves to it.

colophon publish ./out --name "Q3 report" --slug q3-report --visibility unlisted
FlagMeaning
--nameDisplay name in the dashboard. Defaults to the directory name.
--slugThe URL path. Defaults to a slug of the name. Pass it explicitly when you intend to update the site later, so a changed name cannot move the URL.
--visibilitypublic, unlisted (the default for a new site), restricted or private. Left off when updating a site, the level it already has is kept. See Access & sharing.

Updating a site

Publish again with the same slug. The URL does not change; a new version is created and made live. Every earlier version stays listed on the site’s page with aMake live button — rollback is instant, because it is a pointer change and not a re-upload.

Each version also says what it changed against the one published before it —+2 ~1 −1: files added, changed, removed — or identical when a republish moved nothing. Every file is stored once by its content hash, so this is known without reading anything back. The line opens a side-by-side view of the files that differ, and Compare with live on an older version shows what making it live would change, with the button to do so beside the answer. Images show both versions side by side; other files that are not text, or over 1 MB, show their sizes and a link to each version.

Do not publish a second site for a second draft. One slug, many versions, one link that stays correct as the work changes.

Drafts and previews

colophon publish ./site --slug report --draft
# → https://acme.usercontent.colophon.fyi/report/_v/<version id>/

A draft is a version that is stored, scanned and addressable, but not live: the site’s URL keeps serving what it served, and the site’s name and visibility stay as they are. The preview URL is the version’s own, under the same site — so a preview of a private site asks for the same sign-in the site does, and no preview is ever indexed. Send it to whoever needs to approve; when they do, Make live on the site’s Versions list is the same pointer flip as a rollback.

Every kept version has the same kind of URL, so an older version can be looked at without making it live again. A first publish as a draft creates the site with nothing live yet.

Expiry

curl … -F expires_at=2026-10-01T00:00:00Z     # on publish
curl -X PATCH … -d '{ "expires_at": null }'     # clear it later

A site can be given a moment after which it stops answering. Agents produce a great deal of output that is only needed for a while, and this is how it stops needing to be remembered. Past the moment every path answers 410 Gone, previews included, and caches are told beforehand not to hold a page past what is left. Nothing is deleted: the versions stay, the row stays, and the date can be pushed out or cleared from the site’s page or the API to bring it back.

Omitted on a republish, the expiry stays as it was; a draft never touches it. Publishing something already expired is refused, since it is never what anyone meant; dating a live site into the past through the API is deliberate, and takes it down without deleting it.

What gets uploaded

Every regular file under the directory, with paths preserved. The CLI skips.git, .env, node_modules, .next,.venv, __pycache__, .DS_Store and macOS._* resource forks. The server drops the same junk and refuses anything unsafe: absolute paths, .. segments, symlinks.

LimitValue
Per file25 MB
Per version200 MB, 2,000 files
Publishes10 per minute, 200 per day, per workspace

Bare files are made readable at publish time. Every .md gets an.html rendered beside it, with links between Markdown files rewritten to match; a README.md or index.md stands in for a missingindex.html in its directory; and a site root with no index gets the one page it has, or a file browser: every file listed beside a preview of the one selected. The original files stay at their own URLs. Ship your own x.html beside x.md to keep the render off.

How it is served

  • HTML pages get a small analytics beacon injected at publish time — see Analytics.
  • On the free plan, a public site carries a one-line “Published with Colophon” footer under the content of every page, added at publish time. Unlisted, restricted and private sites never do.
  • Public sites are cacheable and indexable. Everything else is served with X-Robots-Tag: noindex, nofollow.
  • Restricted and private sites require a signed-in visitor; see Access & sharing.

Scanning and review

Every version is scanned before it goes live: a phishing heuristic over the HTML, and Google Safe Browsing over every outbound href and src. A hit does not delete anything — the version is stored but held, the site’s previous version (if any) stays live, and the CLI prints held for reviewwith the reasons. A person reviews held versions and either releases or rejects them.

Deleting a site

From the site’s page, type its slug to confirm, or colophon delete <slug>. Every version, every sharing grant and the URL itself go at once; links people already hold will 404. Stored bytes shared with other sites are untouched, and unreferenced ones are collected after seven days. This is the one action that cannot be undone.

Publishing & versions — Colophon docs