Markstream Nuxt
Use this skill when the host app is Nuxt and SSR boundaries matter.
Workflow
- Confirm the repo is Nuxt 3 or 4.
- Install
markstream-vueplus only the optional peers required by the requested features. - Keep browser-only peers behind client-only boundaries.
- Prefer
<client-only>wrappers,.clientplugins, or guarded setup paths.
- Prefer
- Import
markstream-vue/index.cssfrom a client-safe app shell or plugin.- The root JS import does not inject styles; use
markstream-vue/index.cssormarkstream-vue/index.px.cssexplicitly.
- The root JS import does not inject styles; use
- Start with
content, choose the renderer mode by surface, and move tonodesplusfinalonly when the UI needs custom AST control.- Use
mode="chat"for AI chat or SSE output. It uses lightweight batches,fade=false, andmax-live-nodes=0;smooth-streaming="auto"paces visible output. - Use
mode="docs"for rich document surfaces. It is the default and enables larger batches, tooltips, and fade. - Use
mode="minimal"for lightweight non-chat surfaces. - Regular fenced code uses the built-in renderer, enhanced by
stream-diffswhen the optional peer is installed. Userender-code-blocks-as-prefor a forced plain path orsetCustomComponents(customId, { code_block: ... })for a scoped application-owned renderer. typewriteronly controls the blinking cursor and defaults tofalse. Prefertypewriter="simple"for high-frequency chat.- In Vue 3 (including Nuxt),
smooth-streamingcontrols output pacing andfadecontrols opacity; they can be enabled together.mode="chat"keepsfade=falseas a lightweight default. Addfadewhen gradual text reveal is desired; keep it off when animation cost matters more. Vue 3 append fades use stable batches (200 ms, 50 ms coalescing window, at most four batches per text node); later appends do not restart earlier batches. - Streaming vs recovering history: in chat UIs the same
MarkdownRenderstarts streaming and later switches to history whenfinal=true.- Streaming: start with
mode="chat"andfinal; addfadefor text reveal andtypewriteronly when a cursor is wanted. - Recovering/completed chat history: keep
mode="chat"on the same chat row; use:smooth-streaming="false",typewriter=false, and choosefadeindependently for the desired entry/reveal effect. Do not bind it to the inverse of streaming state unless that visual policy is intentional. - Use
mode="minimal"for lightweight non-chat recovered content, and usemode="docs"only for rich document surfaces.
- Streaming: start with
- In SSR, avoid
smooth-streaming="true"on first-screen content; the mounted gate insideautoprevents hydration mismatch. - Remember that
html-policynow defaults tosafe, and Mermaid strict mode is on by default throughmermaid-props.
- Use
- Validate with the smallest relevant Nuxt dev, build, or typecheck command.
Default Decisions
- SSR safety comes before feature completeness.
- Omit
modeonly when the surface should use rich docs defaults. - Smooth streaming is SSR-safe in
automode (the default) because it gates on mount. Do not usesmooth-streaming="true"for first-screen SSR content — it bypasses the mounted gate and can cause hydration mismatch or blank flash. - For a non-virtual chat scroller, import
useStickToBottomfrommarkstream-vue/utilsand callscheduleScrollToBottom()after Vue commits new content. The composable attaches browser listeners after mount; useMarkstreamVirtualTimelinewithstick-to-bottom="auto"for long mixed timelines. - Avoid import-time access to browser globals from server code paths.
- Treat the enhanced code runtime, Mermaid workers, and similar heavy peers as client-only unless the repo already has a proven SSR pattern.
- For large code blocks, the optional off-thread highlight pool (
setStreamDiffsWorkerPoolfrommarkstream-vue, backed by an upstream@pierre/diffsWorkerPoolManager) is also client-only: inject it in a client-only plugin/component, never in server code paths. - Enhanced code blocks in every Markstream package use
stream-diffs; do not installstream-monaco. - Use top-level
code-block-optionsfor supported built-in code-surface configuration. Keep theme, code/language, streaming lifecycle, header, mounting, reveal, and disposal under Markstream's control. - Keep
html-policy="safe"and Mermaid strict mode unless the task is preserving trusted legacy rendering. - If a trusted client-only surface needs older behavior, opt out locally with
html-policy="trusted"and:mermaid-props="{ isStrict: false }", and document why that surface is trusted.
Useful Doc Targets
docs/nuxt-ssr.mddocs/guide/installation.mddocs/guide/usage.mddocs/guide/troubleshooting.md