# ADR-website-001: Public website and documentation site

## Status

Accepted (2026-06-04). Implementation plan:
[`docs/website/plans/20260604-website-implementation-plan.md`](../plans/20260604-website-implementation-plan.md).

> History: drafted as ADR-0042, renamed to ADR-0044 (each collided with a
> number `main` had independently assigned — H1a took 0042, compound-PK FK
> took 0043, then relationship-visualization took 0044). Moved to the
> website ADR namespace (`docs/website/adr/`, id **ADR-website-001**) on
> 2026-06-10 to end the recurring cross-branch number collision: website
> decision records now draw from their own dated sequence and never the
> main global ADR pool (see ADR-0000 "Numbering discipline"). Content is
> unchanged from the original draft.

## Context

RDBMS Playground is nearing its first public release and needs a public
website that does two jobs: **attract** — a landing page that shows the
playground in action — and **document** — a thorough, canonical reference
for everything the playground can do.

The documentation-heavy surface is already implemented and verified (full
simple- and advanced-mode command set, the ten-type vocabulary,
relationships, constraints, indexes, EXPLAIN, undo/history/replay, projects,
export/import, the teaching echo, clipboard, friendly errors, tab completion
and syntax highlighting; 2151 tests passing at the time of writing). The
site is therefore largely a presentation-and-writing effort, not a
wait-for-features one. A grounded inventory of what is shippable now lives
in the implementation plan.

Several choices here had no canonical default; they were settled during a
planning + `/runda` pass with the user and are recorded below.

## Decision

1. **Stack — Astro 6 + Starlight + Tailwind v4.** Astro's content-first,
   zero-JS-by-default model with the Starlight docs theme fits a
   marketing-landing-plus-heavy-docs site better than the alternative
   considered, SvelteKit + Tailwind (the usual go-to here). Interactive
   pieces are added as Astro islands (Svelte or vanilla), so Svelte is still
   available where it earns its place. Tailwind v4 is wired via the official
   `@tailwindcss/vite` plugin; the `@astrojs/starlight-tailwind` plugin
   bridges Tailwind with Starlight's theming.

2. **Demo medium — asciinema.** Showcase sequences are recorded as
   asciinema `.cast` files (text-based, small, faithful to the full
   alternate-screen render) and embedded with `asciinema-player`. The same
   casts are reused inline in the docs — one recording format serves both
   the landing page and documentation enrichment. Recordings are produced by
   a **scripted-input driver** that types commands into a real PTY with
   viewer-friendly pacing; the app's own `history.log` **replay** (ADR-0034)
   re-executes commands without typing animation or pacing and is therefore
   suitable only for state-deterministic docs snippets, not the hero demo.

