Skip to content

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.

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.

Error mode

  • silent keeps the last good render with no console output.
  • warn keeps the last good render and logs each failure.
  • throw surfaces the failure through the local boundary below.
Error mode

Incoming snapshot

Step 1 of 3: Valid introduction

Rendered preview

The preview uses the real component with the selected errorMode.

### Streaming output

The model started with a valid chunk.

It is about to generate a code example and a short summary.

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>

Released under the MIT License.