Zum Inhalt springen
Blume
Esc
↑↓navigieren↵öffnen⌘Jvorschau
Auf dieser Seite

Komponenten

Karten, Schritte, Tabs, Akkordeons, Badges, Codegruppen, Rahmen, Bäume, Typtabellen, Live-Vorschauen und Diffs – die integrierten Komponenten, nutzbar auf jeder MDX-Seite.

Blume liefert einen barrierefreien, themenfähigen Komponentensatz, der auf jeder .mdx-Seite ohne Imports verfügbar ist. Jede Komponente wird unten mit einer Live-Vorschau und ihrem Quellcode gezeigt. Die Komponenten sind Vanilla und React-frei; React wird nur aktiviert, wenn dein Projekt es verwendet – eine beliebige .tsx- oder .jsx-Datei im Projekt, eine React-Island, ein <Component>-Beispiel oder ein Komponenten-Override – oder wenn der Assistent eingeschaltet ist.

Eine Komponente ignoriert Props, die sie nicht entgegennimmt. Die meisten zeigen ihre Kinder an, daher können Schreibweisen aus anderen Doku-Tools leer rendern: Das <Badge type="tip" text="beta" /> aus VitePress ist ein Badge ohne Kinder und zeigt daher nichts an. Erhält eine Komponente ohne Kinder Props, die sie nicht entgegennimmt, warnt Blume mit BLUME_UNKNOWN_PROP und nennt dabei die Props, die sie tatsächlich entgegennimmt. Schreibe den Inhalt stattdessen zwischen die Tags: <Badge>beta</Badge>.

Card and CardGroup

Karten verlinken mit Icon, Titel und kurzem Text auf ein Ziel. Gruppiere sie mit CardGroup zu einem responsiven Raster. Setze sie auf Landingpages, in Abschnittsübersichten und bei „nächsten Schritten“ ein – überall dort, wo du die Leserschaft weiterführst.

<CardGroup cols={2}>
  <Card title="Quickstart" href="/docs/quickstart" icon="rocket">
    Install Blume and ship your first page.
  </Card>
  <Card title="Components" href="/docs/content/components" icon="folder">
    Browse the component library.
  </Card>
</CardGroup>

Card nimmt title, ein optionales href (weglassen für eine nicht klickbare Karte) und ein icon aus Blumes integriertem Icon-Set entgegen. CardGroup nimmt cols entgegen (Standard 2).

Eine Karte nimmt außerdem img entgegen, ein Bild, das sich oben über die Karte erstreckt (oder mit horizontal ab dem Breakpoint sm neben dem Text steht) und wie der Pfad eines Markdown-Bildes angegeben wird: eine Datei neben der Seite (./cover.png), ein Pfad unter public/ oder eine URL; cta, eine Call-to-Action-Zeile in der Akzentfarbe unter dem Text; arrow, einen Pfeil nach dem Titel und dem CTA (standardmäßig nur bei externen Links angezeigt); type, das die Karte einfärbt und wie bei einem Callout ein passendes Icon wählt (note, info, tip, check, warning oder danger); und color, eine beliebige CSS-Farbe für das Icon.

Steps

Eine nummerierte vertikale Abfolge für geordnete Anleitungen – Installationen, Einrichtungsabläufe und Tutorials, bei denen die Reihenfolge zählt. Jeder Step nimmt einen title und ein optionales icon entgegen, das in seiner Markierung anstelle der Nummer angezeigt wird. titleSize an Steps legt die Größe der Schritttitel fest – wie Fließtext (p, der Standard) oder wie eine h4-, h3- oder h2-Überschrift.

Install Blume

Füge das Paket zu deinem Projekt hinzu.

Write a page

Lege eine .mdx-Datei in deinen Inhaltsordner.

Ship it

Führe blume build aus und deploye dist/.
<Steps>
  <Step title="Install Blume">Add the package to your project.</Step>
  <Step title="Write a page">
    Drop an `.mdx` file into your content folder.
  </Step>
  <Step title="Ship it">Run `blume build` and deploy `dist/`.</Step>
</Steps>

Tabs

Wechsle an Ort und Stelle zwischen gleichwertigen Inhalten – Sprachvarianten, betriebssystemspezifischen Befehlen oder alternativen Vorgehensweisen – ohne alles untereinander auf der Seite zu stapeln. Jeder Tab nimmt einen title entgegen.

Nutze Homebrew, um die Toolchain zu installieren.
Nutze winget, um die Toolchain zu installieren.
<Tabs>
  <Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
  <Tab title="Windows">Use winget to install the toolchain.</Tab>
