Editor lessons
The editor lessons walk the TypeScript application client at
editor/.
Run the dev server:
pnpm --filter editor devL01 — Express + TypeScript baseline
Section titled “L01 — Express + TypeScript baseline”src/server.ts
sets up Express in strict TypeScript with no special framework. Routes
mount under
src/routes/
— one file per surface (recommendations, configurations, articles,
change-explainer, preview).
L02 — OpenAPI-generated client types
Section titled “L02 — OpenAPI-generated client types”The FastAPI service ships an OpenAPI schema. The editor consumes it as
auto-generated TypeScript types. The generated client is what the
repositories at
src/recommendations/repository.ts,
src/configurations/repository.ts,
and
src/articles/repository.ts
wrap. A breaking change to the FastAPI schema makes the editor fail at
compile time, not in production — which is the production-realism payoff
of ADR-0005.
L03 — Server-rendered views
Section titled “L03 — Server-rendered views”Each route renders HTML server-side from a view module. The view modules take typed data (from the repositories) and produce HTML strings; nothing flows through a JSX or template engine that could lose types.
src/recommendations/view.tsrenders the recommendation list with title, category, age, sensitivity indicator.src/configurations/view.tsrenders the configuration form with sliders, toggles, and the always-include list.src/articles/view.tsrenders a single-article view.
L04 — HTMX for live preview
Section titled “L04 — HTMX for live preview”Sliders and toggles in the configuration view carry HTMX attributes —
hx-post="/preview", hx-target="#preview-pane", hx-swap="innerHTML".
Moving a slider posts the current form values to the editor’s
/preview route,
which forwards to FastAPI’s /preview endpoint and renders the returned
ranked list as an HTML fragment. The browser swaps just the preview pane.
No page reload, no JavaScript framework, no client-side state.
The architectural decision: ADR-0011 explains why HTMX over React for this surface.
L05 — Form validation with Zod
Section titled “L05 — Form validation with Zod”src/schemas.ts
declares Zod schemas for every form payload the editor accepts. Validation
runs at the route boundary before any data hits the API — invalid input
returns a 400 with a typed error, not a runtime crash deep in the
recommender.
L06 — The 76-test suite
Section titled “L06 — The 76-test suite”editor/tests/
holds 15 test files covering:
- Render tests — confirm HTML output shape for each view
- Repository tests — confirm typed API client integration
- Route tests — confirm form-submission round-trips
- Side-by-side test — confirms the TypeScript editor and the Streamlit swap-demo produce identical rankings for the same inputs (the swappability proof from ADR-0006)
Run the full suite:
pnpm --filter editor testL07 — Change-explainer partial
Section titled “L07 — Change-explainer partial”When the editor changes a configuration, two HTMX partials refresh: the
recommendations pane and an editorial-assistant pane showing why the
list moved. The partial route lives at
src/routes/change-explainer-partial.ts.
The full story belongs to the assistants module.
After this module
Section titled “After this module”Assistants is the natural follow-on — it builds on the editor’s HTMX partial pattern to wire in the change-explainer LLM agent with its Evalite evaluation harness.