Skip to content

tutorials/frontend: add 03-japanese-verb-tower build-through#40

Open
jbeshir wants to merge 1 commit into
mainfrom
tutorial/frontend-japanese-verb-tower
Open

tutorials/frontend: add 03-japanese-verb-tower build-through#40
jbeshir wants to merge 1 commit into
mainfrom
tutorial/frontend-japanese-verb-tower

Conversation

@jbeshir

@jbeshir jbeshir commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Frontend (Preact) build-through tutorial for the japanese-verb-tower widget — entry 03 in the tutorials/frontend/ track. Live widget: https://japanese-verb-tower.widgets.beshir.org

Builds on 01-function-plotter and 02-image-comparison-table: concepts in their ledgers (Preact/Vite stack, render, #widget-ready, hook basics, controlled inputs, ResizeObserver; multi-component composition + lifting state, typed Props, URL-driven read-only view selection, lazy useState initialiser, typed data registry, useLayoutEffect, fit-to-viewport, functional setState, <dialog>/showModal(), popover dismissal, document.title, useMemo for stable identity) are named and linked, not re-taught. All CSS/visual concerns are cross-linked to the design track (../design/03).

New frontend ground this entry teaches:

  • An algorithmic domain engine outside the components — the agglutinative conjugation engine: the Op interface + reg() self-registration, buildTower() as a left-fold threading a Form, recursive form composition (voice ops return { type: 'ichidan' } so the whole rule-set reuses with no special cases), stem helpers dispatching on form.type, allowedOps() as a pure structural legal-move guard, finalForm() replay. The centrepiece.
  • A Cloudflare Worker backend — Workers Static-Assets SPA+API model (run_worker_first + not_found_handling: "single-page-application"), an isolated tsconfig.worker.json, the Workers AI binding (env.AI.run('@cf/qwen/qwen3-30b-a3b-fp8', …)), and the in-Worker abuse guard (Sec-Fetch-Site cross-site reject, rate-limit binding, Cache API memoization via ctx.waitUntil(), input caps, /no_think + <think> stripping).
  • Async fetch + graceful degradation — debounced and abortable fetch using AbortController together with an active flag (and why each alone is insufficient); a synchronous cache short-circuit; a two-tier Map + localStorage cache; best-effort translation that never blocks functionality or #widget-ready.
  • Lazy code-split corpus — dynamic import() of the 26,784-verb corpus after first paint with a silent .catch fallback to the inline 300-verb sample.
  • Bidirectional URL state — write via history.replaceState, restore + re-validate through allowedOps on load (extends 02's read-only view selection).
  • Input transformationromajiToKana() wāpuro greedy longest-match (sokuon, ん disambiguation), a tiered search ranking, and deconjugate() reverse-conjugation that reuses the engine to forward-verify.
  • Testing a pure domain module — the golden-test pattern (tsx runner + committed golden.json + forward-verification), the payoff of keeping the engine framework-free.

Every code excerpt and file:line anchor was verified against the widget's real source by an adversarial review stage (PASS round 2). Round 1 caught a real factual blocker — the demo-verb table had copied the widget's stale README (which lists 見る), but the code actually features 帰る (FEATURED_KANJI, morph.ts:185); the tutorial now follows the code and notes 帰る's godan-in-ichidan-clothing trap.

Note: the ../design/03-japanese-verb-tower.md cross-link resolves once the sibling design tutorial (#39) merges.

🤖 Generated with Claude Code

Build-through tutorial covering the pure algorithmic conjugation engine,
a Cloudflare Worker AI backend (run_worker_first + Workers AI), debounced
abortable fetch with graceful degradation, lazy code-split corpus loading,
bidirectional URL state, and romaji input transformation. Adds the README
track row. Progressive: references frontend 01 and 02 for known concepts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant