AI Display components
Five vanilla-ES-module display components for the tool-call runtime. Each file lives at site/frontend/ai/components/display/<name>.js and exports a single def object the runtime collects automatically.
Component contract
export const def = {
name: "<snake_case id>", // unique id used by the runtime
category: "Display",
title: "<Human Title>",
match(payload) { /* return true iff payload fits this component */ },
render(payload, ctx) { /* return an HTMLElement */ },
example: { /* realistic preset payload */ },
};
All components are XSS-safe: text is set via textContent; no untrusted string is ever passed to innerHTML. Zero dependencies — pure DOM, no imports.
citation
File: site/frontend/ai/components/display/citation.js
A compact cited-source card with favicon, domain, linked title, and a text snippet.
Payload shape
{
title: string; // page / article title
url: string; // canonical URL — used for the link and domain display
snippet: string; // 1–3 sentence excerpt
favicon?: string; // optional favicon URL; falls back to first-letter badge
}
Example
{
"title": "From-scratch SQL engine — AkurAI-Framework",
"url": "https://github.com/olibuijr/AkurAI-Framework",
"snippet": "A pure-Rust zero-runtime-dep full-stack framework with a built-in SQL engine, native ESM frontend, and semantic search.",
"favicon": "https://github.com/favicon.ico"
}
link_preview
File: site/frontend/ai/components/display/link_preview.js
OpenGraph-style preview card: optional hero image, domain badge, bold title, and description. The entire card is a navigable <a>.
Payload shape
{
url: string; // destination
title: string; // OG title
description: string; // OG description
image?: string; // OG image URL — omit to render text-only card
}
Example
{
"url": "https://akurai.is",
"title": "AkurAI — AI for Icelandic businesses",
"description": "AI solutions, automation, and training built specifically for Icelandic companies. Up to 90% training reimbursement via vocational funds.",
"image": "https://akurai.is/og-image.png"
}
stats_display
File: site/frontend/ai/components/display/stats_display.js
A responsive stat grid. Reuses .stat, .stat-value, and .stat-label from the design system. Optional delta strings are coloured green (up) or red (down) based on their leading sign.
Payload shape
{
stats: Array<{
label: string;
value: string | number;
delta?: string | null; // e.g. "+18%" or "-0.3 s"; null = omit
}>;
}
Example
{
"stats": [
{ "label": "Monthly revenue", "value": "ISK 1.2M", "delta": "+18%" },
{ "label": "Active customers", "value": 34, "delta": "+3" },
{ "label": "Avg response time", "value": "1.4 s", "delta": "-0.3 s" },
{ "label": "Uptime", "value": "99.97%", "delta": null }
]
}
terminal
File: site/frontend/ai/components/display/terminal.js
A styled terminal block with a macOS-style title bar (traffic-light dots), a prompt line, output lines, and an optional exit-code indicator (red when non-zero).
Payload shape
{
command: string; // command that was run (shown after the prompt)
lines: string[]; // output lines (stdout / stderr)
exit_code?: number; // optional; omit to hide; non-zero renders in red
}
Example
{
"command": "bun run build",
"lines": [
" Building routes...",
" Compiled 42 pages in 180ms",
" Static assets copied: 7 files",
" Done."
],
"exit_code": 0
}
weather_widget
File: site/frontend/ai/components/display/weather_widget.js
A weather card with current temperature, condition (mapped to emoji — no image assets), hi/lo range, and an optional scrollable hourly strip.
Payload shape
{
location: string; // display name, e.g. "Akureyri, Iceland"
temp: number; // current temperature
unit?: "C" | "F"; // default "C"
condition: string; // free-text, e.g. "Partly cloudy"
hi: number; // daily high
lo: number; // daily low
hourly?: Array<{
time: string; // display label, e.g. "14:00" or "Now"
temp: number;
condition: string;
}>;
}
Example
{
"location": "Akureyri, Iceland",
"temp": 9,
"unit": "C",
"condition": "Partly cloudy",
"hi": 12,
"lo": 5,
"hourly": [
{ "time": "Now", "temp": 9, "condition": "Partly cloudy" },
{ "time": "13:00", "temp": 10, "condition": "Partly cloudy" },
{ "time": "14:00", "temp": 11, "condition": "Sunny" },
{ "time": "15:00", "temp": 12, "condition": "Sunny" },
{ "time": "16:00", "temp": 11, "condition": "Cloudy" },
{ "time": "17:00", "temp": 10, "condition": "Rain" },
{ "time": "18:00", "temp": 8, "condition": "Rain" },
{ "time": "19:00", "temp": 7, "condition": "Cloudy" }
]
}