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 componentMarkdownAsync: 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:
<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:
<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 emitrender-errorwarn: preserve the last successful render, emitrender-error, and log a warningthrow: 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
silentkeeps the last good render with no console output.warnkeeps the last good render and logs each failure.throwsurfaces the failure through the local boundary below.
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:
- VueMarkik attempts to process the latest markdown snapshot.
- If the render fails, the component emits
render-error. - The UI keeps showing the previous successful render.
- 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.
<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>