id: site
title: A stranger can read what this project is, without cloning it
status: open
crates: [didbot-site-anim, didbot-brand]
dependsOn: []
exitCriterion: >
scripts/publish-site.sh puts a build behind did.bot that a
stranger can navigate end to end: marketing pages, every file in docs/,
and the crate API reference, with no dead link between them. #
site #
Everything a stranger can currently read about this project lives in a git
checkout: the README, docs/, and whatever cargo doc renders from them.
None of it is served anywhere. site/ is a static build — Astro, built from
scratch under that directory — that turns all three into one tree:
marketing and the boring launch-required pages (privacy, terms, security,
status, 404), docs/*.md rendered as prose with its links rewritten to
resolve on the site, and cargo doc --workspace --no-deps --document-private-items's own output mounted at /api/.
scripts/build-site.sh builds all three together; scripts/publish-site.sh
adds the S3 sync and CloudFront invalidation; --dry-run plans without
publishing.
The marketing pages other than the landing page have no real copy yet.
CLAUDE.md's Copywriting section says why: brand voice is a
human's call, not something an agent decides while shipping infrastructure.
Those pages' copy is collected in site/src/data/*.ts, one file per
page or section, where a human
writes it in place; every slot in it is still filler today, each wrapped
in one marker. The landing page has already had that pass: its copy
is the owner's own, in site/src/data/landing-beats.ts. site/README.md
documents how a human finds what is still filler.
Where it can serve from, and why that is not decided here #
agent-sites has an open question this epic's layout leans on without answering: an agent's own page and this server's own browser sessions cannot safely share a registrable domain, because a cookie set by one is visible to the other. did.bot is the answer to half of that — it is the marketing origin, a static build with no session of its own and nothing in it an agent wrote — which is why it is safe to put it on the apex domain regardless of how that question resolves. What is not decided here is whether an operator's dashboard ever shares an origin with this site, or whether agent-authored pages end up on a sibling of it; that is agent-sites's call, not this epic's.
Marketing prose is the plain, load-bearing layer — hospitality, in the
project owner's words: the docs, /api/, get-started and the
launch-required pages read as an ordinary site, quickly and legibly.
Everything else on the atmosphere pages (home, features, architecture, about,
contact) carries the site's own strangeness instead of announcing it: a
context meter that fills with scroll depth and folds passed sections rather
than a progress bar addressed to the visitor, a margin ticker of this
repository's own real git log history rather than invented chatter, and a
hover-visible content hash and commit on every docs page — real values
computed at build time, never fabricated. Three testimonials from Opus,
Fable and Haiku sit in site/src/data/testimonials.ts as provisional real
copy — genuine quotations, each trimmed for the page with the untrimmed
original reachable through a native disclosure, marked provisional so a
future copy pass can find and replace them without the placeholder-coverage
check treating "provisional" as license to invent one instead. The hero
animation stays a cellular automaton (Rule 110) resolving into a
force-directed graph, now in Rust — crates/didbot-site-anim, compiled to
wasm by scripts/build-wasm.sh — so the simulation itself is covered by
ordinary cargo test rather than only by eyeballing a canvas.
A self-hosted /.well-known/did.json for did.bot itself was considered and
declined: a real one needs a live signing key and a provisioned account
behind it, which a static S3/CloudFront origin has neither of, and a
did:web document with no working key material would be exactly the kind of
fabricated artifact this epic otherwise refuses to ship.