From fd5c72afc2e7881be59b614143e04dbb73e4345e Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Fri, 30 Oct 2026 20:21:39 +0100 Subject: [PATCH] docs: v1.1 plan (motion, studio import editing, perf, AI schema) Co-Authored-By: Claude Opus 5.5 --- docs/superpowers/plans/2026-10-30-v1-1.md | 92 +++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/superpowers/plans/2026-10-30-v1-1.md diff --git a/docs/superpowers/plans/2026-10-30-v1-1.md b/docs/superpowers/plans/2026-10-30-v1-1.md new file mode 100644 index 0000000..a4cd8da --- /dev/null +++ b/docs/superpowers/plans/2026-10-30-v1-1.md @@ -0,0 +1,92 @@ +# STCourses v1.1 Plan + +> **For agentic workers:** each work package below is owned by one agent in its own git worktree (branch `feat/v11-`, created from `main`). The agent writes its own detailed TDD plan at `docs/superpowers/plans/2026-10-30-v11-.md` in the format of `docs/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: reduce` turns 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 typecheck` and 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. +- `
` folds animate their height with the `interpolate-size` / `::details-content` pattern 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 `/courses/`. +- It creates `/studio/repos/.git` from the course folder. + - Large media are NOT committed into git: they stay referenced in place, and the manifest paths keep working. + - Use `.gitignore` plus 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 `/media/`; 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 by `apps/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_settings` JSON. 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.