Comparisons

Comark vs MDX

Comark parses component syntax at runtime with no build step, while MDX compiles Markdown to JSX at build time. Compare syntax, architecture, framework support, and streaming.

TL;DR: Both let you use components inside Markdown. MDX compiles your content to JSX at build time, so it is tied to a bundler and (in practice) to React. Comark parses component syntax at runtime into a framework-agnostic AST, so content can come from a database, a CMS, or an AI stream, and render to Vue, React, Svelte, Angular, HTML, or a terminal.

At a Glance

ComarkMDX
Component syntax::alert{type="info"}<Alert type="info"> (JSX)
Build stepNot required, parse at runtime or build timeRequired, compiles to JSX
Content sourceAny string: file, database, CMS, API, LLM streamFiles processed by your bundler
RenderersVue, React, Svelte, Angular, Nuxt, HTML, ANSIReact (other JSX runtimes via pragma)
StreamingAuto-close renders incomplete input at every frameNot supported, expects complete documents
OutputCompact serializable ASTCompiled JavaScript module
Inline JavaScript expressionsNo, values come from frontmatter or app stateYes, full JSX expressions
Imports/exports in contentNo, components registered in the rendererYes
Plugin ecosystemComark plugins + markdown-it pluginsremark/rehype plugins

The Core Difference: Content vs Code

An .mdx file is a JavaScript module. It can import components, export values, and embed arbitrary expressions. That power has a cost: your content must go through a compiler before it can render. Shipping a typo fix means triggering a rebuild and a redeploy, and storing MDX in a database means running a compiler on the server for every document.

Comark keeps content as plain text:

::alert{type="warning"}
This action cannot be undone.
::

Because parse(markdown) is a pure function returning an AST, the full CMS pattern works without a build pipeline:

  1. Store raw Markdown (components included) in a database or CMS
  2. Call parse(markdown) on request, on the server or in the browser
  3. Send the compact AST to the client
  4. Render it with a components map: <ComarkRenderer :tree="ast" :components="{ Alert }" />

Content is live the moment it is saved.

Syntax Side by Side

import Alert from './components/Alert'
import Chart from './components/Chart'

# Dashboard

<Alert type="info">
  Welcome back, with **bold** text inside.
</Alert>

<Chart data={metrics} />

Comark components are registered once in the renderer instead of imported per file. Dynamic values use :prop="expression" bindings resolved against frontmatter or application state. See the migration guide for the full mapping.

Streaming

LLMs emit Markdown token by token. MDX cannot compile an unterminated document, so streaming MDX means waiting for the full response or accepting compile errors mid-stream.

Comark's auto-close parser closes incomplete syntax (unterminated bold, unfinished code fences, half-open components) so every frame renders as valid UI:

import { autoCloseMarkdown } from 'comark'

autoCloseMarkdown('**bold text')      // '**bold text**'
autoCloseMarkdown('::alert\nContent') // '::alert\nContent\n::'

Each framework renderer exposes this as a streaming prop that pipes AI output straight into your component tree, custom components included.

What MDX Does That Comark Doesn't

Be aware of what you give up:

  • Inline JavaScript expressions: {2 + 3} or {new Date().toLocaleDateString()} evaluate in MDX. In Comark, compute values in application code and pass them via frontmatter, bindings, or string interpolation.
  • Imports and exports in content: MDX files are modules. Comark content is data; components live in your app.
  • The remark/rehype ecosystem: MDX plugs into it directly. Comark has its own plugin API and can reuse markdown-it plugins, a different but comparable ecosystem.

If your content is written by developers, versioned in git, and full of bespoke logic, MDX's "content as code" model can be the right fit. If your content comes from writers, a CMS, an API, or a model, Comark's "content as data" model removes the compiler from the loop.

Migrating

The MDX migration guide maps every MDX concept (components, props, expressions, imports, exports, layouts) to its Comark equivalent, with a step-by-step checklist.

FAQ