Charts

Fences tagged mermaid whose diagram is pie or xychart-beta become native data_visualization blocks. Slack renders the chart itself, with no image service involved.

### Error budget by service

```mermaid
pie
  "billing-api" : 62
  "checkout" : 28
  "search" : 10
```
Block Kit JSON

xychart-beta produces bar or line charts. This one asks for line; swapping the keyword to bar gives you the other:

```mermaid
xychart-beta
  title "p95 latency (ms)"
  x-axis ["Mon", "Tue", "Wed", "Thu", "Fri"]
  y-axis "ms"
  line [212, 198, 240, 205, 190]
```
Block Kit JSON

Slack's chart block caps counts at 12 pie segments, 12 series, and 20 data points. A chart that exceeds them falls back to the same chain other mermaid diagrams use: a configured renderer, then preformatted source. Overlong text does not cause fallback. Instead, titles are truncated to 50 characters and labels to 20 in the native block, each with a degradation. Mixed bar-and-line charts render as bar (Slack charts are single-type), and a missing chart title falls back to the nearest preceding heading. slackmark also enforces a defensive cap of 2 native charts per message (a community-reported Slack limit).

Other mermaid diagrams

Only pie and xychart-beta have native Slack equivalents. Every other mermaid diagram (flowcharts, sequence diagrams, …) is handled in order:

  1. Configured image renderers. options.renderers is consulted for the fence language. Renderers turn the diagram into an image block.
  2. Preformatted source. With no renderer (the default), the mermaid source is emitted as a code block.

Step 2 is what the default converter does, and it is worth seeing before you decide whether you need a renderer at all. The diagram stays legible; it just is not drawn:

```mermaid
sequenceDiagram
  Agent->>Slack: post message
  Slack-->>Agent: ok
```
Block Kit JSON

Four hosted-URL renderers ship in the slackmark/renderers subpath, and two of them handle mermaid:

import { createConverter } from "slackmark";
import { MermaidInkRenderer } from "slackmark/renderers";

const converter = createConverter({
  renderers: [new MermaidInkRenderer()],
});

MermaidInkRenderer and KrokiRenderer compose public image URLs containing the encoded diagram source. Slack fetches the image. Core still performs no network I/O. Treat hosted renderers as an explicit data-egress opt-in, and pass baseUrl to point at a self-hosted deployment. Slack must be able to fetch that deployment anonymously, and the diagram source is still in the URL either way:

import { KrokiRenderer } from "slackmark/renderers";

new KrokiRenderer({ baseUrl: "https://kroki.internal.example" });

A renderer that produces image bytes instead of a URL additionally needs an uploader. FetchSlackUploader from slackmark/slack implements Slack's external upload flow. It needs the files:write scope, and files:read as well if you set waitForProcessing: true.

The same renderer list handles other fenced languages. KrokiRenderer accepts PlantUML, D2, Graphviz, and its other supported aliases. QuickChartRenderer accepts Chart.js JSON. Display math is offered to CodeCogsRenderer or a local bytes renderer before its preformatted fallback.

For local Mermaid and KaTeX PNGs in Node, see Rasterize content.