Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/content/1.getting-started/0.introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ This is an important message!
::
```

The `::alert` is a block component that supports properties and children (also known as slots). Learn more about the [Component Syntax](/syntax/components).
The `::alert` is a block component that supports properties and children (also known as slots).

::tip{to="/kb/why-comark"}
Want to know more about the Comark design and why we've created it? [Why Comark](/kb/why-comark) explains the reasoning behind this design choice.
::

Comark parses this into an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) that can be rendered to [HTML](/rendering/html). It also supports rendering to [Vue](/rendering/vue), [Nuxt](/rendering/nuxt), [React](/rendering/react), and [Svelte](/rendering/svelte), turning your Markdown into fully interactive content.

Expand Down
162 changes: 162 additions & 0 deletions docs/content/7.kb/0.why-comark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
title: Why Comark is the Future of UI Authoring
description: Markdown has become the shared language between humans and AI. Comark extends it all the way to interactive UI.
navigation:
title: Why Comark?
seo:
title: Why Comark is the Future of UI Authoring
description: Markdown is human-readable, token-efficient, and AI-parseable. Discover why it has become the lingua franca for building UI and how Comark extends it to interactive components.
links:
- label: Comark Syntax
icon: i-lucide-file-text
to: /syntax/components
color: neutral
variant: soft
- label: Streaming API
icon: i-lucide-radio
to: /api/auto-close
color: neutral
variant: soft
---

This page answers two questions.

First, why Markdown has become the default format for both human authoring and machine consumption and why that convergence is not accidental.

Second, why Comark extends it: what standard Markdown is lacking when you need components and how Comark adds that without sacrificing readability, portability, or parser compatibility.

## Why Markdown?

### The Dual Audience Problem

Every piece of content on the web is consumed by at least two types of reader:

- **Humans** who need scannable structure, comfortable prose, and visual hierarchy
- **Machines** who need predictable tokens, explicit structure, and minimum noise

HTML was designed for the first audience. JSON was designed for the second. Neither was designed for both.

**Markdown** was designed for humans but it turns out machines love it too.

### Why Machines Prefer Markdown

The evidence is clearest in token economics.

The same page served as HTML versus Markdown to an AI agent can use **80% fewer tokens** in Markdown form. At scale, that is not a formatting preference, it is an infrastructure decision. Lower token counts mean faster responses, lower costs, and longer effective context windows.

Beyond token count, Markdown's explicit structure maps cleanly to how language models reason. A `##` heading is unambiguously a section boundary. HTML carries the same information buried in `<h2 class="...">` but the signal-to-noise ratio is far worse.

### AI as a First-Class Audience

