CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

chat

Chat SDK renderer for json-render that turns JSON specs into native chat cards (Block Kit on Slack, Adaptive Cards on Teams, and the card format of other Chat SDK adapters). Use when working with @json-render/chat, building bots that post rich messages with tables, charts, fields, or buttons, streaming a generated card into a chat thread, or when the user mentions Chat SDK, Slack Block Kit, or Teams Adaptive Cards together with json-render.

Quality

90%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

SKILL.md
Quality
Evals
Security

@json-render/chat

Renders json-render specs as Chat SDK CardElement objects. Each Chat SDK adapter converts the card to its platform format.

Quick start

import { defineCatalog } from "@json-render/core";
import {
  schema,
  standardComponentDefinitions,
  streamCard,
} from "@json-render/chat";
import { streamText } from "ai";

const catalog = defineCatalog(schema, {
  components: standardComponentDefinitions,
});

chat.onNewMention(async (thread, message) => {
  const result = streamText({
    model: "anthropic/claude-haiku-4.5",
    system: catalog.prompt(),
    prompt: message.text,
  });
  await streamCard(thread, result.textStream);
});

streamCard(target, textStream, options) posts the card once the root exists, edits it every updateIntervalMs (default 500) as elements arrive, and finishes with a validated card. toCard(spec, options) converts a complete spec. toPartialCard(spec) returns a best-effort card for a streaming spec, or null before the root exists.

Spec structure

Same flat tree as other renderers: root plus elements, with optional state. The root must be a Card. An inner Card renders as a titled section, because chat cards cannot nest.

Standard components: Card, Section, Text (markdown), Fields with Field, Table, Chart (pie with segments, or bar, line, area with categories and series[].values), Divider, Image, and Actions with Button and LinkButton.

{
  "root": "card",
  "elements": {
    "card": {
      "type": "Card",
      "props": { "title": "Weekly deploys" },
      "children": ["kpis", "chart"]
    },
    "kpis": { "type": "Fields", "props": {}, "children": ["total"] },
    "total": {
      "type": "Field",
      "props": { "label": "Deploys", "value": "985" },
      "children": []
    },
    "chart": {
      "type": "Chart",
      "props": {
        "title": "Deploys per day",
        "chart": {
          "type": "bar",
          "categories": ["Mon", "Tue"],
          "series": [{ "name": "Deploys", "values": [180, 210] }]
        }
      },
      "children": []
    }
  }
}

State, repeat, and visibility

$state, $item, $index, and $template resolve against spec.state. visible conditions drop elements. repeat renders an element's children once per item. A repeated Table expands its rows as a template, and object rows map to headers by key name. $bindState and $bindItem have no effect because posted messages have no inputs. Expansion stops at maxElements (default 1000 elements and table rows); toCard throws past it.

Validation and limits

toCard throws CardSpecError with an issues array (one entry per problem). Send the issues back to the model to repair the spec. Pass limits to reject specs that a platform would degrade, for example { tables: 1, charts: 2 } for Slack. Available limits: tables, charts, fields, tableRows, tableColumns, chartTitle, chartLabel, chartSeries, chartPoints.

Runtime

The renderer imports chat for types only, so it runs in the browser and on the server. Convert a card for a specific platform with the adapter, for example cardToSlackBlocks from @chat-adapter/slack/blocks or cardToAdaptiveCard from @chat-adapter/teams/cards.

Repository

vercel-labs/json-render

Path

skills/chat/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.