</Tabs>

Füge inline hinzu, um randlos zu rendern – eine Tab-Leiste auf einer Linie über die volle Breite, mit dem Inhalt, der darunter als Fließtext folgt – statt der umrandeten Box. Füge param hinzu, um den aktiven Tab statt mit dem Hash mit einem URL-Query-Parameter zu synchronisieren; das macht die Auswahl teilbar: Ein Link, der auf ?install=windows endet, öffnet den Windows-Tab. Jede Gruppe synchronisiert sich mit ihrem eigenen param, sodass du mehrere unabhängige, direkt verlinkbare Gruppen auf einer Seite verwenden kannst.

Gruppen mit gleichnamigen Tabs wechseln gemeinsam – wähle in einer „macOS“, und jede Gruppe mit einem macOS-Tab zieht nach. Füge syncKey hinzu, um diese Synchronisierung einzugrenzen: Nur Gruppen mit demselben Schlüssel wechseln gemeinsam, sodass unabhängige Gruppen, die zufällig einen Tab-Titel teilen, eigenständig bleiben – oder sync={false}, um eine Gruppe ganz davon auszunehmen.

Der aktive Tab wird in den URL-Hash geschrieben, sodass ein Link direkt mit ihm öffnet; übergib hash={false}, um die URL unverändert zu lassen. defaultTabIndex wählt den Tab, der zuerst geöffnet wird (nullbasiert, Standard 0), wenn weder ein Link noch eine synchronisierte Auswahl einen bestimmt. dropdown ersetzt die Tab-Leiste durch ein Auswahlmenü (nur im umrandeten Layout), borderBottom={false} entfernt die Linie unter der Leiste, und jeder Tab nimmt ein icon entgegen, das vor seinem Titel angezeigt wird.

Nutze Homebrew, um die Toolchain zu installieren.
Nutze winget, um die Toolchain zu installieren.
<Tabs inline param="install">
  <Tab title="macOS">Use Homebrew to install the toolchain.</Tab>
  <Tab title="Windows">Use winget to install the toolchain.</Tab>
</Tabs>

View

Schreibe mit <View>-Blöcken eine einzige Seite für mehrere Zielgruppen, etwa für eine Leserschaft, die unterschiedliche Programmiersprachen oder Frameworks nutzt. Jeder unterschiedliche title wird zu einer Option in einer Auswahl über dem Seiteninhalt, und nur die Blöcke der gewählten Ansicht werden angezeigt. Das Inhaltsverzeichnis zieht mit: Überschriften in ausgeblendeten Ansichten fallen daraus heraus. Fließtext außerhalb aller <View>-Blöcke erscheint in jeder Ansicht, und Blöcke mit demselben Titel werden gemeinsam ein- und ausgeblendet, sodass sich auf einer Seite gemeinsame und ansichtsspezifische Abschnitte abwechseln können. icon wird in der Auswahl neben dem Namen der Ansicht angezeigt.

Everyone reads this paragraph.

<View title="JavaScript" icon="braces">

## Install the client

```bash
npm install @acme/commerce
```

</View>

<View title="Python" icon="terminal">

## Install the client

```bash
pip install acme-commerce
```

</View>

Die erste Ansicht wird angezeigt, bis die Leserschaft eine andere wählt. Blume merkt sich diese Wahl über alle Seiten hinweg, die mit Ansichten geschrieben sind, und schreibt sie als ?view=Python in die URL, sodass ein Link direkt mit derselben Ansicht öffnet. Ein Link auf eine Überschrift innerhalb einer Ansicht öffnet diese Ansicht. Verwende <View>, wenn sich der Großteil der Seite mit der Auswahl ändert, und Tabs, wenn das nur für einen Teil der Seite gilt. Das an Agenten gerichtete Markdown enthält jede Ansicht, jeweils unter ihrem Namen.

Callout

<Callout> ist die Komponente hinter den Callout-Direktiven: :::warning[Heads up] rendert <Callout type="warning" title="Heads up">. Schreibe die Komponente selbst, wenn ein Callout ein eigenes Icon oder eine eigene Farbe braucht, was eine Direktive nicht festlegen kann.

<Callout type="tip" title="Ship it" icon="rocket">
  Run `blume build` before you deploy.
</Callout>

