Files
claude@clouddev1 77c55fa669 docs(website): document the seed command, with cast (ADR-0048)
New Reference page "Generating sample data" (captured output + a
two-table seed cast showing generation, FK sampling context, and a
`set` override); cross-links from inserting-and-editing-data and
columns; seed added to the rdbms highlight grammar;
querying/sql-queries renumbered. Cast stance in STYLE.md revised to
"justify the absence". Refs #33, #34.
2026-06-12 14:41:37 +00:00

255 lines
14 KiB
Markdown
Raw Permalink 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; stance revised 2026-06-12]
**Default to a cast; justify its _absence_, not its presence.** 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. It
earns its place two ways, both observed in real use: it helps **visual
learners** grasp a flow at a glance, and it gives **advanced learners a fast
entry point and overview** — skim the motion, then drop into the prose only
where needed. So the question for each page is not "does this deserve a cast?"
but "is there a good reason *not* to have one?"
This is **not** a mandate for a cast on every page, still less several per
page: a page wants a cast only where the app *does something* worth seeing, and
one well-chosen cast is almost always enough. Concretely:
- **Expect a cast** on any page where the app *does or shows* something: the
landing, **Getting started**, **Using the playground**, **Guides**, and the
**Reference** command pages (a command being run, a diagram drawn, a query
plan or a table of generated rows appearing).
- **Justify the absence** on the rest — pure-lookup or conceptual pages with
nothing to animate (e.g. the Types table, prose Concepts pages). "Nothing
moves here" is a fine reason to record on; "I didn't think about it" is not.
- Reference pages keep their **captured static output** regardless; a cast
complements it, never replaces it.
- 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).