3k Simon-He95

markstream-nuxt Skill

将 markstream-vue 集成到 Nuxt 3 或 Nuxt 4 应用中。当 Codex 需要仅客户端边界、SSR 安全配置、仅浏览器端 peer 门控、支持 worker 的初始化、渲染器 `mode` 选择,或在页面、组件或 Nuxt 插件中安全集成 `MarkdownRender` 时使用。

安装方式:把技能目录放入 ~/.claude/skills/(Claude Code)或在 claude.ai 设置中启用;也可复制右侧安装命令一键添加。

查看源码

技能指令原文(SKILL.md)

Markstream Nuxt

Use this skill when the host app is Nuxt and SSR boundaries matter.

Workflow

  1. Confirm the repo is Nuxt 3 or 4.
  2. Install markstream-vue plus only the optional peers required by the requested features.
  3. Keep browser-only peers behind client-only boundaries.
  • Prefer wrappers, .client plugins, or guarded setup paths.
  1. Import markstream-vue/index.css from a client-safe app shell or plugin.
  • The root JS import does not inject styles; use markstream-vue/index.css or markstream-vue/index.px.css explicitly.
  1. Start with content, choose the renderer mode by surface, and move to nodes plus final only when the UI needs custom AST control.
  • Use mode="chat" for AI chat or SSE output. It uses lightweight batches, fade=false, and max-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-diffs when the optional peer is installed. Use render-code-blocks-as-pre for a forced plain path or setCustomComponents(customId, { code_block: ... }) for a scoped application-owned renderer.
  • typewriter only controls the blinking cursor and defaults to false. Prefer typewriter="simple" for high-frequency chat.
  • In Vue 3 (including Nuxt), smooth-streaming controls output pacing and fade controls opacity; they can be enabled together. mode="chat" keeps fade=false as a lightweight default. Add fade when 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 MarkdownRender starts streaming and later switches to history when final=true.
  • Streaming: start with mode="chat" and final; add fade for text reveal and typewriter only when a cursor is wanted.
  • Recovering/completed chat history: keep mode="chat" on the same chat row; use :smooth-streaming="false", typewriter=false, and choose fade independently 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 use mode="docs" only for rich document surfaces.
  • In SSR, avoid smooth-streaming="true" on first-screen content; the mounted gate inside auto prevents hydration mismatch.
  • Remember that html-policy now defaults to safe, and Mermaid strict mode is on by default through mermaid-props.
  1. Validate with the smallest relevant Nuxt dev, build, or typecheck command.

Default Decisions

  • SSR safety comes before feature completeness.
  • Omit mode only when the surface should use rich docs defaults.
  • Smooth streaming is SSR-safe in auto mode (the default) because it gates on mount. Do not use smooth-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 useStickToBottom from markstream-vue/utils and call scheduleScrollToBottom() after Vue commits new content. The composable attaches browser listeners after mount; use MarkstreamVirtualTimeline with stick-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 (setStreamDiffsWorkerPool from markstream-vue, backed by an upstream @pierre/diffs WorkerPoolManager) 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 install stream-monaco.
  • Use top-level code-block-options for 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.md
  • docs/guide/installation.md
  • docs/guide/usage.md
  • docs/guide/troubleshooting.md