Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as a monorepo subdirectory under desktop/. Source only — node_modules, dist, Cargo target and the upstream .git history are excluded. desktop/ keeps its own independent Cargo workspace (desktop/src-tauri with crates/*); it is not part of the backend boosapi crate, so a `cargo check` at the metapi root still compiles only the backend. Build the desktop app from desktop/src-tauri per desktop/README.md. Note: app icons are still placeholder assets pending the final BoosAPI logo. The updater signing keys live outside the repo and are not included.
4.3 KiB
description
| description |
|---|
| Build AI chat and streaming Markdown UIs with nodes plus final patterns, performance guidance, trusted custom tags, and SSR-safe setup. |
AI Chat & Streaming
Use this path when you are building a chat UI, token stream, SSE response viewer, or any screen where Markdown updates frequently while the user is watching.
If you only render static articles or docs pages, go back to Usage & Streaming and prefer the simpler content path.
1. Choose the leanest install
| Need | Packages | Best for |
|---|---|---|
| Text-only or lightweight chat UI | markstream-vue |
Basic Markdown, lists, links, blockquotes |
| Syntax-highlighted code without Monaco | markstream-vue stream-markdown |
SSR-friendly transcripts, lower bundle budgets |
| Rich code interactions | markstream-vue stream-monaco |
Copy, preview, diff, and Monaco-powered code blocks |
| Diagrams or math in chat output | markstream-vue mermaid katex |
Mermaid fences and KaTeX formulas |
Install only the peers you actually expect to show up in responses.
2. Recommended data flow
For frequent updates, keep parsing outside MarkdownRender and pass nodes + final.
<script setup lang="ts">
import MarkdownRender, { getMarkdown, parseMarkdownToStructure } from 'markstream-vue'
import { computed, ref } from 'vue'
const streamedText = ref('')
const final = ref(false)
const md = getMarkdown('chat-message')
const nodes = computed(() =>
parseMarkdownToStructure(streamedText.value, md, { final: final.value }),
)
</script>
<template>
<MarkdownRender
custom-id="chat"
:nodes="nodes"
:final="final"
/>
</template>
Why this path works better:
MarkdownRenderdoes not need to reparse the full string on every tiny token update.- You can move parsing into a store, worker, or message pipeline later without changing the renderer contract.
custom-id="chat"gives you a scoped place to theme the chat surface or override one renderer safely.
3. Renderer settings that usually work well
- Keep the default virtualization behavior for long transcripts. Only tune
maxLiveNodesif you have a measured reason. - Use
renderCodeBlocksAsPrewhen code fences appear often but Monaco is too heavy for your chat surface. - Leave heavy peers off until you need them. Chat UIs get a large win from not shipping Mermaid, KaTeX, or Monaco by default.
- If you disable virtualization (
:max-live-nodes="0"), then the batching props in Props & Options become more important.
4. Common upgrade paths
Better code blocks
- Want a lighter docs-style look: use
MarkdownCodeBlockNodewithstream-markdown - Want richer preview/diff controls: use
CodeBlockNodewithstream-monaco
See Renderer & Node Components for the trade-offs.
Trusted tags such as thinking
Use custom-html-tags plus setCustomComponents('chat', mapping) so custom tags only affect the chat surface.
See Custom Tags & Advanced Components.
Scoped overrides for one message surface
Use setCustomComponents('chat', { image: ChatImageNode }) and render with custom-id="chat".
See Override Built-in Components.
5. CSS and SSR checklist
- Load your reset first, then import
markstream-vue/index.cssinside@layer components. - Import
katex/dist/katex.min.cssonly if math is enabled. - Gate browser-only peers such as Mermaid, D2, or Monaco behind client-only boundaries in SSR setups.
- If styles leak, scope your chat tweaks under
[data-custom-id="chat"].
Start here when visuals look wrong: Troubleshooting
6. When not to use this path
- Use
contentwhen updates are infrequent or the page is basically static. - Use server-side preparse +
nodeswhen another layer already owns Markdown parsing. - Use the framework-specific guides when SSR/runtime rules matter more than streaming itself.
Next pages
- Installation for peer decisions
- Usage & Streaming for
contentvsnodes - Performance for larger transcripts
- Renderer & Node Components for code/math/diagram component choices
- Troubleshooting when CSS, peers, or SSR behave unexpectedly