Integration
Choose the right SlexKit host integration by matching where Markdown is rendered. Every integration renders only fenced code blocks whose language is slex; ordinary js, json, and unlabeled code blocks stay with the host Markdown renderer.
For the full host API, see the Host Integration reference.
Choose An Integration
| Host | Install or enable | Render target | Default mode |
|---|---|---|---|
| assistant-ui | @slexkit/assistant-ui |
text message parts | secure |
| React / Streamdown | @slexkit/streamdown |
chat messages and React Markdown pages | trusted or secure |
| Tiptap | @slexkit/tiptap |
slex code block previews in an editor |
trusted |
| Obsidian | SlexKit from Community Plugins | local notes in reading mode | trusted readonly |
| Custom Markdown host | slexkit |
product docs, document viewers, site renderers | trusted or secure |
assistant-ui, Streamdown, and Tiptap have ready-made packages. Custom Markdown renderers can use createSlexKitMarkdownRuntimeHost directly. The Obsidian plugin can be installed from Community Plugins; use the plugin repository only when testing unreleased builds.
Package exports and install combinations are listed in Packages.
Runnable Examples
Runnable examples show the integration behavior before app wiring. Streamdown and Tiptap use the same RC low-pass Markdown source, so read-only rendering and editor preview can be compared directly:
- Streamdown Host Adapter mirrors
examples/streamdown. - Tiptap Editor Adapter mirrors
examples/tiptap. - assistant-ui Adapter mirrors
examples/assistant-ui.
Svelte Markdown Host
The SlexKit website uses a custom Markdown renderer inside a Svelte app. There is no separate Svelte Markdown adapter package. When an app owns Markdown parsing, hand each slex code block to SlexKit like this:
import { createSlexKitMarkdownRuntimeHost } from "slexkit";
import MarkdownRenderer from "./MarkdownRenderer.svelte";
const runtimeHost = createSlexKitMarkdownRuntimeHost({
mode: "trusted",
theme: "host-shadcn"
});
mount(MarkdownRenderer, {
target: container,
props: {
content: markdown,
artifactId: "docs-page",
runtimeHost,
slexkitRenderMode: "component"
}
});
Use this pattern when the product owns the Markdown parser, Svelte component tree, or document shell. Keep three rules in place: detect only slex fences, pass a stable artifactId for the document, and call cleanup when the rendered document unmounts.
Streamdown
Install the runtime, theme, plugin, and React peer dependencies:
npm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom
Import styles once in the app entry:
import "@slexkit/theme-shadcn/style.css";
import "@slexkit/streamdown/style.css";
Register the renderer with Streamdown:
import { Streamdown } from "streamdown";
import { slexkitRenderer } from "@slexkit/streamdown";
export function Message({ markdown }: { markdown: string }) {
return (
<Streamdown plugins={{ renderers: [slexkitRenderer] }}>
{markdown}
</Streamdown>
);
}
This renderer only replaces slex code blocks. Other code blocks stay with Streamdown.
assistant-ui
When an assistant-ui app already renders text through @assistant-ui/react-streamdown, use the SlexKit wrapper for message text parts:
npm install slexkit @slexkit/theme-shadcn @slexkit/streamdown @slexkit/assistant-ui @assistant-ui/react @assistant-ui/react-streamdown streamdown react react-dom
Import styles once in the app entry:
import "@slexkit/theme-shadcn/style.css";
import "@slexkit/assistant-ui/style.css";
Use the wrapper where assistant-ui renders text message parts:
import { MessagePrimitive } from "@assistant-ui/react";
import { SlexKitAssistantStreamdownText } from "@slexkit/assistant-ui";
export function AssistantMessage() {
return (
<MessagePrimitive.Root>
<MessagePrimitive.Parts>
{({ part }) =>
part.type === "text" ? (
<SlexKitAssistantStreamdownText
artifactId="message-1"
runtime="secure"
secureFrame={{ runtimeUrl: "/slexkit.runtime.js" }}
/>
) : null
}
</MessagePrimitive.Parts>
</MessagePrimitive.Root>
);
}
The wrapper only replaces the slex language block. Threads, composer state, message state, tool calls, approvals, and form submissions stay with the existing assistant-ui or ToolHost layer.
Tiptap
Install the SlexKit adapter, theme, and Tiptap dependencies:
npm install slexkit @slexkit/theme-shadcn @slexkit/tiptap @tiptap/core @tiptap/pm @tiptap/starter-kit @tiptap/extension-code-block @tiptap/markdown
Import styles once in the app entry:
import "@slexkit/theme-shadcn/style.css";
import "@slexkit/tiptap/style.css";
Disable StarterKit's default code block, then register the SlexKit extension:
import { Editor } from "@tiptap/core";
import StarterKit from "@tiptap/starter-kit";
import { Markdown } from "@tiptap/markdown";
import { createSlexKitTiptapExtension } from "@slexkit/tiptap";
const editor = new Editor({
element: document.querySelector("#editor"),
extensions: [
StarterKit.configure({ codeBlock: false }),
Markdown,
createSlexKitTiptapExtension({ artifactId: "doc-1" })
],
content: markdown,
contentType: "markdown"
});
The extension only takes over code blocks whose language is exactly slex. Other code blocks remain normal editable Tiptap code blocks.
All slex blocks in one editor share state: a state-only block can seed a later layout block. The Tiptap integration uses trusted mode by default; render unreviewed user Markdown or third-party content in a secure web host instead.
Streamdown Options
Use createSlexKitRenderer to set the message/domain, hide source, enable playground behavior, or switch to secure mode:
import { createSlexKitRenderer } from "@slexkit/streamdown";
const renderer = createSlexKitRenderer({
domain: "chat-thread-42",
showChrome: false,
showSource: false,
runtime: "trusted"
});
Inside the same domain, an earlier state-only block can provide data for a later layout block:
<div class="slex-prerender-placeholder" data-slex-source="bmFtZXNwYWNlOiAiY2FsYyIsCiAgZzogeyB2YWx1ZTogMjEgfQp9"><pre><code class="language-slex">namespace: "calc",
g: { value: 21 }
}</code></pre></div>
<div class="slex-prerender-placeholder" data-slex-source="bmFtZXNwYWNlOiAiY2FsYyIsCiAgbGF5b3V0OiB7CiAgICAidGV4dDphbnN3ZXIiOiB7ICIkdGV4dCI6ICInYW5zd2VyOiAnICsgKGcudmFsdWUgKiAyKSIgfQogIH0KfQ=="><pre><code class="language-slex">namespace: "calc",
layout: {
"text:answer": { "$text": "'answer: ' + (g.value * 2)" }
}
}</code></pre></div>
For unreviewed user input, third-party Markdown, or direct agent output, switch to secure mode:
const renderer = createSlexKitRenderer({
runtime: "secure",
secureFrame: {
runtimeUrl: "/slexkit.runtime.js"
},
securePolicy: {
execution: {
maxUnresponsiveMs: 30000
}
}
});
Use Secure Runtime Setup and the Security Runtime Contract when deploying the sandbox iframe, runtime file, and policy fields.
Obsidian
For Obsidian plugin installation only, the developer integration material above is unnecessary. Search for SlexKit in Obsidian Community plugins, then install and enable it.
The Obsidian plugin renders slex code blocks from your local vault in reading mode. It does not write rendered output back to notes.
Install the plugin from Obsidian Community Plugins:
- Open Settings -> Community plugins.
- Disable Restricted mode if needed.
- Search for SlexKit.
- Install and enable the plugin.
The community plugin is marked desktop-only and compatible with Obsidian 1.5.0+.
To test an unreleased build, use BRAT:
BRAT repository: https://github.com/slexkit/obsidian-slexkit
Manual installs copy the GitHub release assets into the vault:
.obsidian/plugins/slexkit/
main.js
manifest.json
styles.css
Enable SlexKit in Obsidian's community plugin settings.
Obsidian Example
Write an explicit slex fence in a note:
<div class="slex-prerender-placeholder" data-slex-source="bmFtZXNwYWNlOiAidmF1bHRfc3RhdHVzIiwKICBsYXlvdXQ6IHsKICAgICJjYXJkOnN0YXR1cyI6IHsKICAgICAgdGl0bGU6ICJWYXVsdCBzdGF0dXMiLAogICAgICAiYmFkZ2U6cmVhZHkiOiB7IGxhYmVsOiAiUmVhZHkiLCB0b25lOiAic3VjY2VzcyIgfSwKICAgICAgInRleHQ6bm90ZSI6IHsgdGV4dDogIlJlbmRlcmVkIGJ5IFNsZXhLaXQgaW4gcmVhZGluZyBtb2RlLiIgfQogICAgfQogIH0KfQ=="><pre><code class="language-slex">namespace: "vault_status",
layout: {
"card:status": {
title: "Vault status",
"badge:ready": { label: "Ready", tone: "success" },
"text:note": { text: "Rendered by SlexKit in reading mode." }
}
}
}</code></pre></div>
Vault status: Ready.
slex code blocks in the same note share state, so an earlier state block can affect a later rendered block.
Obsidian Security Notes
The official plugin treats local vault content as trusted. It is not a sandbox for third-party Markdown or direct agent output.
For untrusted content, use secure mode in a web host with a sandbox frame and host policy.
Before You Ship
- Process only fences whose language is exactly
slex - Keep Markdown fallback for environments without SlexKit
- Use a stable artifact/domain for each document, message, or note
- Call cleanup when a container unmounts; dispose the artifact when the document is destroyed
- Use secure mode for untrusted content instead of trusted mode