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

@slexkit/streamdown

v0.3.0

Published

Streamdown custom renderer for SlexKit fenced UI blocks.

Readme

@slexkit/streamdown

Streamdown custom renderer for Slex fenced UI blocks.

Install

npm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom

Import both style sheets in your app:

import "@slexkit/theme-shadcn/style.css";
import "@slexkit/streamdown/style.css";

Minimal Usage

import { Streamdown } from "streamdown";
import { slexkitRenderer } from "@slexkit/streamdown";

export function Message({ markdown }: { markdown: string }) {
  return (
    <Streamdown plugins={{ renderers: [slexkitRenderer] }}>
      {markdown}
    </Streamdown>
  );
}

Vercel AI SDK

import { useChat } from "@ai-sdk/react";
import { Streamdown } from "streamdown";
import { slexkitRenderer } from "@slexkit/streamdown";

export function Chat() {
  const { messages, status } = useChat();

  return messages.map((message) =>
    message.parts.map((part, index) =>
      part.type === "text" ? (
        <Streamdown
          key={index}
          isAnimating={status === "streaming"}
          plugins={{ renderers: [slexkitRenderer] }}
        >
          {part.text}
        </Streamdown>
      ) : null,
    ),
  );
}

Model Output

Ask the model to emit Slex only in explicit slex fenced blocks. The body is JavaScript-compatible Slex source: a plain object literal with native JS state and expression strings.

```slex
{
  namespace: "status_demo",
  g: {},
  layout: {
    "text:status": { text: "3/4 checks complete" }
  }
}
```

**Status:** 3/4 checks complete

The renderer intentionally handles only slex fences by default. It does not sniff generic JavaScript code blocks.

To show the same Slex source inside the embedded playground UI, keep the slex fence and switch the renderer mode with fence meta:

```slex render="playground" title="Editable demo"
{
  namespace: "editable_demo",
  layout: {
    "text:status": { text: "Rendered inside the playground" }
  }
}
```

You can also make playground display the default for a Markdown surface:

const renderer = createSlexKitRenderer({ renderMode: "playground" });

Fence meta resolution

Fence meta values resolve to the render mode via a flexible parser:

| Meta value | Resolved mode | |------------|--------------| | render="playground", as="playground", mode="playground" | playground | | render="editor", render="workbench" | playground | | render="component", as="component", as="preview" | component | | No meta | Fallback to renderMode option |

Playground meta also supports title, mode, height/previewMinHeight, webUrl/playgroundUrl, and pluginVersion.

Streaming behavior

During streaming (isIncomplete: true), the renderer shows a placeholder instead of attempting to parse partial Slex source. The placeholder defaults to "Rendering SlexKit..." and can be customized:

<SlexKitRenderer
  code={code}
  isIncomplete={true}
  placeholder={<Spinner />}
/>

State-only blocks (source with namespace and g but no renderable layout) are processed via ingest() and return null from the component — they update state silently without rendering DOM.

Trust Boundary

Slex source is JavaScript-compatible object literal syntax with runtime expressions. This package is intended for trusted or controlled model output. Do not treat it as a sandbox for arbitrary third-party Markdown.

For untrusted model output, opt into the secure runtime. The renderer will pass the fence source text into a sandbox frame and route sensitive capabilities through host policy enforced api.* methods:

import { createSlexKitRenderer } from "@slexkit/streamdown";
import "@slexkit/theme-shadcn/style.css";
import "@slexkit/streamdown/style.css";

const renderer = createSlexKitRenderer({
  runtime: "secure",
  securePolicy: {
    network: {
      enabled: true,
      methods: ["GET", "POST"],
      allowOrigins: ["https://api.example.com"],
      credentials: "omit",
      timeoutMs: 15000,
      maxBodyBytes: 4096,
    },
    timer: { enabled: true, maxTimers: 8, minIntervalMs: 16 },
    animation: { enabled: true },
    canvas: { enabled: true, maxCanvases: 4, maxPixels: 1048576, allowedContexts: ["2d"] },
    execution: { heartbeatIntervalMs: 1000, maxUnresponsiveMs: 5000 },
  },
  secureFrame: {
    runtimeUrl: "/slexkit.runtime.js",
    loadTimeoutMs: 8000,
  },
});

