feat: MDX rendering support in books island #29

Closed
opened 2026-02-26 04:06:06 +00:00 by mik-tf · 0 comments
Owner

Context

The books island receives page content as pre-rendered HTML from hero_books backend via the content_html field in the JSON-RPC response. This works for standard markdown, but .mdx files contain JSX components (<Tabs>, <CodeBlock>, embedded iframes, <div style={{...}}>, etc.) that pulldown-cmark strips or misrenders.

Originally tracked as hero_books #44 (closed — moved here since the rendering belongs in the WASM frontend).

Goal

When viewing an .mdx page, render JSX components correctly in the browser. Must work at any scale (books may have thousands of .mdx files).

Approach

Two-part change:

1. hero_books backend — send raw content for .mdx files

The bookservice.get_page RPC response needs a way to signal that content is MDX and provide raw source:

  • Add content_type field ("html" or "mdx") to the response
  • Add content_raw field with the original .mdx source when content_type == "mdx"
  • Backward compatible: content_html still present as fallback

2. archipelagos books island — client-side MDX rendering

In views/mod.rs PageContentView:

  • Check content_type field in the response
  • If "html": use existing dangerous_inner_html path (no change)
  • If "mdx": load mdx-js via JS interop to compile and render the MDX in-browser
  • Use wasm-bindgen / js-sys to call the JS MDX compiler
  • Map common JSX components to styled HTML equivalents (Tabs, CodeBlock, Callout, etc.)

Component mapping

Common MDX components to support:

  • <Tabs> / <TabItem> — tabbed content panels
  • <CodeBlock> — syntax-highlighted code with copy button
  • <Callout> / <Admonition> — info/warning/error boxes
  • <Details> — collapsible sections
  • Embedded iframes (YouTube, Canva, etc.) — pass through as-is
  • Inline styles (style={{...}}) — convert JSX object syntax to CSS string

Prerequisites

  • hero_books backend change (add content_type + content_raw to get_page response)
  • mdx-js loaded as JS dependency in the WASM bundle
## Context The books island receives page content as pre-rendered HTML from hero_books backend via the `content_html` field in the JSON-RPC response. This works for standard markdown, but `.mdx` files contain JSX components (`<Tabs>`, `<CodeBlock>`, embedded iframes, `<div style={{...}}>`, etc.) that pulldown-cmark strips or misrenders. Originally tracked as [hero_books #44](https://forge.ourworld.tf/lhumina_code/hero_books/issues/44) (closed — moved here since the rendering belongs in the WASM frontend). ## Goal When viewing an `.mdx` page, render JSX components correctly in the browser. Must work at any scale (books may have thousands of .mdx files). ## Approach Two-part change: ### 1. hero_books backend — send raw content for .mdx files The `bookservice.get_page` RPC response needs a way to signal that content is MDX and provide raw source: - Add `content_type` field (`"html"` or `"mdx"`) to the response - Add `content_raw` field with the original .mdx source when `content_type == "mdx"` - Backward compatible: `content_html` still present as fallback ### 2. archipelagos books island — client-side MDX rendering In `views/mod.rs` `PageContentView`: - Check `content_type` field in the response - If `"html"`: use existing `dangerous_inner_html` path (no change) - If `"mdx"`: load [mdx-js](https://mdxjs.com/) via JS interop to compile and render the MDX in-browser - Use `wasm-bindgen` / `js-sys` to call the JS MDX compiler - Map common JSX components to styled HTML equivalents (Tabs, CodeBlock, Callout, etc.) ## Component mapping Common MDX components to support: - `<Tabs>` / `<TabItem>` — tabbed content panels - `<CodeBlock>` — syntax-highlighted code with copy button - `<Callout>` / `<Admonition>` — info/warning/error boxes - `<Details>` — collapsible sections - Embedded iframes (YouTube, Canva, etc.) — pass through as-is - Inline styles (`style={{...}}`) — convert JSX object syntax to CSS string ## Prerequisites - hero_books backend change (add `content_type` + `content_raw` to get_page response) - mdx-js loaded as JS dependency in the WASM bundle ## Related - [hero_books #44](https://forge.ourworld.tf/lhumina_code/hero_books/issues/44) (closed, moved here) - [hero_books #43](https://forge.ourworld.tf/lhumina_code/hero_books/issues/43) — basic .mdx pipeline support
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_archipelagos#29
No description provided.