feat(website): projects cast (vi-nav load picker) + --demo on all casts

- New projects cast: create → save as library → new (fresh) → load → navigate
  the picker to the saved project (j, now possible via #24 vi-nav) → Enter
  loads it, the table is restored. Runs under an isolated --data-dir so the
  picker lists only this cast's projects.
- Turn on the demonstration overlay (--demo, #22 / ADR-0047) for ALL casts,
  for a consistent viewer experience: special keys show a badge — e.g.
  [ENTER], and [TAB] at the assistive-editor's completion moment, finally
  making that keystroke visible. Plain j/k navigation stays unbadged, so the
  picker navigation is not surfaced.
- Generator: per-cast `dataDir` (isolated data root) + default-on `--demo`
  (opt out with demo:false). All 7 casts regenerated.

Convert projects.md → .mdx and embed. Build clean (26 pages). Visual playback
of all casts pending a tunnel check.
This commit is contained in:
claude@clouddev1
2026-06-11 10:17:04 +00:00
parent 927e6b2d50
commit e782a280cc
10 changed files with 2370 additions and 2145 deletions
+20 -3
View File
@@ -110,10 +110,18 @@ function trimCast(outPath, { holdEnd = 1.5 } = {}) {
);
}
function yamlFor(cast) {
function yamlFor(cast, dataDir) {
const keys = keysFor(cast.steps)
.map((k) => ` - ${k}`)
.join('\n');
// Build the launch command. `--demo` turns on the demonstration overlay
// (ADR-0047): automatic keystroke badges (so otherwise-invisible keys like
// `j` / Tab / Enter are shown) plus `Ctrl+]`-delimited step captions.
// `--data-dir` isolates the recording from the user's real projects (and
// keeps the load picker listing only this cast's projects).
const cmd = ['rdbms-playground'];
if (cast.demo !== false) cmd.push('--demo'); // on for all casts (opt out with demo:false)
if (dataDir) cmd.push('--data-dir', dataDir);
return [
'settings:',
` width: ${cast.width ?? 90}`,
@@ -124,7 +132,7 @@ function yamlFor(cast) {
' prompt: "$ "',
'instructions:',
' - !Interactive',
' command: rdbms-playground',
` command: ${cmd.join(' ')}`,
' keys:',
keys,
'',
@@ -145,7 +153,16 @@ let failures = 0;
for (const cast of selected) {
const yamlPath = resolve(os.tmpdir(), `autocast-${cast.name}.yaml`);
const outPath = resolve(outDir, `${cast.name}.cast`);
writeFileSync(yamlPath, yamlFor(cast));
// Per-cast isolated data root (so the load picker lists only this cast's
// projects and nothing touches the user's real data dir). Wiped fresh each
// run for a deterministic picker order.
let dataDir = null;
if (cast.dataDir) {
dataDir = resolve(os.tmpdir(), `rdbms-cast-data-${cast.name}`);
rmSync(dataDir, { recursive: true, force: true });
mkdirSync(dataDir, { recursive: true });
}
writeFileSync(yamlPath, yamlFor(cast, dataDir));
console.log(`▶ recording ${cast.name} → public/casts/${cast.name}.cast`);
const res = spawnSync('autocast', ['--overwrite', yamlPath, outPath], {
env,