The secure renderer uses the main slexkit.runtime.js module as its iframe runner. You do not need to ship a second runner file.

Copy the runtime file into your public static directory:

npx -y slexkit copy-runtime public/slexkit.runtime.js

The file must be served by your app or CDN with these response headers:

Access-Control-Allow-Origin: *
Content-Type: text/javascript

This header is configured in your deployment layer, not inside createSlexKitRenderer(). Secure iframes intentionally run with an opaque origin, so the browser treats runtimeUrl as a cross-origin ES module import even when the URL is on your own site. Do not add allow-same-origin to the iframe sandbox to bypass this; that weakens isolation.

If the iframe cannot load or mount the runtime, SlexKit renders a role="alert" diagnostic next to the iframe and logs the same message to console.error. Tune the diagnostic delay with secureFrame.loadTimeoutMs.

For the full trust boundary and capability contract, see the root package security runtime reference.

Examples:

// next.config.js
export default {
  async headers() {
    return [
      {
        source: "/slexkit.runtime.js",
        headers: [
          { key: "Access-Control-Allow-Origin", value: "*" },
          { key: "Content-Type", value: "text/javascript" },
        ],
      },
    ];
  },
};
# Netlify / Cloudflare Pages _headers
/slexkit.runtime.js
  Access-Control-Allow-Origin: *
  Content-Type: text/javascript

If your Markdown surface already owns a page-level SlexKit runtime, pass it into the renderer so block mount/unmount events are delegated to that host:

import {
  createSlexKitMarkdownRuntimeHost,
} from "slexkit";
import { createSlexKitRenderer } from "@slexkit/streamdown";

const runtimeHost = createSlexKitMarkdownRuntimeHost({
  mode: "secure",
  policy,
  secureFrame: {
    runtimeUrl: "/slexkit.runtime.js",
  },
});

const renderer = createSlexKitRenderer({
  runtimeHost,
});

Custom Renderer Options

import { createSlexKitRenderer } from "@slexkit/streamdown";

export const renderer = createSlexKitRenderer({
  languages: ["slex"],          // Fence language tags to process (default: ["slex"])
  renderMode: "component",      // "component" | "playground"
  runtime: "trusted",           // "trusted" | "secure"
  domain: "my-app",             // Namespace prefix for blocks
  showChrome: true,             // Show CodeBlockContainer + toolbar (default: true)
  showSource: false,            // Show source code in a details element
  className: "my-block",        // Extra CSS class on wrapper
  useGlobalRuntimeHost: false,  // Use global markdown runtime host
  playgroundUrl: "/playground.html",  // Custom playground iframe URL
  placeholder: null,            // ReactNode shown during streaming
  onError(error, code) {
    console.error("Failed to render SlexKit", error, code);
  },
});

Standalone component usage

SlexKitRenderer is also exported for direct use without Streamdown:

import { SlexKitRenderer } from "@slexkit/streamdown";

function MyBlock() {
  return (
    <SlexKitRenderer
      code={`{
        namespace: "inline",
        g: {},
        layout: { "text:hello": { text: "Hello" } }
      }`}
      language="slex"
      renderMode="component"
    />
  );
}

Error handling

Parse errors display a diagnostic panel with line, column, excerpt, and detail. Runtime mount errors render a similar alert. The onError callback fires for both cases, receiving the error object and the source code string.

Documentation

Release validation

The package is considered release-ready when the repository checks pass:

bun run build
bun run test
bun run smoke:release

Those checks verify the public renderer exports, style.css subpath export, trusted rendering, secure frame rendering, runtime-host delegation, state-only fences, domain isolation, embedded playground mode, and package version sync.