type legt die Einfärbung und das Standard-Icon fest: note, info (der Standard), tip, success (oder check), warning oder danger. Die Aliasse caution, error, important und warn funktionieren nur in der :::-Form. title fügt eine fett gedruckte erste Zeile hinzu. icon ersetzt das Icon des Typs und nimmt dieselben Eingaben entgegen wie <Icon>: einen Lucide-Namen, einen Bildpfad oder eine Bild-URL oder ein Inline-SVG. color, eine beliebige CSS-Farbe, ersetzt die Einfärbung des Typs: Rahmen, Icon und Fließtext erscheinen in dieser Farbe auf dem Seitenhintergrund.

Badge

Ein kleines Inline-Label für Status oder Metadaten – Versionskennzeichen, „new“- oder „beta“-Markierungen, Stabilitätsstufen. Die variant stimmt die Farbe auf die Bedeutung ab.

Default

Neutrale Metadaten ohne besondere Betonung.

Stabil
<Badge>Stable</Badge>

Accent

Zieht mit deiner Theme-Akzentfarbe den Blick auf sich – gut für „neu“- oder Hervorhebungs-Markierungen.

Neu
<Badge variant="accent">New</Badge>

Success

Ein positiver oder bestandener Zustand.

Bestanden
<Badge variant="success">Passing</Badge>

Warning

Etwas, das mit Vorsicht zu verwenden ist, etwa ein experimentelles Feature.

Beta
<Badge variant="warning">Beta</Badge>

Danger

Ein negativer oder brechender Zustand, etwa eine Veraltung.

Veraltet
<Badge variant="danger">Deprecated</Badge>

Farbe, Form und Größe

Über variant hinaus nimmt ein Badge color entgegen – einen benannten Farbton (blue, green, orange, purple, red, teal, violet, yellow), einen neutralen Ton (gray, surface, white, surface-destructive oder white-destructive) oder einen Hex-Wert – sowie shape (rounded, der Standard, oder pill), size (xs, sm, standardmäßig md oder lg), stroke für eine Umrandung statt einer Füllung, icon für ein Icon vor der Beschriftung, tooltip für einen Hover-Text und disabled, um es abzublenden.

Eine umrandete lila Pille mit Icon: Vorschau

<Badge color="purple" icon="sparkles" shape="pill" stroke>Preview</Badge>

Icon

Rendere ein Icon anhand seines Namens – dieselbe icon-Prop treibt Karten, Schritte, Tabs und Sidebar-Einträge an. Die Namen stammen von Lucide, in Kleinschreibung und Kebab-Case (rocket, gauge, book-open).

<Icon icon="rocket" size={20} />

Blume unterstützt ausschließlich Lucide – ein reiner Name wird gegen Lucide aufgelöst, und du kannst einem Namen zur Symmetrie mit anderen Icon-Eingaben lucide: voranstellen (lucide:rocket). size legt die Pixelgröße fest (Standard 16) und color färbt es ein (jede CSS-Farbe; Standard ist currentColor). Übergib anstelle eines Namens einen rohen <svg>-String, eine Bild-URL oder einen lokalen Bildpfad, um eigene Grafiken zu rendern, und ergänze ein label, um es assistiven Technologien zugänglich zu machen – ohne ein solches gilt das Icon als dekorativ.

Icons werden zur Build-Zeit aufgelöst und als SVG ohne JavaScript eingebettet – zur Laufzeit wird nichts nachgeladen.

File tree

Veranschauliche ein Projekt- oder Ordnerlayout. Umschließe eine gewöhnliche Markdown-Liste, und Blume stylt sie als Baum – praktisch, um Strukturen in Einrichtungs- und Konfigurationsanleitungen zu erklären.

  • docs/
    • index.mdx
    • guides/
      • configuration.mdx
  • blume.config.ts
<FileTree>

- docs/
  - index.mdx
  - guides/
    - configuration.mdx
- blume.config.ts

</FileTree>

Accordion

Staple zusammengehörige Aufklappbereiche in einem einzigen umrandeten Container mit Trennlinien dazwischen – FAQs, optionale Schritte oder lange Beispiele. Jedes Kind ist ein AccordionItem (title, optional icon, description, defaultOpen). Der title rendert Inline-Markdown, sodass Code-Spans, Hervorhebungen und Links darin so erscheinen wie in einem Satz; rohes HTML darin wird als Text angezeigt. Für einen einzelnen eigenständigen Aufklappbereich verwende Expandable.

Does it support MDX?

Ja – jede Seite kann .md oder .mdx sein.

Is the theme customizable?

Ja, über Tailwind-v4-Tokens und dein eigenes theme.css.

<Accordion>
  <AccordionItem title="Does it support MDX?">
    Yes — every page can be `.md` or `.mdx`.
  </AccordionItem>
  <AccordionItem title="Is the theme customizable?">
    Yes, via Tailwind v4 tokens and your own `theme.css`.
  </AccordionItem>
