feat(site): source links to the repo, deployment layout documented

- "View source" and the nav GitHub link pointed at the user profile
  (github.com/shoneyj); both now point at github.com/shoneyJ/writeonce
- README: what actually has to reach the host — the self-contained
  binary plus dist/ (served by /dl) and data/ (WO_DATA) — and the four
  environment variables, with SITE_HOST left UNSET behind a proxy so
  the process binds loopback
- says plainly that dist/ must hold the PUBLISHED release assets: the
  build is not byte-reproducible, so a local tarball would not match
  the published .sha256 and the mirror would disagree with GitHub

Prepared and verified locally: docs/examples/site/dist/ holds the real
v0.1.0 assets (digest matches the release) and target/site serves them
byte-identically. Both directories are gitignored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
shoney.arickathil 2026-08-25 08:45:15 +02:00
parent 8f3824409b
commit b3f8ed9985
3 changed files with 39 additions and 2 deletions

View file

@ -93,6 +93,43 @@ server {
Run the binary under systemd (`Restart=on-failure`, `Environment=SITE_TOKEN=...`, Run the binary under systemd (`Restart=on-failure`, `Environment=SITE_TOKEN=...`,
`Environment=WO_DATA=/var/lib/writeonce-site`); SIGTERM drains cleanly. `Environment=WO_DATA=/var/lib/writeonce-site`); SIGTERM drains cleanly.
### What to copy to the host
The binary is self-contained — VM, bytecode and database engine are
inside it — but two directories are read at RUNTIME and must travel
with it:
```
/srv/writeonce-site/
site the binary (docs/examples/site/target/site)
dist/ what /dl serves — the RELEASE assets:
writeonce-0.1.0-linux-amd64.tar.gz
writeonce-0.1.0-linux-amd64.tar.gz.sha256
data/ WO_DATA — the WAL; create it, keep it
```
```
SITE_TOKEN=<bearer for /admin> required, the process refuses to start without it
WO_DATA=/srv/writeonce-site/data durable chapters; omit for RAM-only
WO_DIST=/srv/writeonce-site/dist where /dl reads from (default ./dist)
SITE_HOST leave UNSET behind a proxy — loopback is the
right default; set it only to expose directly
```
Behind a proxy `SITE_HOST` stays unset, so the process binds
`127.0.0.1` and is unreachable except through nginx. It prints the
bound address at startup, which is the quickest way to confirm that.
**Keep `dist/` the published release, not a local build.** `just dist`
produces a different digest on every run, so a locally built tarball
would not match the `.sha256` the release publishes and would make the
mirror disagree with the GitHub download. Fetch the assets from the
release instead:
```
gh release download v0.1.0 -D dist -R shoneyJ/writeonce
```
## What it demonstrates ## What it demonstrates
Chapters 1–9 teach the language (values, containers, classes, optionals, Chapters 1–9 teach the language (values, containers, classes, optionals,

View file

@ -13,7 +13,7 @@ pub class HomePage {
-- hero: tagline + the two CTAs (the go.dev shape, no JS anywhere) -- hero: tagline + the two CTAs (the go.dev shape, no JS anywhere)
let h1 = el("h1", "text-4xl font-bold mb-4", "One language. One runtime.<br>One database. One binary."); let h1 = el("h1", "text-4xl font-bold mb-4", "One language. One runtime.<br>One database. One binary.");
let sub = el("p", "text-lg text-gray-700 leading-relaxed mb-6", "writeonce is a language whose compiler, runtime, web server and " .. "database ship as a single never-stopping Linux binary. Ownership-" .. "checked memory, inferred GC where ownership cannot reach, actors " .. "on every core — and the page you are reading is served by it."); let sub = el("p", "text-lg text-gray-700 leading-relaxed mb-6", "writeonce is a language whose compiler, runtime, web server and " .. "database ship as a single never-stopping Linux binary. Ownership-" .. "checked memory, inferred GC where ownership cannot reach, actors " .. "on every core — and the page you are reading is served by it.");
let ctas = el("div", "flex items-center justify-center gap-4", btn_link("/ch/hello", "Get started", true) .. btn_link("https://github.com/shoneyj", "View source", false)); let ctas = el("div", "flex items-center justify-center gap-4", btn_link("/ch/hello", "Get started", true) .. btn_link("https://github.com/shoneyJ/writeonce", "View source", false));
let hero = el("div", "text-center py-16", h1 .. sub .. ctas); let hero = el("div", "text-center py-16", h1 .. sub .. ctas);
-- code showcase: a real flavor of the language -- code showcase: a real flavor of the language

View file

@ -5,7 +5,7 @@ pub fn header() -> Text {
let links = link("/install", "text-gray-700", "Install"); let links = link("/install", "text-gray-700", "Install");
links = links .. link("/ch/hello", "text-gray-700", "Tutorial"); links = links .. link("/ch/hello", "text-gray-700", "Tutorial");
links = links .. link("/packages", "text-gray-700", "Packages"); links = links .. link("/packages", "text-gray-700", "Packages");
links = links .. link("https://github.com/shoneyj", "text-gray-700", "GitHub"); links = links .. link("https://github.com/shoneyJ/writeonce", "text-gray-700", "GitHub");
-- The brand is the mark plus the wordmark, one inline-flex row so the -- The brand is the mark plus the wordmark, one inline-flex row so the
-- tile and the text share a baseline at any font size. -- tile and the text share a baseline at any font size.
let brand = el("span", "flex items-center gap-2", logo_svg(28) .. "<span>writeonce.de</span>"); let brand = el("span", "flex items-center gap-2", logo_svg(28) .. "<span>writeonce.de</span>");