Add "Rust MDX" live embeddable component blocks
Add "Rust MDX" live embeddable component blocks
#11 in tonybierman/dx-blog — merged 2026-05-29
Summary
Implements roadmap #4 — the "identity-defining" feature: post Markdown can contain [[component:name key=val]] blocks that the renderer mounts as real, interactive Dioxus components (WASM, signal-driven) instead of iframes.
Previously the body rendered as one inert dangerous_inner_html blob (reader.rs:180), opaque to Dioxus' VDOM. Now the body is split into a sequence of rendered-markdown runs and live embed blocks, interleaved in the reader and the editor preview.
What's included
src/mdx.rs(shared, server + web) —parse_bodysplits a body intoSegment::Htmlruns (each passed through the existingrender_markdown, byte-for-byte identical for plain prose) andSegment::Embed { name, props }. Prop tokenizer handles bare and quoted values.src/embeds.rs—EmbedBlockregistry dispatching to typed components:counter— signal-driven counterchart— inline SVG bar/line fromdata="3,7,2,9"tweak— slider-driven live SVG curvelivechart— timer-streamed scrolling feedstockchart/ticker— live candlestick chart with volume sub-band ("market open")- unknown names → safe inline fallback
reader.rs+admin/posts.rs— render the segment stream in the reader and the editor's live preview.seed.rs— one demo post per component (rust-mdx-*).justfile—reseedrecipe (wipe dev DB + serve withDX_SEED=1).
Design notes
- Embed components are not feature-gated: they SSR-render their initial state and hydrate on the client (the whole point vs. an iframe). Streaming components seed their initial window deterministically (no
rand/clock) so SSR and the client's first paint match — animation begins after hydration. - Props are typed strings parsed in
EmbedBlock, never injected as HTML — strictly safer than iframe embeds. use_intervaltimers cancel on unmount, so leaving a post stops its chart; embeds aren't mounted on feed/list pages (body-only).
Verification
cargo fmtcleancargo check --no-default-features --features server,sqlitecargo check --no-default-features --features web --target wasm32-unknown-unknowncargo test --no-default-features --features server,sqlite→ 16 passed (incl. 5 newparse_bodytests)
Run just reseed, then open any rust-mdx-* post (animated charts start once the wasm client hydrates).
🤖 Generated with Claude Code
Last updated 2026-05-30
Links to this note
Credits
Merged pull requests, newest first.