</Accordion>

Expandable

Ein leichtgewichtiger Inline-Aufklappbereich für verschachtelte Details – etwa die Unterattribute eines Feldes oder eine optionale Randbemerkung. title beschriftet den Umschalter (Standard „Show more“) und rendert wie bei einem Accordion-Eintrag Inline-Markdown; setze defaultOpen, damit er aufgeklappt startet.

Show advanced options

Diese Einstellungen sind optional und müssen selten geändert werden.

<Expandable title="Show advanced options">
  These settings are optional and rarely need changing.
</Expandable>

Columns

Ordne Karten oder Blöcke in einem responsiven Raster aus gleich breiten Spalten an, das auf Mobilgeräten umbricht. Columns nimmt cols entgegen; umschließe jede Zelle mit einem Column.

Fast

Gebaut auf Astro und Vite.

Themeable

Tailwind-v4-Design-Tokens.

<Columns cols={2}>
  <Column>
    <Card title="Fast" icon="rocket">
      Built on Astro and Vite.
    </Card>
  </Column>
  <Column>
    <Card title="Themeable" icon="sun">
      Tailwind v4 design tokens.
    </Card>
  </Column>
</Columns>

CodeGroup

Fasse mehrere Codeblöcke zu einem einzigen Tab-Umschalter zusammen – ein Tab pro Sprache oder Datei. Die Tab-Beschriftung ist der Titel des jeweiligen Blocks (der Text nach der Sprache) oder, bei einem Block ohne Titel, der Name seiner Sprache (TypeScript, Python), und der Kopier-Button der Gruppe sitzt in der Tab-Leiste und kopiert den gerade angezeigten Block. Füge dropdown hinzu, um statt über eine Tab-Leiste über ein Menü zu wechseln.

export const greet = (name: string) => `Hello, ${name}`;
def greet(name: str) -> str:
    return f"Hello, {name}"
fn greet(name: &str) -> String {
    format!("Hello, {name}")
}
<CodeGroup>

```ts TypeScript
export const greet = (name: string) => `Hello, ${name}`;
```

```python Python
def greet(name: str) -> str:
    return f"Hello, {name}"
```

```rust Rust
fn greet(name: &str) -> String {
    format!("Hello, {name}")
}
```

</CodeGroup>

Frame

Umschließe ein Bild oder eine beliebige Grafik mit einem zentrierten, umrandeten Rahmen samt optionaler caption (wird als Markdown gerendert) und hint.

Frames center and caption visuals.

A framed illustration.
<Frame
  caption="A **framed** illustration."
  hint="Frames center and caption visuals."
>
  <img src="/screenshot.png" alt="Product screenshot" />
</Frame>

YouTube

Bette ein YouTube-Video in einen responsiven, datenschutzfreundlichen (youtube-nocookie.com) 16:9-Rahmen ein, der kein Client-JavaScript ausliefert. Übergib eine Video-id oder eine vollständige url sowie optional einen title (für Barrierefreiheit) und eine start-Zeit in Sekunden. Eine Playlist-url (youtube.com/playlist?list=… oder youtube.com/embed/videoseries?list=…) bettet die gesamte Playlist ein.

<YouTube id="aqz-KE-bpKQ" title="Big Buck Bunny" />
<YouTube url="https://youtu.be/aqz-KE-bpKQ" start={30} />

Color

Zeige Farbfelder mit kopierbaren Hex-Werten – nützlich, um eine Palette oder Markenfarben zu dokumentieren. Verwende variant="compact" für eine Liste von Farbfeldern oder variant="table" mit Color.Row, um sie zu gruppieren. Jedes Color.Item nimmt einen name und einen value entgegen (einen Hex-String oder { light, dark } für themenabhängige Farben); ein themenabhängiges Farbfeld kopiert den Wert für das Theme, das die Leserschaft gerade sieht.

<Color variant="compact">
  <Color.Item name="blue-500" value="#3B82F6" />
  <Color.Item name="green-500" value="#16A34A" />
  <Color.Item name="background" value={{ light: "#FFFFFF", dark: "#0A0A0A" }} />
</Color>

Tree

Rendere eine hierarchische Datei-/Ordnerstruktur mit ausklappbaren Ordnern. (Für eine schnelle, listenbasierte Variante siehe File tree; Tree bietet Kontrolle pro Ordner.) Verwende Tree.Folder (name, optional defaultOpen, openable) und Tree.File (name).

