npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@brett_lamy/docstream

v0.6.4

Published

GitBook-aware readonly markdown and AI stream renderer.

Downloads

1,741

Readme

@brett_lamy/docstream

GitBook-aware markdown rendering for React applications and AI streaming surfaces.

@brett_lamy/docstream combines a small GitBook-flavored markdown parser with React renderers that can display docs blocks while a response is still streaming. It is designed for read-only documentation previews, AI answer panes, and apps that need GitBook-specific syntax without embedding a full editor.

Features

  • React renderer for GitBook-style markdown blocks.
  • Streaming-friendly GitbookStreamdown component inspired by vercel/streamdown.
  • Parser and serializer for round-tripping supported GitBook syntax.
  • Syntax-highlighted code blocks through lowlight.
  • GitBook block support for hints, tabs, expandables, steppers, embeds, content refs, columns, figures, tables, math, dividers, updates, and OpenAPI operations.
  • CSS exported as a stable package entrypoint so host apps can theme with CSS variables or shadcn-style design tokens.
  • Attribute-aware direct video embeds for muted, looping inline clips in long-form posts.
  • Optional VizEmbed integration for mounting deterministic @brett_lamy/viz-engine scenes in a document.
  • Vite source mounts for rendering and editing real component or Storybook files without copying implementations into Markdown.

Installation

npm install @brett_lamy/docstream react

React is a peer dependency and must be provided by your app.

Basic Setup

Import the package CSS once near your app entrypoint:

import "@brett_lamy/docstream/styles.css"

The stylesheet provides heading hierarchy and consistent spacing for the DocsRenderer, MarkdownContent, and streaming render paths. Host CSS can override those defaults through the normal cascade.

If your TypeScript app checks CSS side-effect imports, include Vite's standard environment declaration or an equivalent CSS module declaration:

/// <reference types="vite/client" />

Render Streaming Markdown

Use GitbookStreamdown when markdown may arrive incrementally from an AI stream. The component accepts either markdown or string children.

Markdown-only applications can import the renderer from the streamdown subpath. This keeps optional playground integrations out of the host bundle:

import { GitbookStreamdown } from "@brett_lamy/docstream/streamdown"
import { GitbookStreamdown } from "@brett_lamy/docstream"
import "@brett_lamy/docstream/styles.css"

export function Answer({ text, isStreaming }: { text: string; isStreaming: boolean }) {
  return (
    <GitbookStreamdown markdown={text} isStreaming={isStreaming} />
  )
}

isStreaming adds aria-busy and a data-streaming attribute to the wrapper. isAnimating is also accepted for compatibility with stream UI state.

Render Parsed Documents

Use parseMarkdown and DocsRenderer when you want to parse once, inspect the AST, or serialize it later.

import { DocsRenderer, parseMarkdown, serializeMarkdown } from "@brett_lamy/docstream"

const doc = parseMarkdown(markdown)
const roundTripped = serializeMarkdown(doc)

export function Preview() {
  return <DocsRenderer doc={doc} />
}

Markdown Helper Component

MarkdownContent parses and renders a markdown string in one step:

import { MarkdownContent } from "@brett_lamy/docstream"

export function Preview({ markdown }: { markdown: string }) {
  return <MarkdownContent markdown={markdown} />
}

GitBook Syntax

The parser supports normal Markdown plus GitBook-style block tags.

Hints

{% hint style="info" %}
Helpful context for the reader.
{% endhint %}

Supported styles are info, success, warning, and danger.

Tabs

{% tabs %}
{% tab title="TypeScript" %}
```ts
export const ok = true
```
{% endtab %}
{% tab title="JSON" %}
```json
{ "ok": true }
```
{% endtab %}
{% endtabs %}

Expandables

{% expandable title="More details" %}
Hidden content goes here.
{% endexpandable %}

Steppers

{% stepper %}
{% step %}
Create a token.
{% endstep %}
{% step %}
Call the API.
{% endstep %}
{% endstepper %}

OpenAPI Operations

{% openapi-operation spec="petstore.yaml" path="/store/orders" method="get" /%}

When a spec cannot be resolved, the renderer displays a fallback asking for an OpenAPI spec URL.

Inline video clips

Direct media embeds can opt into browser-safe inline playback. muted is important when autoplay is enabled:

{% embed url="/generated/example/clips/offsets.mp4"
  title="A reader resumes from its bookmark"
  autoplay="true" loop="true" muted="true" controls="false" %}

The attributes round-trip through parseMarkdown and serializeMarkdown and are rendered as a native <video playsInline> element.

VizEngine scenes

Install the optional peer dependency when a document needs a live, seekable scene rather than a rendered clip:

npm install @brett_lamy/docstream @brett_lamy/viz-engine
import { VizEmbed } from "@brett_lamy/docstream/viz"
import "@brett_lamy/docstream/styles.css"

<VizEmbed scene={scene} title="The same event, replayed into two projections" />

VizEmbed keeps the scene's timeline deterministic and delegates the clock to VizEngine, so a reader can pause or scrub the same explanation used to produce the short clip.

File-backed components and stories

Markdown is the composition layer. Keep component and Storybook implementations in normal source files, then mount their directory in Vite:

// vite.config.ts
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
import { docstreamSources } from "@brett_lamy/docstream/vite"

export default defineConfig({
  plugins: [
    react(),
    docstreamSources({
      mounts: [{ name: "ui", root: "src/components" }],
    }),
  ],
})

Reference a named component export or a CSF story from Markdown:

{% source-ref mount="ui" path="Button.tsx" export="Button" kind="component" title="Button" %}

{% source-ref mount="ui" path="Button.stories.tsx" export="Primary" kind="story" title="Primary button" %}

Render references using the Vite client. The AST keeps mount, path, exportName, and kind, so provenance survives parse/edit/serialize cycles:

import { MarkdownContent, SourcePreview, createViteSourceClient } from "@brett_lamy/docstream"

const client = createViteSourceClient()

export function Guide({ markdown }: { markdown: string }) {
  return (
    <MarkdownContent
      markdown={markdown}
      sourceRenderer={(reference) => <SourcePreview reference={reference} client={client} />}
    />
  )
}

client.read(reference) returns the current file plus provenance. client.write(reference, content) writes back to the mounted real file. The plugin validates the mount boundary, only edits existing files, and notifies Vite after a save so the preview reloads through Vite's normal module pipeline. Set writable: false on a mount when a documentation site should only render.

The Vite endpoints exist only during development. For a deployed static site, bundle the referenced modules and use the read-only production client:

import { createBundledSourceClient } from "@brett_lamy/docstream"
import * as ButtonModule from "./components/Button"

const client = createBundledSourceClient({
  "ui:Button.tsx": ButtonModule,
})

Entries may also be lazy import functions. Keys can be mount:path (recommended) or just path when names cannot collide.

Assets and OpenAPI Specs

Relative image and OpenAPI spec paths can be resolved against an asset base:

import { setAssetBase } from "@brett_lamy/docstream"

setAssetBase("/docs/assets/")

You can also resolve paths yourself with resolveAsset.

API Reference

Components

  • GitbookStreamdown: Parses and renders markdown for read-only stream output.
  • DocsRenderer: Renders a parsed DocumentNode.
  • MarkdownContent: Parses and renders a markdown string.
  • OpenApiOperation: Renders a parsed OpenAPI operation block.
  • SourcePreview: Imports and renders a mounted component or CSF story export.
  • createViteSourceClient: Reads, writes, and imports files exposed by the Vite plugin.
  • createBundledSourceClient: Imports bundled source modules in read-only production builds.

Parser and Serializer

  • parseMarkdown(markdown): Converts a full markdown document into a DocumentNode.
  • parseBlocks(markdown): Parses markdown into block nodes.
  • serializeMarkdown(doc): Converts a DocumentNode back to markdown.
  • serializeBlocks(blocks): Serializes block nodes.
  • parseInline(markdown): Parses inline markdown nodes.
  • serializeInline(nodes): Serializes inline nodes.
  • plainText(nodes): Extracts plain text from inline nodes.
  • refDefinitions(markdown): Reads reference-style link definitions.

Types

All AST types are exported from the package root, including DocumentNode, Block, Inline, and HintStyle.

Styling and Theming

The package CSS is intentionally token-driven. It uses normal CSS variables and class names so host apps can align the renderer with a shadcn-style theme.

:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --border: 214.3 31.8% 91.4%;
  --muted: 210 40% 96.1%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --primary: 221.2 83.2% 53.3%;
}

Import the CSS once, then set tokens globally in your app. Components also expose stable classes such as docs-code, docs-tabs, docs-hint, docs-table, and docs-openapi.

Bundler Notes

This release ships TypeScript and TSX source through ESM exports:

{
  "exports": {
    ".": {
      "types": "./src/index.ts",
      "import": "./src/index.ts"
    },
    "./styles.css": "./src/styles.css"
  }
}

It is validated with Vite and modern TypeScript moduleResolution: "Bundler". Plain Node.js, CommonJS, or tooling that does not transpile TypeScript in dependencies may need a future precompiled JS build.

Related Package

Use @brett_lamy/docstream-editor when you need the editable TipTap experience for the same document model.