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

velomark

v0.1.0

Published

Solid-only markdown rendering tuned for streamed AI responses.

Readme

velomark

pnpm

Solid-only Markdown rendering built for streamed AI responses.[^incremark]

velomark is a public npm package for apps that need Markdown rendering to stay responsive while content is still arriving. It is optimized for append-heavy streams, stable DOM identity for already-rendered blocks, and a restrained Solid-first API that is easy to integrate into product code.

Why use velomark?

  • Streaming-first rendering instead of snapshot-first repainting
  • Stable block reuse so earlier content keeps its DOM identity when later content grows
  • Solid-only package surface with no framework abstraction layer
  • Strong built-in syntax surface for the Markdown features common in coding-agent output
  • Built-in defaults for code blocks, Mermaid, math, footnotes, directives, tables, and HTML
  • First-class theming with semantic tokens, light and dark presets, and partial overrides

Requirements

  • solid-js ^1.9.10
  • Node.js >=18
  • A stylesheet import from velomark/styles.css

Install

pnpm add velomark solid-js

You can also use npm or yarn if that is what your app already uses.

Quick start

import { Velomark } from "velomark";
import "velomark/styles.css";

const markdown = `# Hello

This is **streamed** Markdown.

\`\`\`ts
const answer = 42;
\`\`\`
`;

export function Example() {
  return <Velomark markdown={markdown} />;
}

Common integration examples

Render a live stream

import { createSignal } from "solid-js";
import { Velomark } from "velomark";
import "velomark/styles.css";

export function StreamingExample() {
  const [markdown, setMarkdown] = createSignal("# Thinking");

  const append = (chunk: string) => {
    setMarkdown(current => current + chunk);
  };

  return (
    <>
      <button onClick={() => append("\n\nMore content arrived.")}>Append</button>
      <Velomark markdown={markdown()} />
    </>
  );
}

Use the built-in dark theme

import { Velomark } from "velomark";
import "velomark/styles.css";

export function DarkExample(props: { markdown: string }) {
  return <Velomark markdown={props.markdown} theme="dark" />;
}

Override part of the theme

import { Velomark } from "velomark";
import "velomark/styles.css";

export function BrandedExample(props: { markdown: string }) {
  return (
    <Velomark
      markdown={props.markdown}
      theme={{
        color: {
          text: {
            accent: "#0f62fe",
          },
          diagram: {
            primary: "#0f62fe",
            secondary: "#78a9ff",
          },
        },
      }}
    />
  );
}

Apply a theme to a host element

import { applyTheme } from "velomark";

const host = document.querySelector(".markdown-preview");

if (host instanceof HTMLElement) {
  applyTheme(host, "dark");
}

Override a language-specific code block renderer

import type { VelomarkCodeBlockRendererProps } from "velomark";
import { Velomark } from "velomark";
import "velomark/styles.css";

function JsonBlock(props: VelomarkCodeBlockRendererProps) {
  return (
    <pre>
      <code>{JSON.stringify(JSON.parse(props.code), null, 2)}</code>
    </pre>
  );
}

export function CustomCodeExample(props: { markdown: string }) {
  return (
    <Velomark
      codeBlockRenderers={{
        json: JsonBlock,
      }}
      markdown={props.markdown}
    />
  );
}

Override a directive container

import type { VelomarkContainerRendererProps } from "velomark";
import { Velomark } from "velomark";
import "velomark/styles.css";

function Callout(props: VelomarkContainerRendererProps) {
  return (
    <aside data-callout={props.name}>
      <strong>{props.attributes?.title ?? "Note"}</strong>
      <div>{props.children}</div>
    </aside>
  );
}

export function CustomContainerExample(props: { markdown: string }) {
  return (
    <Velomark
      containers={{
        info: Callout,
        warning: Callout,
      }}
      markdown={props.markdown}
    />
  );
}

What Velomark renders well

Core blocks

  • Paragraphs and headings
  • Ordered, unordered, nested, and task lists
  • Blockquotes
  • Fenced code blocks with syntax highlighting
  • Mermaid fences rendered as diagrams
  • Tables with column alignment
  • Thematic breaks
  • Footnote definitions
  • Math blocks
  • Raw HTML blocks and structured HTML elements
  • Container, leaf, and text directives

Inline syntax

  • Strong, emphasis, delete, and inline code
  • Links and images
  • Hard line breaks
  • Footnote references
  • Inline math
  • Raw inline HTML and structured inline HTML elements
  • Reference-style links and images, including collapsed and shortcut forms

Streaming behavior

  • Append-heavy content growth
  • Tail rewrites
  • Incomplete intermediate states for fences, references, directives, HTML, and tables
  • Stable outer code-block shell while highlighted code grows