src
index.ts
components
Button.tsx
blume.config.ts
<Tree>
  <Tree.Folder name="src" defaultOpen>
    <Tree.File name="index.ts" />
    <Tree.Folder name="components">
      <Tree.File name="Button.tsx" />
    </Tree.Folder>
  </Tree.Folder>
  <Tree.File name="blume.config.ts" />
</Tree>

Panel

Ein betitelter Container für ergänzende, beiseitegestellte Inhalte. title ist optional.

<Panel title="Good to know">
  Panels hold supporting detail without interrupting the main flow.
</Panel>

Tooltip

Zeige beim Überfahren eines Inline-Begriffs eine Definition oder einen Hinweis. tip ist der Hover-Text; ergänze optional eine headline sowie ein cta + href für einen weiterführenden Link.

Fahre über den Begriff APIAPIA set of protocols software uses to communicate.Read the guide, um mehr zu erfahren.

Hover the <Tooltip tip="A set of protocols software uses to communicate." headline="API" cta="Read the guide" href="/docs/quickstart">API</Tooltip> term.

Tile

Eine klickbare Vorschau, die mit einer Grafik – einem Icon oder Bild – über Titel und Beschreibung eröffnet. Gut für Galerien und Showcases. Nimmt title, description und href entgegen; das Kind ist die Grafik.

Quickstart

Ship your first page in minutes.

<Tile
  title="Quickstart"
  description="Ship your first page in minutes."
  href="/docs/quickstart"
>
  <Icon icon="rocket" size={28} />
</Tile>

Prompt

Eine einzelne Zeile mit einer Beschriftung und einem Kopier-Button. Die description (Markdown) ist die sichtbare Beschriftung; der Body ist der Prompt selbst – ausgeblendet und beim Drücken des Buttons Copy prompt als Markdown in die Zwischenablage kopiert, mit intakten Links, Listen und Code. Die Satzzeichen werden so kopiert, wie du sie getippt hast: Gerade Anführungszeichen, -- und ... bleiben, wie sie geschrieben sind, auch wenn der Fließtext an anderen Stellen der Seite sie als typografische Anführungszeichen, Gedankenstriche und Auslassungspunkte anzeigt. actions steuert die Buttons (z. B. ["copy", "cursor"]).

Ask the model to document an endpoint.

<Prompt
  description="Ask the model to **document** an endpoint."
  actions={["copy"]}
>
  Write reference docs for the POST /v1/pets endpoint.
</Prompt>

Visibility

Zeige oder verbirg Inhalte je nach Zielgruppe. for="web" rendert nur auf der Website; for="agents" zielt auf das an Agenten gerichtete Markdown, das KI-Agenten lesen (llms-full.txt und die .md-Spiegelung jeder Seite).

Dieser Hinweis erscheint auf der Website, wird aber im an Agenten gerichteten Markdown weggelassen.

<Visibility for="web">Shown on the site only.</Visibility>
<Visibility for="agents">Shown only in the generated Markdown.</Visibility>

Type tables

Tabellen zur Dokumentation der Eigenschaften eines Objekts – seiner Props, Typen und Standardwerte. Schreibe die Zeilen mit TypeTable von Hand oder erzeuge sie direkt aus einem TypeScript-Interface oder Typ-Alias mit AutoTypeTable.

Type table

Ein Prop / Type-Raster, in dem sich jede Zeile ausklappen lässt, um ihre Beschreibung und Details zu zeigen. Übergib eine type-Map mit den Eigenschaftsnamen als Schlüssel; jeder Eintrag nimmt einen type entgegen, dazu optional eine description, ein default, ein required-Flag, typeDescription und typeDescriptionLink. Optionale Props (required nicht gesetzt) zeigen ein ? nach dem Namen.

EigenschaftTyp
labelstring

The button's visible label.

Typstring
variant?"primary" | "ghost"

Visual style.

Typ"primary" | "ghost"
Standard"primary"
disabled?boolean
Typboolean
<TypeTable
  type={{
    label: {
      type: "string",
      required: true,
      description: "The button's visible label.",
    },
    variant: {
      type: '"primary" | "ghost"',
      default: '"primary"',
      description: "Visual style.",
    },
    disabled: { type: "boolean" },
  }}
/>

Auto type table

Erzeuge eine Typtabelle aus einem TypeScript-Typ, damit die Dokumentation mit dem Quellcode synchron bleibt. Richte AutoTypeTable mit path (aufgelöst relativ zu deinem Projektstammverzeichnis, dem Ordner, in dem du blume ausführst) und einem Typ-name auf eine Datei aus. Beschreibungen stammen aus JSDoc-Kommentaren, Standardwerte aus @default-Tags, und optionale Eigenschaften (?) werden entsprechend markiert.

