Render markdown preview in-browser (WASM)

Render markdown preview in-browser (WASM)

#10 in tonybierman/dx-blog — merged 2026-05-29

What

Moves the post editor's live Markdown preview off the server and into the wasm client. Implements the In-browser WASM markdown editor roadmap item.

Previously the editor round-tripped to the preview_markdown server fn on every (debounced) keystroke. Now render_markdown (the shared pulldown-cmark + ammonia pipeline) is compiled for the web target and runs directly in the browser.

Why it's a good fit

The client now uses the exact same pipeline the server uses to produce stored body_html, so the preview matches saved output byte-for-byte. It's also:

  • Zero-latency — synchronous use_memo, no debounce and no network round-trip
  • Offline-capable — preview works without the server
  • Zero server load — the preview endpoint is gone entirely

Changes

  • Cargo.toml — add pulldown-cmark + ammonia to the web feature (verified they compile to wasm32-unknown-unknown)
  • src/server/mod.rs — gate render_markdown on any(server, web)
  • src/pages/admin/posts.rs — replace the server-fn use_resource with a synchronous use_memo; drop the preview debounce
  • src/server/admin/posts.rs — delete the now-unused preview_markdown server fn (POST /api/admin/preview)

Verification

  • Server check (server,sqlite): clean
  • WASM client check (web, wasm32-unknown-unknown): clean
  • cargo fmt: applied
  • Tests: 11/11 pass — including render_markdown sanitization tests, which now also cover the in-browser path

Notes / follow-ups

  • Adds ammonia/html5ever to the wasm bundle (size trade-off), kept identical to the server pipeline so preview stays byte-for-byte consistent.
  • Syntax highlighting (syntect/tree-sitter) in code blocks is a noted follow-up, not in this PR.

🤖 Generated with Claude Code

Last updated 2026-05-30