For the full status matrix, see docs/feature-matrix.md.

Code blocks and Mermaid

velomark ships generic built-in code block behavior by default:

  • syntax highlighting for supported fenced languages
  • a floating copy button for standard code fences
  • a floating language badge when a language exists
  • theme-aware colors for code surfaces

Mermaid uses its own dedicated rendering path:

  • successful Mermaid fences render as diagrams, not as generic code blocks
  • incomplete streaming fences stay in plain code mode until the fence is complete
  • invalid diagrams fall back to source rendering instead of failing the whole block
  • diagram colors are derived from the active VelomarkTheme

You can tune standard code blocks with codeBlockOptions:

<Velomark
  codeBlockOptions={{
    copyButton: true,
    highlight: true,
    highlightTheme: "github-dark",
    languageLabel: true,
  }}
  markdown={markdown}
/>

Theming

velomark uses semantic theme tokens instead of ad hoc component color props.

Built-in presets:

  • default
  • dark

Public theme utilities:

import {
  applyTheme,
  darkTheme,
  defaultTheme,
  generateCssVars,
  mergeTheme,
  resolveTheme,
  velomarkColors,
  velomarkThemePresets,
  velomarkTokens,
} from "velomark";

The public contract is:

  • use theme="default" or theme="dark"
  • pass a partial VelomarkTheme object when you need to override specific semantic tokens
  • use applyTheme or generateCssVars when you need container-scoped control outside the component

Theme coverage includes:

  • text and link colors
  • code blocks, inline code, copy controls, and language badges
  • blockquotes, tables, and math fallback surfaces
  • Mermaid diagram theme variables
  • typography, radius, shadow, and spacing tokens

Public API

Component

interface VelomarkProps {
  class?: string;
  codeBlockOptions?: {
    copyButton?: boolean;
    defaultView?: "preview" | "source";
    highlight?: boolean;
    highlightTheme?: string;
    languageLabel?: boolean;
    previewToggle?: boolean;
  };
  codeBlockRenderers?: Record;
  containers?: Record;
  debug?: boolean;
  markdown: string;
  onDebugMetrics?: (metrics: VelomarkDebugMetrics) => void;
  theme?: "default" | "dark" | Partial;
}

Key exported types

import type {
  InlineToken,
  PartialVelomarkTheme,
  RenderBlock,
  RenderDocument,
  VelomarkCodeBlockOptions,
  VelomarkCodeBlockRendererProps,
  VelomarkContainerRendererProps,
  VelomarkProps,
  VelomarkTheme,
  VelomarkThemeName,
} from "velomark";

Parser export

parseInline is exported for advanced consumers that need inline-token parsing outside the component.

Security and trust model

velomark supports raw HTML and structured HTML rendering. If your Markdown source is untrusted, sanitize it before you pass it into Velomark.

This package focuses on rendering and streaming behavior. It does not try to be an HTML sanitizer.

Troubleshooting

The Markdown renders with no styling

You probably forgot the stylesheet import:

import "velomark/styles.css";

Code fences render without syntax highlighting

Check these first:

  • the fence has a language, for example ```ts
  • codeBlockOptions.highlight is not disabled
  • the requested language is supported by the active highlighter setup

Unlabeled fences intentionally render as plain code.

Mermaid falls back to source

That is expected when:

  • the fence is still streaming and incomplete
  • the Mermaid source is invalid
  • Mermaid cannot finish rendering the diagram

The consumer gets a Solid peer dependency warning

Make sure the app uses solid-js ^1.9.10 or newer within the supported major range.

FAQ

Is Velomark a full CommonMark or GFM engine?

Not in the abstract “everything Markdown supports” sense. It targets the syntax and rendered surface that matter most for streamed AI and coding-assistant output, and it has strong coverage for that subset.

Does it support React, Vue, or Svelte?

No. velomark is intentionally Solid-only.

Can I override rendering?

Yes, but the public API is intentionally restrained. Today the main extension seams are:

  • codeBlockRenderers
  • containers
  • theme overrides
  • onDebugMetrics

Is the playground part of the runtime package?

No. The dev playground exists to inspect streamed behavior and theme previews during package development. It is not a runtime dependency of published consumers.

Development

pnpm install --ignore-workspace
pnpm exec vitest run
pnpm run lint:types
pnpm run lint:code
pnpm run build
pnpm run test:packed-consumer

To inspect the local playground:

pnpm run dev

[^incremark]: Velomark is inspired by the renderer goals and streaming ergonomics explored in Incremark, while keeping a smaller Solid-only public surface.