diff --git a/.gitignore b/.gitignore index 09a2363..c2c69fe 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,5 @@ pnpm-debug.log* docs/designs/_ref +.qoder/ diff --git a/bun.lock b/bun.lock index 9db730e..8dc909d 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,7 @@ "name": "orchids-project", "dependencies": { "@astrojs/sitemap": "3.7.3", + "@libredb/libredb": "0.1.3", "@tailwindcss/vite": "4.3.1", "astro": "7.0.3", "tailwindcss": "4.3.1", @@ -235,6 +236,8 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@libredb/libredb": ["@libredb/libredb@0.1.3", "", { "bin": { "libredb": "dist/cli/main.js" } }, "sha512-TuQRLz+sEIx0YJSvT9tiin4yehpqdG1kalPgVtnGhw78JmgUsLryS3/sbNMI2X3sTxE+8Gel7CvUim6s2azYDQ=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="], diff --git a/docs/superpowers/plans/2026-06-30-playground-opfs-editor.md b/docs/superpowers/plans/2026-06-30-playground-opfs-editor.md new file mode 100644 index 0000000..e4e13dc --- /dev/null +++ b/docs/superpowers/plans/2026-06-30-playground-opfs-editor.md @@ -0,0 +1,1066 @@ +# /playground OPFS Editor Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a public `/playground` route that runs a real OPFS-backed LibreDB entirely in the browser — preloaded sample data, a clickable command cheatsheet, reset, and graceful in-memory fallback — with no backend and no login. + +**Architecture:** A SSR-safe Astro page reuses the site's `StudioShell` chrome and mounts a client-only island. The engine runs in a Web Worker (OPFS sync-access handles are Worker-only); the UI talks to it over `postMessage`. Pure, testable modules (`protocol`, `engine`) hold the command grammar and lens dispatch; the worker and client are thin shells around them. + +**Tech Stack:** Astro 7 (static, no React), TypeScript (strict), Tailwind 4, `@libredb/libredb@0.1.3` (`/browser` entry), `bun:test`, Playwright (MCP) for browser verification. + +## Global Constraints + +- Import the engine **only** from `@libredb/libredb/browser` (its import graph reaches no `node:` module). Never import the bare `@libredb/libredb`. +- **No engine/DOM/Worker code may run during SSR.** All engine code lives in the Worker or in client ` +``` + +- [ ] **Step 3: Create `src/pages/playground.astro`** + +```astro +--- +import Layout from "../layouts/Layout.astro"; +import StudioShell from "../components/studio/StudioShell.astro"; +import Playground from "../components/studio/Playground.astro"; +--- + + + + + + +``` + +- [ ] **Step 4: Add the nav link in `src/components/studio/TopBar.astro`** + +Read the file first. Find the existing top-bar link/menu markup and add, following the surrounding pattern, a link whose `href="/playground"` labeled `Playground`. Do **not** modify `src/data/sections.ts` (that drives the schema explorer rows and homepage nav). Keep the change to a single anchor consistent with the existing nav items. + +- [ ] **Step 5: Verify it builds and renders** + +Run: `bun run build 2>&1 | tail -25` +Expected: build succeeds; `dist/playground/index.html` exists. +Then revert the build-mutated compose files: +Run: `git checkout -- src/data/docker-compose.example.yml public/docker-compose.example.yml 2>/dev/null; git status --short` +Expected: only the new/intended files show as changes. + +- [ ] **Step 6: Commit** + +```bash +git add src/components/studio/Cheatsheet.astro src/components/studio/Playground.astro src/pages/playground.astro src/components/studio/TopBar.astro +git commit -m "feat(playground): editor pane, cheatsheet, route, nav link (#19)" +``` + +--- + +## Task 6: Gate + browser verification (Playwright) + +**Files:** none created — verification only. + +- [ ] **Step 1: Run the full gate** + +Run: `bun run gate 2>&1 | tail -30` +Expected: typecheck, format, lint, knip, and all `bun:test` pass. Fix any failures (likely knip on unused exports — ensure every new export is consumed; prettier — run `bun run format:fix`). + +- [ ] **Step 2: Serve the production build with caching disabled** + +Run (background): `bunx http-server dist -p 8081 -c-1` +(Use a cache-disabled static server per the repo's VT runtime-testing note.) + +- [ ] **Step 3: Playwright — load and assert seed renders** + +Navigate to `http://localhost:8081/playground`. Take a snapshot. Assert: +- The result grid shows the 3 seeded users (Ada, Linus, Grace). +- The persistence badge reads `OPFS · persistent` (Chromium on localhost is a secure context with OPFS). + +- [ ] **Step 4: Playwright — click-to-run, persist, reset** + +- Click the cheatsheet button `insert into users {"id":"4","name":"Lin","age":29,"active":true}`, then `select * from users` → assert a 4th row `Lin` appears. +- Reload the page → assert `Lin` is still present (OPFS persistence across reload). +- Click `↺ Reset sandbox` → assert the grid returns to exactly the 3 seed rows. +- Click `prefix config:` → assert key/value rows for `config:*` render. + +- [ ] **Step 5: Confirm no `node:` in the client bundle** + +Run: `grep -rl "node:fs\|require(\"fs\")\|node_fs" dist/assets/*.js | head` (or scan the playground chunk). +Expected: no matches — the browser entry pulled no `node:` module into the client bundle. + +- [ ] **Step 6: Final commit (if any verification fixes were needed)** + +```bash +git add -A && git commit -m "test(playground): gate fixes + browser-verified OPFS demo (#19)" +``` + +--- + +## Self-Review + +- **Spec coverage:** Public no-login route (Task 5) ✓ · client-side OPFS Worker, no backend (Tasks 3,6) ✓ · 3-lens seed (Task 2) ✓ · clickable palette (Tasks 4,5) ✓ · persist + isolate + reset (Tasks 3,6) ✓ · no `node:fs`, marketing build unaffected (Task 6, TopBar-only nav change) ✓ · in-memory fallback + notice (Tasks 3,4,5) ✓ · `db.close()` teardown (Tasks 3,4) ✓ · no SSR engine code (Task 5 client-only ` diff --git a/src/components/studio/TopBar.astro b/src/components/studio/TopBar.astro index 9bca776..2c80247 100644 --- a/src/components/studio/TopBar.astro +++ b/src/components/studio/TopBar.astro @@ -43,6 +43,9 @@ const DEMO = 'https://app.libredb.org'; data-action="notice" data-notice="monitoring"> Monitoring + + Playground +