Releases
Enterprise-grade release notes — hero media, a Highlights grid, changes grouped into sections, and a collision-free release timeline. Every block typed for the MCP.
A Release is one complete release record — a version, date, optional status, a hero (screenshot or
video), a Highlights grid, and changes grouped into sections (New / Improved / Fixed /
Security). Wrap a stack in Releases (alias Changelog) for a full changelog led by a
collision-free release timeline. Humans read the record; the agent gets
{ kind:"release", version, date, areas, media, highlights, sections, changes } — every block typed,
so "what shipped in 2.0?" or "every security fix since June" is a query, never prose-parsing.
MCP launch
Highlights
Agents query the structured index directly.
Timeline dates keep their precision.
- First-class MCP over the structured index.
- Comparison cells stay typed.Comparison
Variants
Set variant on Releases (a single Release can override). Same typed data — only the rendering
changes.
| variant | Looks like | Best for |
|---|---|---|
| feature (default) | Hero media, Highlights grid, grouped sections, area jump-rail | Major releases & release notes |
| timeline | Date-axis strip + sleek hover cards, lighter rail | A rolling 'what's new' feed |
| compact | Dense rows: date · version · one-liner · soft tag | Bugfix logs, point releases |
Media — screenshots & video
A media block leads the entry (the first item is the hero). superlore never hosts — src is a path
or URL you provide. Images get a click-to-zoom lightbox; video supports a self-hosted file, the named
providers (YouTube / Loom / Vimeo), or provider: "iframe" to embed any URL verbatim — so any
embeddable player works. Nothing loads until the viewer hits play.
media={[
{ type: "video", provider: "iframe", src: "https://your-host.example/embed/abc", poster: "/hero.png", title: "Walkthrough", duration: "0:42" },
{ type: "video", src: "/walkthrough.mp4" }, // raw file → <video>
{ type: "image", src: "/screenshot.png", alt: "New dashboard", caption: "The redesigned dashboard." },
]}provider is inferred from src when omitted: a known host (YouTube / Loom / Vimeo) or a raw media
file (.mp4, .webm, …) is detected automatically; anything else is embedded as an iframe.
When to use it
Product changelogs, release notes, version histories. Because each change keeps its type and each
release carries typed areas / highlights, an agent filters the corpus by change kind, product
area, or marquee feature — never re-reading rendered bullet lists.
Props
Releases (alias Changelog) — the stack + timeline.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | One or more Releases |
label | string | "Changelog" | Accessible name |
variant | feature · timeline · compact | feature | Default rendering for every Release |
Release — the dual-representation unit.
| Prop | Type | Default | Description |
|---|---|---|---|
version | string | — | e.g. 2.0.0 |
date | string | — | Precision inferred (see Timeline) |
status | Status | — | Optional lifecycle status |
title | string | — | Optional headline |
summary | ReactNode | — | Optional intro line |
areas | string[] | — | Product areas touched — rail + timeline hover |
media | ReleaseMedia[] | — | Hero + inline screenshots / video |
highlights | ReleaseHighlight[] | — | Marquee features, rendered as a card grid |
sections | ReleaseSection[] | — | Changes grouped under headings |
changes | ReleaseChangeInput[] | — | Flat changes (used when sections is omitted) |
variant | feature · timeline · compact | — | Override the stack variant for this entry |
ReleaseMedia — { type: "image" | "video", src, provider?, poster?, alt?, caption?, title?, duration? }
ReleaseHighlight — { title, body?, icon?, href?, media? }
ReleaseSection — { label, icon?, changes: ReleaseChangeInput[] }
ReleaseChangeInput — { type: added · changed · fixed · removed · deprecated · security, text, refs? }
What the agent sees
Each Release serializes on its own — the date is parsed, the status is the shared enum, media is
referenced (never pixels), and every change keeps its type. When sections are used, changes is
the flattened union — so a flat query still works:
{
"kind": "release",
"id": "2-0",
"title": "MCP launch",
"status": "done",
"version": "2.0",
"date": { "iso": "2026-06-15", "precision": "day" },
"areas": ["MCP", "Timeline", "Comparison"],
"media": [
{ "type": "image", "src": "/dual-representation.png", "caption": "One source, two readings." }
],
"highlights": [
{ "title": "First-class MCP", "body": "Agents query the structured index directly." }
],
"sections": [
{
"label": "New features",
"changes": [{ "type": "added", "text": "First-class MCP over the structured index." }]
},
{ "label": "Fixes", "changes": [{ "type": "fixed", "text": "Comparison cells stay typed." }] }
],
"changes": [
{ "type": "added", "text": "First-class MCP over the structured index." },
{ "type": "fixed", "text": "Comparison cells stay typed." }
]
}Why type every block
A typed type per change turns "every security fix since June" into a corpus filter; typed
areas and highlights let an agent answer "what shipped for the dashboard?" or "summarize the
marquee features of 2.0" — from data, never a screenshot it has to interpret.