<AutoTypeTable path="./src/button.ts" name="ButtonProps" />

Du kannst den Typ statt eines path auch inline über type übergeben – praktisch für kleine Beispiele:

EigenschaftTyp
labelstring

The button's visible label.

Typstring
variant?"primary" | "ghost"

Visual style.

Typ"primary" | "ghost"
Standard"primary"
disabled?boolean

Disable interaction.

Typboolean
<AutoTypeTable
  name="ButtonProps"
  type={`
export interface ButtonProps {
  /** The button's visible label. */
  label: string;
  /**
   * Visual style.
   * @default "primary"
   */
  variant?: "primary" | "ghost";
  /** Disable interaction. */
  disabled?: boolean;
}
`}
/>

API fields

Zeilen, mit denen du einen Endpunkt Feld für Feld von Hand dokumentierst, gestaltet wie die generierte OpenAPI-Referenz. ParamField ist ein Anfrageparameter, benannt über das Attribut, das angibt, wohin er gehört: path, query, header oder body. ResponseField ist ein Feld der Antwort, benannt über name. Beide nehmen type, required, deprecated und ein default entgegen, wobei die Beschreibung ihr Inhalt ist; ResponseField nimmt außerdem pre- und post-Beschriftungen rund um den Namen entgegen.

userIdpathstringerforderlich

Die Benutzer-ID.

limitqueryinteger
Standard: 20

Wie viele Ergebnisse zurückgegeben werden, maximal 100.

planbetastring

Der Tarif des Benutzerkontos.

<ParamField path="userId" type="string" required>
  The user's ID.
</ParamField>

<ParamField query="limit" type="integer" default={20}>
  How many results to return, up to 100.
</ParamField>

<ResponseField name="plan" type="string" post={["beta"]}>
  The user's plan.
</ResponseField>

Verschachtle die Felder eines Objekts mit einem Expandable in seiner Beschreibung:

<ResponseField name="address" type="object">
  Where the order ships.

  <Expandable title="properties">
    <ResponseField name="city" type="string" required>
      City name.
    </ResponseField>
  </Expandable>
</ResponseField>

Auf einer Seite mit api-Frontmatter bauen die ParamFields außerdem das „Try it“-Panel und die Anfragebeispiele der Seite auf: siehe Handgeschriebene API-Seiten. Die Felder verwenden dieselben Namen und Props wie bei Mintlify, sodass dafür geschriebene Seiten unverändert rendern. Die Markdown-Kopie der Seite listet jedes Feld mit seinem Typ und seinen Flags auf.

Anfrage- und Antwortbeispiele

RequestExample und ResponseExample enthalten Codeblöcke, ein Tab pro betiteltem Code-Fence (dropdown wechselt wie bei CodeGroup zu einem Sprachmenü). Auf breiten Bildschirmen heften sie sich an eine Spalte neben der Seite, die Anfrage über der Antwort, und bleiben sichtbar, während die Leserschaft durch die Felder scrollt – so wie die Beispiele einer OpenAPI-Operation; die Seite verzichtet dafür auf ihr Inhaltsverzeichnis. Auf schmalen Bildschirmen folgen sie dem Seiteninhalt.

<RequestExample>

```bash cURL
curl --request POST https://api.acme.dev/v1/users \
  --header "Authorization: Bearer $ACME_TOKEN" \
  --data '{ "email": "ada@example.com" }'
```

```ts title="Acme SDK"
await acme.users.create({ email: "ada@example.com" });
```

</RequestExample>

<ResponseExample>

```json 201
{ "id": "usr_8f2k", "status": "invited" }
```

</ResponseExample>

Schreibe sie an eine beliebige Stelle auf der obersten Ebene der Seite; jedes wandert in die Spalte. Ist eines in eine andere Komponente verschachtelt, etwa in einen Tab, bleibt es dort, wo es steht.

GitHub info

Eine Karte, die auf ein GitHub-Repository verlinkt und dessen Stern- und Fork-Zahlen anzeigt. Die Zahlen werden zur Build-Zeit abgerufen – kein Client-JavaScript –, daher zeigen sie den Stand deines letzten Builds und keine Live-Werte; die Karte wird auch ohne sie gerendert, wenn die API nicht erreichbar ist. Übergib owner und repo oder lass beides weg, um das Repository aus deiner blume.config zu verwenden. Setze eine Umgebungsvariable GITHUB_TOKEN, um das API-Ratenlimit anzuheben; eine token-Prop überschreibt sie für eine einzelne Karte, aber die Umgebungsvariable hält das Token aus deinen Inhalten heraus.

