tanstack/markdown · Archived

production-pipelines

Audit and ship a production Markdown pipeline with explicit trust boundaries, external syntax highlighting, parse-ahead caching, compatibility checks, deterministic output, and bundle budgets. Load before deploying blogs, docs, or untrusted-content rendering.

First seen Aug 23, 2026

Installation

$ npx skills add tanstack/markdown --skill production-pipelines

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from tanstack/markdown.

npx skills add tanstack/markdown

Browse all from tanstack/markdown

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 126
Default branch main
Open issues 4
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

More metadata
type
lifecycle
library
@tanstack/markdown
library_version
0.0.13

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 13,498 B
  • docs SUMMARY.md 287 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 3 installs

SKILL.md

This skill builds on render-markdown. Read it first for the supported syntax, AST, parser options, and renderer contracts.

TanStack Markdown — Production Pipeline Checklist

Run every section before deploying a blog, documentation site, or user-content renderer.

Trust Boundary Checks

Check: Classify every Markdown source

Expected:

import { renderHtml } from '@tanstack/markdown/html'

export function renderUntrustedMarkdown(
  source: string,
  sanitize: (html: string) => string,
): string {
  const rendered = renderHtml(source)
  return sanitize(rendered)
}

Fail condition: Untrusted input reaches allowHtml, an unaudited extension renderHtml hook, or an unaudited highlighter.

Fix: Separate trusted and untrusted entry points, keep trusted callbacks disabled for untrusted content, and enforce application link, image, and final-HTML policy.

Highlighting Checks

Check: Return trusted code contents only

Expected:

import { renderHtml } from '@tanstack/markdown/html'
import { createHighlighter } from '@tanstack/highlight/core'
import { plaintext } from '@tanstack/highlight/languages/plaintext'
import { ts } from '@tanstack/highlight/languages/ts'
import { createTanStackMarkdownHighlighter } from '@tanstack/highlight/markdown'
const highlighter = createHighlighter({ languages: [plaintext, ts] })
export const html = renderHtml('```ts {1}\nconst answer = 42\n```', {
  highlighter: createTanStackMarkdownHighlighter(highlighter),
})

Fail condition: The callback returns a complete <pre><code> tree, does not escape source code, or comes from an unreviewed transform.

Fix: Return only escaped markup for the renderer-owned <code> contents, and run highlighting during ingestion, build, or server rendering.

Compatibility Checks

Check: Validate the actual content corpus

Expected:

MARKDOWN_CORPUS_DIRS=../site/src/blog:../site/docs pnpm run test:corpus
pnpm run corpus:audit:tanstack
pnpm run corpus:audit:external

Fail condition: Adoption relies only on CommonMark examples or a comparison table instead of the site's Markdown.

Fix: Add downstream content directories, preserve practical regressions with focused fixtures, and require renderer and bundle accounting for new syntax.

Check: Verify deterministic output

Expected:

import { renderHtml } from '@tanstack/markdown/html'
import { parseMarkdown } from '@tanstack/markdown/parser'

const source = '# Deterministic\n\n- one\n- two'
const firstDocument = JSON.stringify(parseMarkdown(source))
const secondDocument = JSON.stringify(parseMarkdown(source))
const firstHtml = renderHtml(source)
const secondHtml = renderHtml(source)

if (firstDocument !== secondDocument || firstHtml !== secondHtml) {
  throw new Error('Markdown output is nondeterministic')
}

Fail condition: Identical source and options produce different serialized AST or HTML.

Fix: Remove time, randomness, environment state, and unstable ordering from extensions and render callbacks.

Performance and Cache Checks

Check: Parse once with final options

Expected:

import type { MarkdownDocument } from '@tanstack/markdown'
import { renderHtml } from '@tanstack/markdown/html'
import { parseMarkdown } from '@tanstack/markdown/parser'

const cache = new Map<string, MarkdownDocument>()

