---
url: /guide/streaming-markdown.md
---
# Streaming Markdown

Markdown generated by an LLM is often temporarily invalid while the response is still streaming. A fenced code block may be missing its closing backticks, a list may be half-written, or a plugin may reject an intermediate state.

VueMarkik is designed to handle that pattern without forcing the UI to flicker or flooding the console with warnings.

## Which Component to Use

All three rendering components support `error-mode` and preserve the last successful render by default when an updated render fails.

Choose between them based on how the rest of your app works:

* `Markdown`: use when your rendering path is synchronous and you want the simplest component
* `MarkdownAsync`: use when you already rely on Vue `<Suspense>`
* `MarkdownHooks`: use for reactive async updates, especially streamed LLM output

If you are consuming incremental model output directly, `MarkdownHooks` is usually the best default because it reacts naturally to changes in the `text` prop.

## Recommended Configuration

For LLM output, start with:

```vue
<script setup lang="ts">
import { MarkdownHooks } from 'vuemarkik';
import { ref } from 'vue';

const llmOutput = ref('### First chunk');
</script>

<template>
  <MarkdownHooks :text="llmOutput" error-mode="silent" />
</template>
```

This configuration does two things:

* Preserves the last successful render when a streamed update is temporarily invalid
* Avoids console warnings by default

The same `error-mode` behavior is available on `Markdown` and `MarkdownAsync` as well:

```vue
<Markdown :text="snapshot" error-mode="silent" />

<Suspense>
  <MarkdownAsync :text="snapshot" error-mode="silent" />
</Suspense>
```

## Error Modes

VueMarkik exposes three render error modes:

* `silent`: preserve the last successful render and emit `render-error`
* `warn`: preserve the last successful render, emit `render-error`, and log a warning
* `throw`: throw the render failure immediately

For production LLM output, `silent` is the right default. Use `warn` while debugging plugin behavior. Use `throw` in tests or when you want failures to stop rendering immediately.

## Timed Demo

The following example rotates through valid and broken snapshots automatically. Try switching error modes to compare how recovery behaves.

::: raw&#xA;
:::

## What Happens on a Failed Update

When a streamed update cannot be rendered:

1. VueMarkik attempts to process the latest markdown snapshot.
2. If the render fails, the component emits `render-error`.
3. The UI keeps showing the previous successful render.
4. When a later update becomes valid again, the rendered output updates normally.

This avoids a bad user experience where content flashes between rendered output and an empty state while the model is still generating.

## Observability

If you want to track rendering problems without showing them in the console, listen to `render-error` and send the payload to your own logging or monitoring system.

```vue
<script setup lang="ts">
import { MarkdownHooks } from 'vuemarkik';
import { ref } from 'vue';

const llmOutput = ref('### First chunk');

function reportMarkdownIssue(payload: { error: unknown; text: string }) {
  console.debug('Skipped an intermediate markdown render.', payload);
}
</script>

<template>
  <MarkdownHooks
    :text="llmOutput"
    error-mode="silent"
    @render-error="reportMarkdownIssue"
  />
</template>
```

## Related Guides

* [API Reference](./api-reference)
* [Remark & Rehype Plugins](./remark-rehype-plugins)
* [Syntax Highlighting](./syntax-highlighting)
