Decision
OLN rejected wikitext as a contribution surface (Entry 029, Entry 009). This is the replacement, and four architecture forks were settled up front because each one constrains the rest of the build:
- Editor engine — a block editor (TipTap / ProseMirror). Blocks map 1:1 to the rendered page (the "edit live" feel), with a mature extension API for custom nodes (entity references, structured fields, plugin blocks) and a path to real-time collaboration later.
- MDX is interchange, not the execution path — the security crux. UGC is never compiled or evaluated. The source of truth is ProseMirror JSON, rendered through a component allowlist under a strict CSP — no raw HTML injection. We serialize to and from a safe MDX subset only for export, diffing, and portability; anything unrecognised deserializes to an inert placeholder and never runs.
- Collaboration — presence + single-writer at launch. Live cursors and viewer presence, with a soft edit lock (heartbeat TTL, steal-after-expiry). No CRDT at launch; the block structure lets real-time co-editing drop in later.
- Plugins and themes — allowlist now, sandbox later. v1 runs no user
JavaScript. A plugin is a manifest + field schema that configures an
OLN-reviewed, allowlisted component; a theme is validated design tokens plus a
checked asset bundle — no arbitrary CSS or JS. Both marketplaces ship day one
over this safe substrate. The block API is
data-in → vnodes-outand capability-gated, so a future sandbox can execute real user logic behind the same interface with no rewrite — built when creator demand for custom logic outweighs the cost of reviewing components.
Why
"User-extensible" at launch means extensible in data and configuration, not in logic. That is the trade that makes the security review tractable while still letting the plugin and theme marketplaces launch. Source-of-truth-as-JSON plus an allowlist renderer means there is no code path from user content to execution — the single most important property for a platform that invites strangers to author pages.
Open threads
- The exact safe-MDX subset grammar — which marks and nodes round-trip.
- Attribution rendering for user-uploaded theme and plugin assets.
- The capability surface of the eventual logic sandbox (data in, vnodes out; no DOM, no network unless granted) — designed when the revisit trigger fires.