Files
rdbms-playground/website/STYLE.md
T
claude@clouddev1 6777216e37 feat(website): set production site URL (relplay.org); record Phase B decisions
Set Starlight `site` to https://relplay.org (apex) — enables the
sitemap, canonical URLs, and Open Graph URL resolution; clears the
sitemap build warning. Record the resolved STYLE.md decisions:
single-version launch, fixed-dark cast theme (casts bake RGB colours,
so light/dark would need dual-theme recordings), and the site origin.
2026-06-11 15:36:29 +00:00

248 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Documentation style guide (living)
This is the **living** home for documentation authoring conventions for the
RDBMS Playground website. It grows as we write.
- **Binding rules** come from
[ADR-website-001 §7](../docs/website/adr/20260604-adr-website-001.md);
this guide must not contradict them. If a convention is significant,
durable, or contested, it is decided in an **ADR** (new or amended), and
this guide references it. Finer, settled conventions live here directly.
- **Open decisions** (not yet settled) are tracked at the bottom so we
decide them deliberately rather than re-deciding per page. When one
settles, move it up into the body (and to an ADR if it's significant).
Status tags used below: **[DECIDED]** (binding or settled) ·
**[OPEN]** (to be decided — see the log).
---
## Terminology & wording [DECIDED — ADR-website-001 §7]
- **No "DSL".** It is internal jargon. Use **simple mode** (the playground's
keyword command language) and **advanced mode** (SQL).
- **No engine name.** Never name SQLite / STRICT / rusqlite / PRAGMA in
user-facing copy. Say **"the database"** or **"the engine"**. (Continues
the user-facing posture of ADR-0002.)
- Preferred terms (extend as we go): "command", "project", "table",
"column", "relationship" (the user-facing word for a declared foreign-key
link), "constraint", "index".
- Add new banned/preferred terms here as they come up, with a one-line
reason.
## Voice & tone [DECIDED, refine as needed]
- **Teaching-first.** Pedagogy wins ties (CLAUDE.md). Explain the *why*, not
just the *how*; the audience spans beginners through learners ready for
raw SQL.
- Second person ("you"), present tense. Imperative mood for step
instructions ("Create a table…").
- Prefer short sentences and concrete examples over abstract prose.
## Structure [DECIDED]
Pragmatic, Diátaxis-influenced split (five top-level sidebar sections,
autogenerated per directory under `src/content/docs/`):
- **Getting started** — install, first project, simple vs. advanced, the
example database.
- **Using the playground** — *the application you drive*, kept distinct from
the database-language Reference: command-line options, the assistive editor
(completion / highlighting / `[ERR]`/`[WRN]` indicator / hints / in-line
editing), the output pane (scrolling), projects (save/load/new/rebuild),
undo & history, export & import, clipboard, getting help. (ADR-0003's
"app-level commands" + ADR-0022/0027 typing assistance + the CLI.)
- **Guides** — task-oriented how-tos. *These are the most important didactic
content and will be iterated for teaching quality before publication.*
- **Reference** — the exhaustive command/SQL/type surface. **Page
granularity: one page per topic / command-family** (Tables, Columns,
Relationships, Indexes, Constraints, Inserting & editing data, Querying,
Types, …), each covering the simple-mode and advanced-mode forms where
both apply. Hand-written now (the command surface is settled bar H1a
output); small post-release adjustments are expected and fine.
- **Concepts** — the "why": projects & storage, undo & history, etc.
Ground every reference page in source — `parse.usage.*` and `help.*` in
`src/friendly/strings/en-US.yaml`, `src/dsl/command.rs`, `src/dsl/types.rs`
— never paraphrase grammar from memory.
## "Planned / not yet available" callouts [DECIDED — ADR-website-001 §7]
Any capability that is not yet fully implemented is **omitted** or carries a
clear callout — never presented as shipped. Standard form: a Starlight aside
```md
:::caution[Planned]
This is planned and not yet available.
:::
```
## Examples & code [DECIDED]
- **Shared example database: a small library** — `authors`, `books`,
`members`, `loans` (see the canonical schema below). Reuse it across all
pages so readers build familiarity; it models 1:n (an author has many
books) and m:n (books ↔ members, through loans).
- Where both modes apply, show the **simple-mode** form and its
**advanced-mode (SQL)** equivalent — the in-app teaching echo already
pairs these, so docs mirror it.
- Prefer **worked examples** (a real command on the library schema) over
abstract prose, and **always cross-link** the related reference/guide
pages (use stubs so links resolve before a page is written).
- Code blocks for exact input/output; reserve casts for motion/flow.
### Code-block fences
- **Simple-mode commands → ` ```rdbms `** — custom highlight grammar in
`src/grammars/rdbms.mjs`, registered with Expressive Code in
`astro.config.mjs` (keywords + types coloured).
- **Advanced-mode SQL → ` ```sql `**; shell / install → ` ```sh `.
- A decorative `> ` prompt is prepended to `rdbms` lines via CSS
(`src/styles/global.css`) — **do not type `>` in the fence**. It is
copy-safe (Expressive Code's copy button uses `data-code`) and
`user-select:none`.
- **One command per line** in an `rdbms` block; a multi-line single
statement (e.g. advanced `CREATE TABLE`) belongs in a ` ```sql ` block,
where no prompt is added.
- **Command output → a plain unlabelled ` ``` ` fence** placed immediately
after the command block (no language, so no `> ` prompt and no
highlighting). Output must be **captured from the real app**, never
hand-drawn — box-drawing diagrams, query-plan trees, and data tables are
copied verbatim (trailing padding spaces trimmed). The capture method: a
throwaway in-crate test that builds the canonical library schema and prints
the rendered output (`render_structure_with_diagrams`,
`render_relationship_diagram`, `render_data_table`, `render_explain_plan`,
`show_list`), removed once the output is pasted. Colour is lost in a static
block (the structure still reads); the coloured/animated rendering is
earmarked for casts.
### Canonical library schema (source of truth for examples)
Use these exact names/types in every example:
| Table | Columns (playground types) |
|-----------|---------------------------------------------------------------------------------------------|
| `authors` | `author_id` serial (pk) · `name` text (not null) · `birth_year` int |
| `books` | `book_id` serial (pk) · `title` text (not null) · `author_id` int (→ authors) · `published` int · `isbn` text (unique) |
| `members` | `member_id` serial (pk) · `name` text (not null) · `joined` date |
| `loans` | `loan_id` serial (pk) · `book_id` int (→ books) · `member_id` int (→ members) · `loaned_on` date · `returned_on` date |
Relationships: `books.author_id → authors.author_id` (1:n); `loans` joins
`books` and `members` (the m:n bridge). Show `shortid` on the Types page via
a small standalone example, not by complicating this schema.
## asciinema casts [DECIDED]
- Casts show *flow/motion*; static code blocks show *exact input/output*.
Prefer a code block when a still example suffices.
- Pair a hero/landing cast with a text transcript or the equivalent docs
snippet (accessibility + SEO).
### Where to use a cast [DECIDED 2026-06-10]
**Rule: a cast wherever the app *does something*.** A cast at the top of a page
gives the reader the *shape* of what the page describes — quickly and visually
— with the detailed text below for when they need it. (This helps visual
learners, but is valuable more broadly.) Concretely:
- **Broadly** on the pages about *doing / interacting*: the landing, **Getting
started** (first project, modes), **Using the playground** (the assistive
editor, output-pane scrolling, undo/redo, projects, copy, export/import), and
**Guides**.
- **Selectively** on **Reference** — only where motion beats the still (e.g.
the relationship diagram being drawn; a query plan appearing). Reference
pages keep their **captured static output** regardless; a cast complements,
never replaces it.
- **Skip** pure-lookup / conceptual pages with nothing to animate (e.g. the
Types table, prose Concepts pages).
- A cast is **selective**: it shows a chosen, representative slice of what the
page documents — it need not exercise every command on the page.
- **Autoplay only the landing hero**; elsewhere casts are click-to-play (a
poster frame) so they don't all clamor at once. All casts re-record in one
`pnpm casts` run, so breadth stays maintainable.
### Cast pacing & clarity [DECIDED 2026-06-11]
- **Give the viewer a beat before a command is submitted.** A command that is
typed and `Enter`-ed in the same instant vanishes before the viewer can read
it. Type, **pause**, then submit — especially for **modal confirmations**
(e.g. the `save as` name prompt) and short commands (`new`): script the text
and the `Enter` as *separate* steps with a pause between (`{ type: 'x',
enter: false, after: … }` then `{ key: 'Enter', after: … }`).
- **Surface state where the schema sidebar would.** At the cast width (90 cols)
the schema sidebar is hidden (ADR-0046 hides it at ≤90 cols), so the viewer
can't see tables/relationships appear and disappear. Insert `show tables` /
`show table <T>` / `show data <T>` at the points where state **changes**, so
a sequence reads clearly (e.g. the projects cast shows `show tables` before
saving, after `new`, and after loading — table present → none → present).
- **Driver: `autocast`** (ADR-website-001 §2; chosen by the 2026-06-10
spike). `autocast`'s `!Interactive` feeds keys to the running TUI and
captures the redraw — the correct model for a full-screen crossterm app.
`asciinema-automation` was rejected: it assumes *shell* semantics (Enter as
`\n`, and an `expect()` echo-check per keystroke), which a redrawing TUI
breaks — it produced a garbled cast.
- **Authoring workflow.** Source command-lists live in `casts-src/casts.mjs`
(human-readable steps: `type` / `wait` / `key`). `pnpm casts` runs
`casts-src/generate.mjs`, which expands them to autocast YAML (one key per
character; Enter = `^M`) and records to `public/casts/<name>.cast`. The
command-lists are the durable source; **`.cast` files are regenerable** —
re-run `pnpm casts` to re-record as the app evolves (a final sweep is due
once the app is locked). Needs a `cargo build` binary at `../target/debug`.
- **Embedding.** `Demo.astro` (the WASM-swap seam, ADR-website-001 §3) wraps
`Cast.astro` (asciinema-player island). Call sites use `Demo`.
- **Conventions.** Terminal geometry per cast (default 90×26); file name =
cast `name`; player theme `asciinema`. **Cast theme — fixed dark for launch
(DECIDED 2026-06-11).** Casts bake the app's dark theme into the recording as
RGB SGR codes, so the player theme can't recolour them; true light/dark would
require recording light-theme cast variants and swapping via the `Demo` seam.
Deferred as not worth the doubled asset/recording cost for launch; revisit
with the eventual full re-record.
## Formatting [DECIDED, refine]
- Starlight asides for notes/tips/cautions; tables for reference matrices
(types, constraints, referential actions).
- Keyboard keys rendered consistently (e.g. <kbd>Ctrl</kbd>+<kbd>Z</kbd>).
- Cross-link related pages; never expose ADR numbers or internal jargon to
the reader (ADRs are for us, not the docs audience).
---
## Open decisions log
Decide these as we write; record the outcome (and escalate to an ADR if
significant).
**Resolved (2026-06-10):**
9. ~~Cast scripting toolchain~~**`autocast`**, proven by spike over
`asciinema-automation` (which can't drive a full-screen TUI). Source
command-lists in `casts-src/`, `pnpm casts` to record. See the *asciinema
casts* section above. (Remaining sub-item: light/dark player theme sync —
folded into #8 / Phase B.)
**Resolved (2026-06-05):**
1. ~~Depth / organising spine~~**Pragmatic** four-section split (see
Structure above).
2. ~~Page granularity~~**one page per topic / command-family**, both
modes per page (see Structure).
3. ~~Standard example dataset~~**the library** (schema above).
4. ~~Simple-vs-advanced pairing~~**show both where both apply** (see
Examples).
5. ~~"Planned" callout~~ → standard `:::caution[Planned]` aside (see above).
6. ~~Reference generation vs hand-writing~~**hand-write now** (command
surface is settled bar H1a output; small later adjustments expected).
**Resolved (2026-06-11):**
7. ~~Versioning~~**single-version for launch.** No version selector; one can
be added at/after v1 if the docs ever need to diverge by version.
Cast light/dark → **fixed dark for launch** (see *asciinema casts* above).
`site` set to **`https://relplay.org`** (apex) — enables sitemap, canonical,
and Open Graph URL resolution; a `www` host, if used, 301-redirects to apex.
**Still open:**
8. **SEO/meta — remaining.** Per-page titles/descriptions are set; canonical +
basic Open Graph (`og:title`/`og:url`) now auto-generate from `site`. What
remains: **Open Graph social-card images** (`og:image`) — needs a card
design, so it travels with the branding work (logo + palette, TBD with the
user; the existing favicon is *not* a brand guideline).