The tooling industry has converged on this conclusion. [Streamdown](https://github.com/vercel/streamdown) (an open-source renderer by Hayden Bleasel, DX Engineer at Vercel) was built precisely because LLMs stream token by token and existing renderers like `react-markdown` assume a complete document, making them unable to handle unterminated blocks gracefully. Because LLMs tend to produce Markdown by default, Streamdown is a React component designed to render it correctly as chunks arrive — pairing naturally with `useChat` and other streaming patterns from `@ai-sdk/react`. Together they reflect a deliberate recognition that AI agents are now a _primary_ consumer of content, not a secondary one.

The same shift is visible in developer tooling. Files like `AGENTS.md` and `.cursorrules` are Markdown documents that configure AI coding assistants. GitHub Copilot reads them across sessions. Cursor injects them into every prompt. Claude Code uses `CLAUDE.md`. The format that humans write is the same format that machines act on.

This is new. For most of computing history, human-authored content and machine-readable configuration were different artifacts in different formats. Markdown is collapsing that boundary.

## Why Comark?

Markdown solves the dual-audience problem. But standard Markdown stops at document structure (headings, lists, code blocks, emphasis...). It has no way to express a warning callout, a tabbed code group, a video embed, or a pricing card.

### The Next Iteration of MDC

Comark is the next iteration of [mdc](https://github.com/nuxt-content/mdc), the MDC parser that has powered [Nuxt Content](https://content.nuxt.com)'s component syntax for over five years. MDC proved the concept syntax for embedding components inside Markdown.

Comark takes that foundation and extends it in three directions:

- **Streaming and auto-closing:** the [auto-close](/api/auto-close) parser completes unterminated blocks on the fly, so AI-generated or live-streamed Markdown renders correctly at every frame without buffering
- **Compact AST for SSR:** instead of a verbose object tree, Comark produces compact tuples `['tag', props, ...children]` that reduce payload size when serialized and sent over the wire
- **Multiple rendering targets:** the same source renders to Vue, React, Svelte, Nuxt, plain HTML and ANSI terminal output without changing the content

### The Gap Between Document and UI

The current workarounds for going beyond standard Markdown are:

- **Raw HTML** — works, but immediately breaks the plain-text properties that make Markdown human-readable and reintroduces the token overhead it removes for AI.
- **MDX** — extends Markdown with JSX, but it is a *compiler*: `.mdx` files are transformed to JSX at build time. Shipping new content means triggering a rebuild and a redeploy.

Comark's position is that component syntax should stay in plain text, parse at runtime, and work across any renderer. That is the design constraint every other decision follows from.

### The Improved Syntax

#### Block Components

Comark's component syntax is a superset of standard Markdown, inspired by the [Markdown directives proposal](https://talk.commonmark.org/t/generic-directives-plugins-syntax/444), a CommonMark effort to standardize a generic extension point without breaking parsers or leaving plain text.

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

This is still plain text. No bundler, no compiler step. A human can read it and understand it. An AI agent can parse it as structured data: a component named `alert` with a `type` attribute and text content.

That shift makes Markdown data, not code. Because `parse(markdown)` is a pure function returning a [Comark AST](/syntax/comark-ast), the full CMS pattern becomes possible:

1. A database, CMS, or headless service stores the raw Markdown (including `::` components)
2. On request, the server runs `parse()` and gets the compact AST
3. The AST is sent to the client
4. `<Comark :value="ast" :components="{...}" />` renders it by looking up each tag name in a components map at runtime

#### Slots

Raw HTML does break down at one point: **slots** (named regions inside a component). In HTML syntax, placing rich Markdown content into specific named regions of a tag is awkward at best. In Comark, slots are first-class: `#slotname` markers let you place full Markdown into any named region of a component:

```mdc
::hero
#title
Build UIs from **Markdown**

#description
Comark parses component syntax at runtime — no compiler, no rebuild.
Supports Vue, React, Nuxt, and Svelte out of the box.

#cta
[Get started](/getting-started)
::
```

### One Source, Every Renderer

MDX is tied to React. @nuxtjs/mdc was tied to Nuxt. Most Markdown renderers are tied to a single output target. Comark decouples the parse step from the render step entirely.

The same `.md` source file renders to:

- [`<Comark>` in Vue](/rendering/vue) — async components, streaming, slot-based composition
- [`<Comark>` in React](/rendering/react) — Server Components and client-side rendering
- [`<Comark>` in Nuxt](/rendering/nuxt) — zero-config module with auto-imports and Nuxt UI integration
- [`<Comark>` in Svelte](/rendering/svelte) — snippets and streaming
- [`renderHTML()` in @comark/html](/rendering/html) — server-side HTML strings, RSS, emails, static builds
- [`renderANSI()` in @comark/ansi](/rendering/ansi) — styled terminal output for CLIs

The content layer outlasts any particular rendering technology. Write your content once, choose your renderer at the call site.

### An AST Built for Machines

Most Markdown parsers produce verbose object trees:

```typescript
{ type: 'element', tag: 'p', props: {}, children: [{ type: 'text', value: 'Hello' }] }
```

The [Comark AST](/syntax/comark-ast) uses compact tuples instead:

```typescript
['p', {}, 'Hello']
```

The same information, a fraction of the allocations. This matters for static site generators, build pipelines, and AI content endpoints, where the parser stops being the bottleneck. The same philosophy that makes Markdown token-efficient for LLMs makes Comark's AST memory-efficient for the JavaScript runtime.

Because Comark can parse on the server and send only the compact AST over the wire, the client receives what it needs to render. For Markdown-driven websites serving many readers, this is a meaningful payload and CPU reduction at every request.

### Streaming by Design

AI models generate content token by token. A renderer built on the assumption of a complete document breaks immediately when the input is a live stream.

Comark is built for this case. The [auto-close](/api/auto-close) parser handles incomplete syntax by automatically completing it so the UI renders correctly at every frame. The `streaming` prop on `<Comark>` and `<ComarkRenderer>` pipes AI-generated Markdown directly into your component tree as it arrives, with no intermediate buffering.

Comark takes the same premise as [Streamdown](https://github.com/vercel/streamdown) further: not just streaming plain Markdown, but streaming Markdown with component syntax so AI output can include interactive UI elements rendered in real time.

---

Markdown has become the connective tissue between human authorship and machine intelligence. Comark extends that connective tissue all the way to interactive UI by using component syntax that stays readable, one source that renders anywhere, an AST built for machines, and streaming that works out of the box.
Loading