3. **In-page WASM playground — deferred** (OOS: **deferred**, not rejected).
   A live, type-it-yourself playground compiled from the Rust app to
   WebAssembly is desirable but is a multi-week sub-project, so it does not
   block the site. The demo section is designed with a stable seam (a single
   `Demo` component contract) so a WASM playground island can replace the
   asciinema player later with no change to call sites. Recorded boundary
   for that future work:
   - **Portable core (runs on `wasm32-unknown-unknown` largely as-is):**
     `src/dsl/*` (parser, types, grammar, walker), the pure `App::update()`,
     `ui.rs`, `theme.rs`, `friendly/*`, output rendering; an in-memory DB
     path already exists (`Connection::open_in_memory()`). `rusqlite`
     compiles to the browser target via its `ffi-sqlite-wasm-rs` feature.
   - **Native edge needing `cfg`-gated browser replacements:** the
     multi-thread Tokio runtime + the dedicated DB **worker thread**
     (ADR-0010) → current-thread/in-line async; `crossterm` terminal +
     event-stream → a browser backend (e.g. Ratzilla's DOM/Canvas) + DOM
     events; `arboard`, `zip`, file persistence (ADR-0015), file logging;
     and the rusqlite **backup-API** undo (ADR-0006) → a SQL dump/restore.
   When taken up, this becomes its own ADR + iteration plan.

4. **Hosting — portable static build; Cloudflare is the target (decided
   2026-06-11).** Astro 6 builds to static HTML/CSS with no adapter, so the
   output deploys equally to Cloudflare, Vercel, Netlify, or GitHub Pages — we
   stay uncoupled from any one host. **Planned pipeline: Gitea Actions →
   Cloudflare.** Cloudflare now steers new projects to **Workers (static
   assets)** over Pages; either serves the static `dist/` and needs no Astro
   adapter (the `@astrojs/cloudflare` adapter is only for SSR, which the site
   does not use). The future in-page WASM playground (§3), if it needs
   COOP/COEP headers, can get them from Cloudflare `_headers`. **CI implemented
   2026-06-15** (`.gitea/workflows/website.yaml`): a push touching `website/**`
   builds the static site with pnpm and deploys `dist/` to the Cloudflare Pages
   project **`relplay`** via `wrangler` (Direct Upload — no Git integration).
   The `--branch` label selects environment against the project's production
   branch (`main`): **`main` → production (`relplay.org`)**, **`website` →
   preview (`website.relplay.pages.dev`)**, with `staging.relplay.org` attachable
   to the `website` branch alias. The crate's CI gate (`ci.yaml`) skips
   website-only pushes; the build is pure-Node (the `.cast` files are committed,
   so no cargo). Secrets: `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID`.

5. **Repo topology — monorepo.** The site lives under `website/` in the
   playground repo; the crate stays at the repo root. The repo as a whole
   moves to its public home later; site and crate travel together.

6. **Canonical docs home — the website.** User-facing documentation lives on
   the site. In-repo `docs/` keeps ADRs, handoffs, and development notes;
   `docs/simple-mode-limitations.md` (requirement DOC1) was a development aid
   and now *feeds* the site's content rather than competing with it. The
   sharing recipes promised by requirement E2 become a docs page.

7. **Documentation scope and conventions.** Document the **full supported
   feature set**. Any capability not yet fully implemented (a small minority
   — e.g. multi-line input, query cancellation, `seed`, `m:n` convenience,
   ER-diagram export, the `show tables`/`relationships`/`indexes` family) is
   either omitted or carries a clear **"planned / not yet available"**
   callout — never presented as shipped. Two wording rules bind all
   user-facing copy:
   - **No engine name** (SQLite/STRICT/rusqlite/PRAGMA) — continues the
     user-facing posture of ADR-0002; copy says "the database"/"the engine".
   - **No "DSL"** — it is internal jargon. The two input modes are **simple
     mode** (the playground's keyword command language) and **advanced
     mode** (SQL).

8. **Install documentation — two mechanisms.** The install page documents
   **prebuilt release binaries** (self-hosted download — not GitHub
   Releases, since the repo will move) and **package managers**. Both can be
   written now against the planned mechanisms; concrete download URLs slot in
   at release. (Distribution items D1–D3 in `requirements.md` remain the
   tracking home for the release tooling itself.)

## Consequences

- The site can ship on the strength of already-implemented features; it is
  gated on writing and recording, not on finishing the app.
- One recording format (asciinema `.cast`) serves both marketing and docs,
  and is reusable as the app evolves (re-run the script, re-record).
- The WASM playground is preserved as a real future option without holding
  up launch; the demo seam keeps the upgrade cheap.
- A single canonical docs home removes the divergence risk of maintaining
  user docs in two places.
- Website build choices (Decisions 1, 2, 4, 5) are recorded here for
  traceability but do not, by themselves, warrant further ADRs; only
  app-architecture decisions (notably the future WASM port) will.

## Out of scope

- **In-page WASM playground** — *deferred* (see Decision 3); revisit as its
  own ADR + iteration plan.
- **Hosted/SaaS playground or a server-backed doc CMS** — *rejected*: a
  static site fully satisfies the need, consistent with ADR-0007's
  no-hosted-publishing stance. Revisit only if real demand emerges.
