5.3 KiB
STCourses v1.1 Plan
For agentic workers: each work package below is owned by one agent in its own git worktree (branch
feat/v11-<id>, created frommain). The agent writes its own detailed TDD plan atdocs/superpowers/plans/2026-10-30-v11-<id>.mdin the format ofdocs/superpowers/plans/2026-10-30-stcourses.md, then executes it. Spec:docs/superpowers/specs/2026-10-30-stcourses-design.md. Project rules:CLAUDE.md.
Goal: five improvements to v1:
- navigation motion (from user feedback);
- editing imported courses in the studio;
- a smaller first load;
- the deferred AI schema work;
- cleaning up stale dev scripts.
Global Constraints
- Everything in
CLAUDE.md"Project rules" applies. - Motion:
- only light, purposeful motion: 120–220 ms, ease-out;
- opacity and short (≤ 8 px) translate only;
- no bounce, no scale-pop, no parallax;
prefers-reduced-motion: reduceturns all of it off;- motion must never delay input or block navigation.
- No new colours or fonts.
- Every DB change is a new portable migration that runs on SQLite and Postgres.
- Every change keeps
bun test,bun run typecheckand the Postgres run green.
Work packages
M — Navigation motion (branch feat/v11-motion)
User feedback: "the navigation between courses, pages and steps could need some light animations and not switch as hard."
Scope:
- route changes in the shell;
- library to course;
- lesson to lesson, including previous/next and the floating action bar;
- module expand/collapse in the sidebar;
- deck slide changes;
- hint/fold open/close;
- progress bar fills;
- toasts and overlays.
Approach:
- Use the View Transitions API (
document.startViewTransition) where the browser supports it, with a CSS-only fallback (a fade-in of the new content). - Keep the sidebar and header stable during lesson changes, so they don't flash. Only the lesson column transitions.
- Restore scroll position correctly.
- Lesson content should appear as a quick fade plus a 4–6 px rise.
<details>folds animate their height with theinterpolate-size/::details-contentpattern where supported, and open instantly otherwise.
Acceptance:
- headless-Chrome screenshots or recordings of mid-transition frames;
- no layout shift of the sidebar;
- a reduced-motion test shows no animation;
- no added JS dependency over 5 KB.
S — Edit imported courses in the studio (branch feat/v11-studio-import)
Resolves the v1 TODO TODO(studio): convert imported course to a studio-managed repo (ruling R9).
Scope:
- Add an owner-only action, "Make editable in the studio", for imported courses under
<dataDir>/courses/<id>. - It creates
<dataDir>/studio/repos/<id>.gitfrom the course folder.- Large media are NOT committed into git: they stay referenced in place, and the manifest paths keep working.
- Use
.gitignoreplus a media reference, or Git LFS only if it's already available. Document the choice.
- After conversion the course is served from the studio's published worktree. The original import folder is kept read-only as the media source, or moved under
<dataDir>/media/<id>; pick one and document it. - The id stays the same, so learners' progress and notes are kept.
- Visibility stays restricted until the owner changes it.
Acceptance: convert a synthetic imported course, edit a lesson title, publish, and confirm the learner sees the change, existing progress and notes survive, and media still play with Range requests.
P — Smaller first load plus cleanup (branch feat/v11-perf)
v1 ships one JS file of about 1.8 MB plus 1.47 MB of CSS and fonts.
Scope:
- Code-split per feature route (lazy chunks for studio, import, AI and admin; the learner reader and library stay in the main chunk).
- Load the heavy libraries only where they are used:
- pdf.js only in the deck viewer;
- sanitize-html only where lesson HTML is rendered.
- Fonts: latin plus latin-ext subsets only,
font-display: swap, and only the weights actually used. - Long-cache headers for hashed assets in production.
Targets for the initial library page in a production build: at most 600 KB of JS gzip, and at most 350 KB of fonts and CSS. Measure and report before and after.
Cleanup:
- remove or update the stale per-package dev scripts (
packages/*/dev/serve.ts,scripts/dev.ts), now superseded byapps/server; - update READMEs and
docs/operations.md.
A — Deferred AI contract requests 3–5 (branch feat/v11-ai)
From docs/contract-requests/ai.md:
- (3) Tool calls as structured fields on
ChatMessage, with providers updated (Anthropic tool_use/tool_result blocks, OpenAI tool_calls). - (4) A per-course mentor setting stored in its own table instead of the generic
ai_settingsJSON. Migrate existing rows. - (5) A citations column on
ai_messages, so the UI renders citations from data rather than re-parsing text.
New migrations go in the AI package's migrations directory and must run on both DBs, with an upgrade test from the v1 schema. Also encrypt MCP env/headers at rest with the same AES-GCM/HKDF scheme as BYOK keys, never returning them in full to the UI (only masked). This was a v1 deferred minor.
Order
M, S and A run in parallel. P starts after M is merged, because both touch the web shell and bundling. Each package gets a task review (and fix rounds) before merging, and a final whole-branch review runs on main at the end.