export function renderCachedArticle(key: string, source: string): string {
  const cacheKey = `markdown-0.0.13:${key}`
  let document = cache.get(cacheKey)
  if (!document) {
    document = parseMarkdown(source, {
      frontmatter: true,
      headingIds: true,
    })
    cache.set(cacheKey, document)
  }
  return renderHtml(document)
}

Fail condition: Stable content is reparsed per request, or parser options/extensions change after the AST is cached.

Fix: Build the AST with final parse options, version persisted cache keys, invalidate stored ASTs when node contracts change, and use only narrow entry points.

Check: Enforce bundle budgets

Expected:

pnpm run size
pnpm test -- tests/bundle-size.test.ts

Fail condition: Any measured entry exceeds its checked gzip budget or starts bundling a highlighter.

Fix: Inspect the bundle diff and justify any syntax or dependency cost before adjusting a budget.

Release Checks

Check: Run the complete package gate

Expected:

pnpm run verify

Fail condition: Tests, typechecking, build, docs validation, conformance accounting, sizes, benchmarks, or the npm dry run fail.

Fix: Resolve every gate before publishing, including HTML/React/Octane parity; audit raw HTML, highlighter output, HTML hooks, and component replacements separately.

Common Production Mistakes

CRITICAL Enabling HTML for untrusted Markdown

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

export function renderComment(source: string): string {
  return renderHtml(source, { allowHtml: true })
}

Correct:

import { renderHtml } from '@tanstack/markdown/html'

export function renderComment(source: string): string {
  return renderHtml(source)
}

allowHtml emits raw nodes and is not a sanitization step.

Source: docs/core-concepts/security.md

HIGH Returning highlighter containers

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

function escapeCode(code: string): string {
  return code.replace(/[&<>]/g, (character) => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
  })[character] ?? character)
}

console.log(renderHtml('```ts\nconst x = 1\n```', {
  highlighter: (code) => `<pre><code>${escapeCode(code)}</code></pre>`,
}))

Correct:

import { renderHtml } from '@tanstack/markdown/html'

function escapeCode(code: string): string {
  return code.replace(/[&<>]/g, (character) => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
  })[character] ?? character)
}

console.log(renderHtml('```ts\nconst x = 1\n```', {
  highlighter: (code) => `<span class="token">${escapeCode(code)}</span>`,
}))

The renderer owns <pre><code>; the callback supplies only the code element's trusted contents.

Source: docs/guides/syntax-highlighting.md

CRITICAL Trusting arbitrary highlighter output

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

const source = '```html\n<img src=x onerror=alert(1)>\n```'
console.log(renderHtml(source, { highlighter: (code) => code }))

Correct:

import { renderHtml } from '@tanstack/markdown/html'

function escapeCode(code: string): string {
  return code.replace(/[&<>]/g, (character) => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
  })[character] ?? character)
}

const source = '```html\n<img src=x onerror=alert(1)>\n```'
console.log(renderHtml(source, { highlighter: escapeCode }))

Highlighter output is inserted without further escaping in every renderer.

Source: docs/core-concepts/security.md

MEDIUM Bundling highlighting into static clients

Wrong:

import { Markdown } from '@tanstack/markdown/react'
import { tokenize } from '@tanstack/highlight'

export function Article({ source }: { source: string }) {
  return <Markdown highlighter={(code) => String(tokenize(code))}>{source}</Markdown>
}

Correct:

import { renderHtml } from '@tanstack/markdown/html'
import type { CodeHighlighter } from '@tanstack/markdown'

export function renderStaticArticle(
  source: string,
  highlighter: CodeHighlighter,
): string {
  return renderHtml(source, { highlighter })
}

Tokenizer runtimes, grammars, and themes can outweigh Markdown parsing and should remain build-time or server-side for static content.

Source: docs/guides/performance.md

CRITICAL Treating defaults as a sanitizer

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

export function renderForEveryPolicy(source: string): string {
  return renderHtml(source)
}

