Migrate Markdown renderers without breaking features
Migrates an app from react-markdown, markdown-it, or marked to Markstream while preserving transforms, URL policy, and streaming semantics.
Why it matters
Replace an existing Markdown renderer (react-markdown, markdown-it, marked) with Markstream while preserving all transforms, custom components, URL policies, raw-HTML behavior, streaming semantics, and security boundaries.
Outcomes
What it gets done
Inventory all renderer imports, plugins, HTML policies, URL transforms, custom renderers, and tests before migration
Map existing built-in renderers and plugins to Markstream scoped overrides and component maps
Preserve safe HTML defaults and streaming behavior while maintaining visual and functional parity
Run builds and behavior tests to verify mappings and document intentional differences
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/ag-markstream-migration | bash Overview
Markstream Migration
Migrates an existing Markdown renderer (react-markdown, markdown-it, marked) to Markstream while preserving custom transforms, URL policy, and security behavior. Use when replacing a Markdown renderer or choosing between Markstream's content, smooth-streaming, and nodes modes.
What it does
This skill replaces an existing Markdown renderer without silently dropping transforms, custom components, URL policy, raw-HTML behavior, or streaming semantics, directing readers to a companion adoption-checklist reference first. Its workflow: before changing dependencies or source files, inspect the existing package manager and project conventions, preview the intended edits, and obtain explicit user approval; inventory renderer imports, call sites, plugins, HTML policy, URL transforms, allowlists, custom renderers, CSS, and tests; classify the migration as direct, renderer-custom, plugin-heavy, or security-heavy; install the Markstream framework package and its explicit CSS, preserving visible behavior before adding optional features; map built-ins to scoped overrides, preferring renderer-local component maps in React; use trusted custom tags only for trusted content and reserve parse transforms for irreducible token/AST requirements; keep the content prop with smooth streaming for ordinary token streams, reaching for nodes only for worker parsing, shared AST ownership, or structural transforms; preserve safe HTML and strict Mermaid defaults, scoping and documenting any trusted legacy exception; and finally run the relevant builds and behavior tests, reporting mappings, intentional differences, and anything left for review.
Documented limitations: Markstream cannot reproduce every remark, rehype, or markdown-it plugin automatically, visual parity does not prove security or URL-policy parity, and large migrations may require a staged conversion. A security note: do not weaken sanitization just to achieve screenshot parity, and explicitly review dependencies, raw HTML, URL transforms, and trust boundaries during the migration.
When to use - and when NOT to
Use when replacing react-markdown, markdown-it, marked, or another renderer; migrating node renderers; or choosing between Markstream's content, smooth streaming, and nodes modes.
Inputs and outputs
Input is an existing Markdown-rendering codebase using a different library. Output is a Markstream-based renderer with visible behavior preserved, explicit HTML/URL/trust-boundary decisions documented, and a report of mappings, intentional differences, and unresolved review items.
// Before:
// import ReactMarkdown from 'react-markdown'
// return <ReactMarkdown>{markdown}</ReactMarkdown>
import MarkdownRender from 'markstream-react'
import 'markstream-react/index.css'
export function AssistantAnswer({
markdown,
isDone,
}: {
markdown: string
isDone: boolean
}) {
return (
<MarkdownRender
content={markdown}
final={isDone}
fade={isDone}
typewriter={!isDone}
smoothStreaming={isDone ? false : 'auto'}
htmlPolicy="safe"
/>
)
}
Who it's for
Developers migrating an existing app off react-markdown, markdown-it, marked, or another renderer onto Markstream, who need to preserve custom transforms, URL policy, and security behavior rather than just matching the old visual output.
Source README
Markstream Migration
Overview
Replace an existing Markdown renderer without silently dropping transforms, custom components, URL policy, raw-HTML behavior, or streaming semantics. Read references/adoption-checklist.md first.
When to Use
Use when replacing react-markdown, markdown-it, marked, or another renderer; migrating node renderers; or choosing between Markstream content, smooth streaming, and nodes.
Workflow
Before changing dependencies or source files, inspect the existing package manager and project conventions, preview the intended edits, and obtain explicit user approval.
- Inventory renderer imports, call sites, plugins, HTML policy, URL transforms, allowlists, custom renderers, CSS, and tests.
- Classify the migration as direct, renderer-custom, plugin-heavy, or security-heavy.
- Install the framework package and explicit CSS. Preserve visible behavior before optional features.
- Map built-ins to scoped overrides; in React prefer renderer-local component maps.
- Use trusted custom tags only for trusted content and reserve parse transforms for irreducible token/AST requirements.
- Keep
contentwith smooth streaming for ordinary token streams. Usenodesonly for worker parsing, shared AST ownership, or structural transforms. - Preserve safe HTML and strict Mermaid defaults; scope and document any trusted legacy exception.
- Run relevant builds and behavior tests. Report mappings, intentional differences, and unresolved review.
Example
// Before:
// import ReactMarkdown from 'react-markdown'
// return <ReactMarkdown>{markdown}</ReactMarkdown>
import MarkdownRender from 'markstream-react'
import 'markstream-react/index.css'
export function AssistantAnswer({
markdown,
isDone,
}: {
markdown: string
isDone: boolean
}) {
return (
<MarkdownRender
content={markdown}
final={isDone}
fade={isDone}
typewriter={!isDone}
smoothStreaming={isDone ? false : 'auto'}
htmlPolicy="safe"
/>
)
}
Limitations
- Markstream cannot reproduce every remark, rehype, or markdown-it plugin automatically.
- Visual parity does not prove security or URL-policy parity.
- Large migrations may require staged conversion.
Security & Safety Notes
Do not weaken sanitization for screenshot parity. Review dependencies, raw HTML, URL transforms, and trust boundaries explicitly.
Discussion
Questions & comments ยท 0
Sign In Sign in to leave a comment.