Die Karte liest die Instanz aus github.host, sodass auf einer Enterprise-gehosteten Website auch explizite owner/repo diese Instanz adressieren. Übergib host, um eine einzelne Karte woanders hinzurichten – etwa auf ein öffentliches Projekt von einer Enterprise-Website aus; die REST-Basis wird davon genauso abgeleitet wie von github.host.

haydenbleasel/blumeThe open-source docs framework for humans and agents.Sterne: 1.8KForks: 118
<!-- Uses the repo from blume.config -->
<GithubInfo />

<!-- Or point it at any repository -->
<GithubInfo owner="haydenbleasel" repo="blume" />

<!-- Or at a repository on another instance -->
<GithubInfo host="https://github.com" owner="haydenbleasel" repo="blume" />

Component

Component rendert eine Beispieldatei aus dem Verzeichnis examples/ deines Projekts als Live-Vorschau neben ihrem hervorgehobenen Quellcode, in Tabs. Richte es mit path auf eine Datei aus – ihr Ort unterhalb von examples/, ohne Erweiterung (aus examples/counter.tsx wird also path="counter"). React-, Vue-, Svelte- und Astro-Beispiele werden alle unterstützt; Framework-Beispiele hydrieren, Astro-Beispiele werden statisch gerendert. So bleiben Vorschau und Code aus einer einzigen Datei synchron. Ein path, der auf kein Beispiel verweist, rendert stattdessen einen „No example found“-Kasten, und blume dev, blume build und blume doctor warnen an der entsprechenden Zeile davor (BLUME_EXAMPLE_NOT_FOUND).

Die Vorschau rendert in einem isolierten Rahmen, den die Doku-Styles nie erreichen – keine Fließtext-Abstände, Typografie oder Theme-Elemente sickern in deine Komponente. Der Rahmen erhält Tailwind (Preflight + Utilities, die aus deinem Projekt und deinem Beispielverzeichnis gescannt werden), Blumes Design-Tokens, sodass Klassen wie bg-background standardmäßig der Website-Palette folgen, und er folgt der Hell-/Dunkel-Umschaltung der Website in Echtzeit. Der Bereich passt seine Größe an das gerenderte Beispiel an – und verfolgt das weiter, falls das Beispiel nach dem Laden wächst oder schrumpft – wobei die Tabs „Preview“ und „Code“ dieselbe Höhe teilen, sodass das Umschalten die Seite nie verschiebt.

Um Vorschauen mit deinem eigenen Designsystem zu gestalten – etwa mit shadcn-Variablen – richte examples.css auf ein Stylesheet aus. Es wird nach Blumes Standardwerten in jeden Vorschaurahmen eingefügt, sodass deine Tokens gewinnen. Verwende darin kein @import "tailwindcss"; der Rahmen stellt Tailwind bereits bereit. Sowohl .dark als auch [data-theme="dark"] funktionieren für Dark-Mode-Overrides:

// blume.config.ts
export default defineConfig({
  examples: { css: "examples/theme.css" },
});
/* examples/theme.css */
:root {
  --primary: oklch(0.6 0.2 260);
}

.dark {
  --primary: oklch(0.75 0.15 260);
}

@theme inline {
  --color-primary: var(--primary);
}

Auch das Verzeichnis ist konfigurierbar – setze source (oder nutze die Kurzschreibweise als String, examples: "..."), wenn deine Beispiele anderswo liegen (z. B. in einem Registry-Layout). path ist immer relativ dazu:

// blume.config.ts
export default defineConfig({
  examples: "registry/files-sdk",
});
<!-- registry/files-sdk/file-list/basic.tsx -->
<Component path="file-list/basic" />

examples kann auch ein Glob sein (alles mit *, ?, [], {} oder !). Es werden nur passende Dateien erfasst, und path ist relativ zum statischen Präfix des Globs (dem Teil vor dem ersten Platzhalter). Das ist für eine Registry gedacht, die den Quellcode jeder Komponente neben ihrem Beispiel ablegt – richte es nur auf die Beispiele aus, damit die Quelldateien, die keinen Default-Export für eine Vorschau haben, nicht mit eingesammelt werden:

// blume.config.ts
export default defineConfig({
  // registry/files-sdk/file-list/file-list.tsx — source, left out
  // registry/files-sdk/file-list/examples/basic.tsx — discovered
  examples: "registry/files-sdk/**/examples/*",
});
<!-- keyed relative to registry/files-sdk -->
<Component path="file-list/examples/basic" />