Correct:

import { renderHtml } from '@tanstack/markdown/html'

export function renderWithPolicy(
  source: string,
  sanitize: (html: string) => string,
): string {
  return sanitize(renderHtml(source))
}

Core escaping and protocol filtering do not enforce application-specific outbound-link, image, or final-HTML policy.

Source: docs/core-concepts/security.md

HIGH Assuming complete CommonMark behavior

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

export function renderArbitraryMarkdown(source: string): string {
  return renderHtml(source)
}

Correct:

import { renderHtml } from '@tanstack/markdown/html'

export function renderControlledDocs(source: string): string {
  return renderHtml(source)
}

The package implements a documented docs/blog profile, not complete CommonMark, GFM, MDX, or arbitrary plugin behavior.

Source: docs/core-concepts/syntax-profile.md

MEDIUM Reparsing unchanged content

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

export function renderRequest(source: string): string {
  return renderHtml(source)
}

Correct:

import type { MarkdownDocument } from '@tanstack/markdown'
import { renderHtml } from '@tanstack/markdown/html'
import { parseMarkdown } from '@tanstack/markdown/parser'

export function compile(source: string): MarkdownDocument {
  return parseMarkdown(source)
}

export function renderRequest(document: MarkdownDocument): string {
  return renderHtml(document)
}

String render inputs parse the complete document, while a cached MarkdownDocument skips that work.

Source: docs/core-concepts/document-model.md

HIGH Injecting HTML into React

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

export function Article({ source }: { source: string }) {
  const html = renderHtml(source)
  return <article dangerouslySetInnerHTML={{ __html: html }} />
}

Correct:

import { Markdown } from '@tanstack/markdown/react'

export function Article({ source }: { source: string }) {
  return <article><Markdown>{source}</Markdown></article>
}

The HTML string adds a trusted insertion boundary and bypasses React component replacement.

Source: docs/guides/react.md

MEDIUM Expecting fence metadata to highlight

Wrong:

import { renderHtml } from '@tanstack/markdown/html'

const source = '```ts {1}\nconst answer = 42\n```'
console.log(renderHtml(source))

Correct:

import { renderHtml } from '@tanstack/markdown/html'

function escapeCode(code: string): string {
  return code.replace(/[&<>]/g, (character) => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
  })[character] ?? character)
}

const source = '```ts {1}\nconst answer = 42\n```'
console.log(renderHtml(source, { highlighter: escapeCode }))

Fence metadata enters the AST, but token markup requires an external highlighter.

Source: docs/core-concepts/syntax-profile.md

Tensions

Compatibility breadth versus bundle budget

Do not maximize conformance by default. Require target-corpus evidence, renderer coverage, and measured bundle cost before adding syntax.

Rich trusted output versus untrusted-content safety

Do not enable raw HTML, extension HTML, or highlighter markup globally to solve presentation needs. Scope each trusted callback to controlled content.

Parse-ahead performance versus option timing

Build cached ASTs with final parser options and document transforms. Keep required HTML render hooks active when rendering those cached documents.

Pre-Deploy Summary

  • Every content source is classified as trusted or untrusted.
  • Raw HTML, extension HTML, and highlighter output have explicit owners.
  • Application link, image, and final-sanitization policies are enforced.
  • The downstream corpus passes deterministic AST and renderer checks.
  • Unsupported syntax is documented rather than silently assumed.
  • Stable content is parsed once with final options and versioned cache keys.
  • Highlighting runs at build time or on the server where possible.
  • Narrow entry points and individual extensions are used.
  • Bundle budgets and HTML/React/Octane parity tests pass.
  • pnpm run verify passes before release.

Related Skills

  • render-markdown for the supported profile, AST, parser options, and core HTML rendering.
  • docs-features for docs metadata and code-fence behavior.
  • custom-extensions for parser hooks and trusted HTML extension boundaries.
  • react-rendering and octane-rendering for framework component policy and SSR parity.