---
title: Markdown behavior
description: Understand supported Markdown, what waits during a stream, and how completed content is rendered.
---

Smoothstream parses Markdown with CommonMark and GitHub Flavored Markdown support. While input is open, it also checks whether the current structure can safely enter the reveal schedule. This is why a response can contain more source text than is currently visible.

Set `receiving` to `false` when input ends. That lets Smoothstream finish interpreting and presenting the tail. See [Streaming a response](/get-started/streaming) for the integration pattern.

## Supported content

| Content | What is supported |
| --- | --- |
| Prose | Paragraphs, headings, emphasis, strong emphasis, strikethrough, escapes, and line breaks. |
| Links | Inline links, reference links, and GFM autolinks. |
| Lists and quotes | Ordered and unordered lists, task lists, nesting, and blockquotes. |
| Tables | GFM tables, including column alignment. |
| Code | Inline code, fenced code blocks, and indented code blocks. Syntax highlighting is optional. |
| Images | Markdown images, including images inside links. |
| Footnotes | References, definitions, and back links scoped to each instance. |
| Separators | Markdown thematic breaks. |

Smoothstream does not execute MDX or JSX, render raw HTML from the source, or expose a general remark/rehype plugin option. Math and diagram syntax do not have dedicated renderers in the current packages. [Component overrides](/customize/components) customize supported semantic elements after parsing; they do not add Markdown syntax.

## Text and incomplete formatting

Prose can begin revealing before the paragraph is complete. Smoothstream keeps a small amount of source in reserve to avoid committing text whose meaning might still change. Character reveal also waits for a complete word's geometry so a partial word does not start on one line and jump to the next.

Consider an incoming snapshot that ends with:

```md
Here is the **important
```

The unfinished emphasis is withheld while input remains open. When its closing delimiter arrives, the formatted content can enter the schedule:

```md
Here is the **important part** of the answer.
```

If input ends without a matching delimiter, normal Markdown parsing determines the final result. Smoothstream does not invent a closing delimiter to force formatting. Literal Markdown punctuation can therefore appear in the completed answer. Closing a paragraph can also resolve ambiguity before the whole response finishes.

`reveal="word"` groups each complete word into a single entrance. Character mode uses Unicode graphemes, keeping emoji and combining characters together. See [Reveal and timing](/customize/reveal).

## Links

A link needs complete Markdown syntax and a confirmed destination before it can appear. Once it appears, its sanitized `href` and `title` are available to custom link components and it is interactive while its label animates. Footnote references wait for their target to appear in the document; custom components should preserve the supplied attributes rather than invent a fallback destination.

Reference-style links can depend on definitions later in the response:

```md
See the [installation guide][install].

[install]: https://example.com/install
```

While input is open, an unresolved reference can withhold the affected content and later presentation. Put reference definitions early if you control the source and want that content to appear sooner. On close, an unresolved reference is interpreted as ordinary Markdown text.

## Lists and blockquotes

Lists can reveal completed items before the whole list ends. Long items can also reveal safe prose while their tail is still arriving. Nested blocks are evaluated within their containing list or quote.

List markers enter with their items and settle to native list semantics. Task lists render disabled checkboxes; they represent the Markdown state rather than an editable task application.

```md
- [x] Receive the source
- [ ] Finish presenting the response
```

## Tables

A table waits until its boundary is confirmed, such as when a following block arrives or input closes. This gives the browser all of the table's content for column sizing before visible rows start entering. A late, wide cell would otherwise resize earlier rows and rewrap text the reader has already seen.

Once admitted, rows reveal in order, with text inside each row following the configured character or word reveal. A table does not need a separate animation setting.

Wide tables scroll horizontally inside a stationary frame. Style that frame separately from the semantic cells; see [Styling](/customize/styling).

## Code blocks

Fenced code can begin presenting before the closing fence arrives. Complete lines are admitted while input is open; the unfinished final line waits until a newline arrives or input closes. Each admitted line then uses the configured character or word reveal.

With [syntax highlighting](/customize/syntax-highlighting), a line waits for its highlighting result before it enters the schedule. Accepted line colors stay fixed as later source arrives. This avoids showing plain text first and recoloring it during reveal.

An attached highlighter also enables the copy control. It becomes available when the code block is confirmed complete, including when input closes without an explicit closing fence. Copy uses the block's complete code, even if some of that code is still revealing.

## Images

Smoothstream starts loading an image when it discovers its source. An unresolved image does not block later blocks. Its visible entrance waits for readiness and may change the layout after surrounding text has appeared.

Use useful alt text:

```md
![A flow from incoming text through the reveal scheduler to rendered Markdown](/images/flow.png)
```

Relative image and link URLs resolve in the consuming application's page context. Smoothstream does not fetch a Markdown document from a URL or infer a separate asset base path.

## Footnotes

```md
The result needs some context.[^source]

[^source]: Supporting detail, with **Markdown** formatting.
```

A complete footnote reference reserves its marker while a later definition is pending. The surrounding prose can continue revealing. The marker remains non-interactive until the definition is ready; the note appears at the end with a back link to each reference.

If input closes without the definition, the reference becomes literal Markdown. IDs are scoped to each Smoothstream instance, so different messages can reuse `[^source]` without sharing fragment targets.

## HTML and URL handling

Raw HTML in the Markdown source is not turned into elements. The parsed Markdown tree is sanitized before rendering.

| Destination | Allowed schemes |
| --- | --- |
| Links | `http:`, `https:`, `mailto:`, and `tel:` |
| Images | `http:` and `https:` |

Relative paths and fragment destinations are also allowed. Schemes such as `javascript:`, `vbscript:`, and `data:` are removed. These rules apply to source Markdown; application-provided components and highlighters are trusted code and remain responsible for the properties they introduce.

For the reasoning behind these presentation choices, read [How Smoothstream works](/concepts/how-it-works).