In einem Monorepo liegen die Komponenten, die deine Beispiele importieren, meist in einem benachbarten Workspace-Paket. Tailwinds @source scannt Dateien, keine Importe: Blume scannt dein Projekt und das examples-Verzeichnis (wohin auch immer source zeigt, auch außerhalb des Projekts), sodass eine Klasse, die nur innerhalb dieses benachbarten Pakets verwendet wird, erst erzeugt wird, wenn du das Paket zum Scan hinzufügst. Das machst du mit einer @source-Direktive in examples.css (für die Vorschaurahmen) oder theme.css (für die Website), relativ zu der Datei geschrieben, in der sie steht – die übliche Tailwind-Regel – und Blume übernimmt sie in das erzeugte Stylesheet:

/* examples/theme.css */
@source "../../../packages/ui/src";
import { useState } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <button
      className="rounded-blume border-border bg-background text-foreground hover:bg-muted border px-4 py-2 text-sm font-medium transition-colors"
      onClick={() => setCount((value) => value + 1)}
      type="button"
    >
      Clicked {count} {count === 1 ? "time" : "times"}
    </button>
  );
};

export default Counter;
<!-- examples/counter.tsx -->
<Component path="counter" />

Ein Astro-Beispiel rendert live und ohne Client-JavaScript:

---
interface Props {
  title?: string;
}

const { title = "Hello from Astro" } = Astro.props;
---

<div class="rounded-blume border border-border bg-muted/30 px-5 py-4">
  <p class="m-0 font-semibold text-foreground text-sm">{title}</p>
  <p class="m-0 mt-1 text-muted-foreground text-sm">
    A static, server-rendered example — no client JavaScript ships.
  </p>
</div>

CodeBlock

CodeBlock hebt einen Code-String mit demselben Shiki-Theme und denselben Transformern hervor wie deine eingezäunten Codeblöcke – einschließlich des Hell-/Dunkel-Wechsels – für Stellen, an die kein Code-Fence passt, etwa eine Landingpage oder eine eigene Komponente. Übergib code und ein lang:

export const greet = (name: string): string =>
`Hello, ${name}!`;
---
import CodeBlock from "blume/components/content/CodeBlock.astro";
---

<CodeBlock lang="ts" code={source} />

title legt die Beschriftung der Kopfzeile fest – etwa einen Dateinamen –, die sonst die Sprache anzeigt, und icons={false} blendet das Marken-Icon der Sprache aus, so wie es markdown.code.icons für Code-Fences tut.

Ohne code rendert CodeBlock seine Kinder so, wie sie geschrieben sind, sodass ein Code-Fence, der in <CodeBlock>…</CodeBlock> eingeschlossen ist (so wie Fern und Mintlify Code schreiben), als ebendieser Fence angezeigt wird. title und die übrigen Props greifen dann nicht: Gib dem Fence stattdessen nach der Sprache seinen Titel.

Um selbst zu einem HTML-String hervorzuheben (z. B. innerhalb deiner eigenen Komponente), importiere den zugrunde liegenden Helfer aus blume/markdown:

import { highlightCode } from "blume/markdown";

const html = await highlightCode(source, "ts");

Diff

Diff rendert einen Diff im Git-Stil, hervorgehoben mit demselben Shiki-Theme wie deine Codeblöcke und vollständig zur Build-Zeit erzeugt – kein Client-JavaScript. Übergib zwei Inline-Strings (old / new), zwei Dateipfade (before / after) oder einen Unified Patch (einen Inline-patch-String oder eine src-Datei).

<Diff
  lang="ts"
  old={`export function greet(name) {
  return "Hi, " + name;
}`}
  new={`export function greet(name: string): string {
  return "Hi, " + name + "!";
}`}
/>

Vergleiche zwei Dateien in deinem Projekt, relativ zu dessen Stammverzeichnis:

<Diff before="diffs/button-before.ts" after="diffs/button-after.ts" />

Oder rendere einen Unified Patch – entweder aus einer Datei mit src oder inline mit patch:

<Diff src="diffs/greet.patch" />
<Diff
  patch={`--- a/greet.ts
+++ b/greet.ts
@@ -1,3 +1,4 @@
-export function greet(name) {
-  return "Hi, " + name;
+export function greet(name: string): string {
+  const greeting = "Hi, " + name + "!";
+  return greeting;
 }`}
/>

Zuletzt aktualisiert am

War diese Seite hilfreich?