---
title: Konfigurationsdatei
description: >-
  Jede Option in blume.config.ts, von Website-Metadaten und Inhaltsquellen bis zu den Links, die zu den einzelnen Konfigurationsanleitungen der jeweiligen Funktionen führen.
sidebar:
  label: blume.config.ts
---

Blume liest `blume.config.ts` aus dem Stammverzeichnis deines Projekts. Umschließe deine Konfiguration mit `defineConfig`, um Autovervollständigung und Typprüfung zu erhalten — jedes Feld ist optional und hat einen sinnvollen Standardwert.

```ts blume.config.ts lineNumbers
import { defineConfig } from "blume";

export default defineConfig({
  title: "My Docs",
  description: "Documentation for my project.",
});
```

## Ein vollständiges Beispiel [#a-complete-example]

Ein umfassenderes Beispiel, das die gängigsten Optionen abdeckt (den Rest findest du in der Anleitung zur jeweiligen Funktion):

```ts blume.config.ts lineNumbers
import sitemap from "@astrojs/sitemap";
import { defineConfig } from "blume";

export default defineConfig({
  // Site
  title: "My Docs",
  description: "Documentation for my project.",
  logo: "/logo.svg",

  // Astro integrations — installed and versioned by this site
  integrations: [sitemap()],

  // Content
  content: {
    root: "docs",
  },

  // Theme — see the Theming guide
  theme: {
    accent: "teal",
    radius: "md",
    mode: "system",
  },

  // Search — see the Search guide
  search: {
    provider: "orama",
  },

  // Markdown features
  markdown: {
    imageZoom: true,
    code: {
      icons: true, // language icon in the code-block header
      wrap: false, // wrap long lines instead of scrolling
    },
    codeBlocks: {
      theme: {
        light: "github-light", // bundled name or custom Shiki theme object
        dark: "github-dark",
      },
    },
  },

  // AI — llms.txt, MCP, the AI catalog; see the Discoverability section
  ai: {
    llmsTxt: true,
    // AI Catalog / ARD manifest at /.well-known/ai-catalog.json (needs deployment.site)
    catalog: true,
    // MCP server (needs server output)
    mcp: {
      enabled: false,
      route: "/mcp",
    },
  },

  // SEO — OG images, feeds, sitemap, structured data; see the Discoverability section
  seo: {
    og: { enabled: true },
    rss: { enabled: true, types: ["blog", "changelog"] },
    sitemap: true,
    robots: true,
    structuredData: true,
  },

  // Deployment — see the Deployment guide
  deployment: {
    output: "static",
    site: "https://docs.example.com",
  },
});
```

## Website [#site]

| Option | Standard | Beschreibung |
| --- | --- | --- |
| `title` | `"Documentation"` | Name der Website — wird im Header, in Seitentiteln und OG-Karten angezeigt. |
| `description` | — | Standard-Meta-Beschreibung, wird für SEO und OG verwendet. |
| `logo` | — | Bildmarke und/oder Wortmarke, die im Header angezeigt wird. |
| `banner` | — | Websiteweite Ankündigungsleiste über dem Header. |

### Logo

Verweise mit `logo` auf eine SVG-Datei, und Blume bindet sie inline ein, sodass ein Logo mit `currentColor` automatisch dem hellen und dunklen Theme folgt:

```ts blume.config.ts
logo: "/logo.svg",
```

Die SVG-Datei kann im Stammverzeichnis deines Projekts oder in `public/` liegen. Die Marke besteht aus einer Bildmarke (`image`) plus einer Wortmarke (`text`); in der Objektform kannst du beide unabhängig voneinander festlegen:

```ts blume.config.ts lineNumbers
logo: {
  image: "/logo.svg", // string, or { light, dark, alt } for themed raster art
  text: "Acme",       // wordmark beside the mark
  href: "/",          // overrides the brand link (defaults to "/")
},
```

`image` nimmt denselben Wert wie die Kurzform entgegen — einen einzelnen Pfad oder `{ light, dark, alt }` für getrennte helle/dunkle Grafiken (Rasterbilder müssen in `public/` liegen).

`text` steuert die Wortmarke unabhängig von der Bildmarke:

- **Lässt du `text` weg**, verwendet die Marke den `title` deiner Website (Standardverhalten).
- **Setze `text: ""`**, um nur die Bildmarke anzuzeigen — praktisch, wenn das Logobild die Wortmarke bereits enthält.
- **Setze `text` ohne `image`** für ein reines Text-Logo.

### Favicon

Es gibt keine Favicon-Option — Blume erkennt es automatisch anhand des Dateinamens, so wie Next.js es tut. Lege eine `icon`- oder `favicon`-Datei (`.svg`, `.png` oder `.ico`) in das Stammverzeichnis deines Projekts oder in das Verzeichnis `public/`, und sie wird zum Symbol im Browser-Tab:

```
my-docs/
├─ blume.config.ts
├─ icon.png          ← picked up automatically
└─ docs/
```

Sind mehrere vorhanden, gewinnt SVG vor PNG vor ICO, und eine Datei in `public/` wird gegenüber einer im Stammverzeichnis bevorzugt. Findet Blume kein Icon, greift es auf die eigene Bildmarke zurück.

Eine dunkle Bildmarke verschwindet vor dunkler Browser-Oberfläche, deshalb kannst du eine zweite Datei für den Dunkelmodus mitliefern. Lege eine `-dark`-Geschwisterdatei neben deine Icon-Datei — gleicher Name, gleiches Verzeichnis, mit `-dark` vor der Dateiendung (`icon.png` → `icon-dark.png`) — und Blume gibt beide Icons hinter einer `prefers-color-scheme`-Media-Query aus, plus ein einfaches helles Tag für Browser und Crawler, die Media Queries bei Icons ignorieren:

```
my-docs/
├─ blume.config.ts
├─ icon.png          ← light mode
├─ icon-dark.png     ← dark mode
└─ docs/
```

Verwendet wird nur die Geschwisterdatei des Icons, das Blume ausgewählt hat — eine `-dark`-Datei mit einem anderen Namen bleibt unbeachtet, sodass sich keine unbeteiligte Datei versehentlich mit deiner Bildmarke paaren kann. Die dunkle Datei ist optional; bei nur einem Icon gibt Blume wie bisher ein einzelnes Tag aus. Blumes eigene Fallback-Bildmarke bringt beide Varianten mit.

### Apple-Touch-Icon

Das Symbol, das iOS verwendet, wenn jemand deine Website zum Home-Bildschirm hinzufügt, wird auf dieselbe Weise erkannt. Lege eine `apple-icon`-Datei (`.png`, `.jpg` oder `.jpeg`) — oder eine `apple-touch-icon.png`, den Namen, den die meisten Favicon-Generatoren ausgeben — in das Stammverzeichnis deines Projekts oder in das Verzeichnis `public/`, und Blume richtet `<link rel="apple-touch-icon">` für dich ein. Es gibt keinen Standardwert; wird keine Datei gefunden, wird kein Tag ausgegeben.

```
my-docs/
├─ blume.config.ts
├─ apple-icon.png     ← picked up automatically
└─ docs/
```

Lege die Datei in `public/` statt in das Stammverzeichnis des Projekts: iOS ignoriert die Inline-Daten-URI, die Blume für ein Icon im Stammverzeichnis verwendet, sodass nur eine Datei in `public/` (ausgeliefert unter `/apple-icon.png`) zuverlässig auf den Home-Bildschirm gelangt. Anders als beim Favicon gibt es hier keine `-dark`-Geschwisterdatei — iOS ignoriert Media Queries bei Home-Bildschirm-Icons, eine dunkle Variante könnte also nie ausgeliefert werden.

### Banner

Zeige eine websiteweite Ankündigungsleiste über dem Header an. Übergib eine Zeichenkette oder ein Objekt mit einem Link und einer Schließen-Schaltfläche:

```ts blume.config.ts
banner: "Docs are in beta — expect changes.",
```

```ts blume.config.ts lineNumbers
banner: {
  content: "Blume v1 is here!",
  link: { text: "Read more", href: "/blog/v1" },
  dismissible: true,
  id: "v1",
},
```

Ist `dismissible` aktiviert, zeigt die Leiste eine Schließen-Schaltfläche und bleibt für diese Besucherin bzw. diesen Besucher danach ausgeblendet. Der Schlüssel für das Ausblenden basiert standardmäßig auf dem Inhaltstext, sodass eine Bearbeitung der Nachricht das Banner zurückbringt; setze eine feste `id`, damit es über Bearbeitungen hinweg ausgeblendet bleibt.

## Inhalte [#content]

Wo deine Inhalte liegen und wie Blume sie findet. Unter [Seiten](/docs/content) erfährst du, wie aus Dateien Routen werden.

```ts blume.config.ts lineNumbers
content: {
  root: "docs",
}
```

| Option | Standard | Beschreibung |
| --- | --- | --- |
| `root` | `"docs"` | Ordner, den Blume nach Inhalten durchsucht. |
| `include` | `["**/*.{md,mdx}"]` | Globs, die auf Inhaltsdateien passen. |
| `exclude` | `["**/_*", "**/.*"]` | Zu ignorierende Globs (Dateien mit Unterstrich und Punkt am Anfang). |
| `pages` | `"pages"` | Ordner für benutzerdefinierte `.astro`-Seiten. |
| `defaultType` | `"doc"` | Seiten-`type`, der verwendet wird, wenn das Frontmatter ihn weglässt. |
| `types` | `{}` | Inhaltsdefinitionen pro Typ — benutzerdefinierte Frontmatter-Schlüssel, die auf Seiten eines `type` beschränkt sind. Siehe [Frontmatter](#frontmatter). |

Statische Assets liegen in `public/` — eine Datei unter `public/logo.png` wird unter `/logo.png` ausgeliefert, sodass eine Referenz wie `![](/images/create.png)` auf `public/images/create.png` verweist. Bilder, die über einen **relativen Pfad** referenziert werden (`![](./diagram.png)`), liegen stattdessen neben deinen Inhalten und werden [beim Build optimiert](/docs/content/syntax#links-and-images).

## Bilder [#images]

Lokale Bilder, die über einen relativen Pfad referenziert werden, werden beim Build automatisch optimiert — komprimiert, in WebP konvertiert und mit intrinsischen `width`/`height`-Attributen versehen, damit das Layout beim Laden nicht springt. Es gibt nichts zu konfigurieren; Hinweise zum Verfassen findest du unter [Links und Bilder](/docs/content/syntax#links-and-images).

Externe Bilder werden standardmäßig unverändert ausgeliefert. Damit Blume sie ebenfalls beim Build herunterlädt und optimiert, autorisiere ihre Hosts:

```ts blume.config.ts lineNumbers
image: {
  domains: ["cdn.example.com"],
  remotePatterns: [{ protocol: "https", hostname: "**.example.com" }],
}
```

| Option | Standard | Beschreibung |
| --- | --- | --- |
| `domains` | `[]` | Hostnamen, deren externe Bilder optimiert werden dürfen. |
| `remotePatterns` | `[]` | Musterbasierte Autorisierung (`protocol`, `hostname`, `port`, `pathname`); Hostnamen akzeptieren die Platzhalter `*.` (eine Ebene) und `**.` (beliebige Tiefe). |

## Frontmatter

Das Frontmatter einer Seite wird streng validiert — ein unbekannter Schlüssel lässt den Build fehlschlagen, sodass Tippfehler früh auffallen. Um projektspezifische Metadaten zu hinterlegen (eine verantwortliche Person, ein Prüfdatum), deklariere die zusätzlichen Schlüssel unter `frontmatter.extend`, jeweils zugeordnet zu einem von dir bereitgestellten Schema:

```ts blume.config.ts lineNumbers
import { defineConfig } from "blume";
import { z } from "zod";

export default defineConfig({
  frontmatter: {
    extend: {
      owner: z.string(),
      reviewedAt: z.coerce.date().optional(),
    },
  },
});
```

Jede [Standard-Schema](https://standardschema.dev)-Bibliothek funktioniert — Zod (in der Version, die dein Projekt installiert), Valibot, ArkType. Schlüssel außerhalb der Erweiterung bleiben streng validiert, das Erkennen von Tippfehlern ändert sich also nicht. Zur Validierungssemantik siehe [Benutzerdefinierte Schlüssel](/docs/reference/frontmatter#custom-keys).

Schlüssel unter `extend` gelten websiteweit. Um Schlüssel nur auf Seiten eines Inhaltstyps vorzuschreiben — der `status` eines RFCs, der `service` eines Runbooks — deklariere sie stattdessen pro Typ unter `content.types`:

```ts blume.config.ts lineNumbers
import { defineConfig } from "blume";
import { z } from "zod";

export default defineConfig({
  content: {
    types: {
      rfc: {
        facets: ["domain", "status"],
        frontmatter: {
          domain: z.string(),
          status: z.enum(["draft", "review", "enforced"]),
        },
      },
    },
  },
});
```

Ein Schlüssel kann websiteweit oder pro Typ deklariert werden, nicht beides. Wie die Zuordnung aufgelöst wird, erfährst du unter [Schlüssel pro Typ](/docs/reference/frontmatter#per-type-keys).

`facets` benennt die benutzerdefinierten Schlüssel, deren Werte zu filterbaren Metadaten werden: Sie werden mit den Suchdokumenten mitgeführt (`blume-search.json` und der MCP-Index), und die [MCP-Tools](/docs/discoverability/mcp) akzeptieren eine `filters`-Eingabe, die gegen sie abgeglichen wird, sodass ein Agent zum Beispiel nur `enforced`-RFCs in der Domäne `architecture` abrufen kann. Jedes Facet muss ein deklarierter benutzerdefinierter Schlüssel sein — pro Typ oder websiteweit — und nur Zeichenketten-Werte (oder in Zeichenketten umgewandelte Zahlen/Booleans) werden facettiert.

## GitHub

Verweise Blume mit `github` auf dein Repository. Das versorgt den [Repository-Link](/docs/content/navigation#repository-link) im Header sowie die [Seitenaktionen](/docs/content/navigation#page-actions) **Edit on GitHub** und **Give feedback**:

```ts blume.config.ts lineNumbers
github: {
  owner: "acme",
  repo: "docs",
}
```

| Option | Standard | Beschreibung |
| --- | --- | --- |
| `owner` | — | GitHub-Konto oder -Organisation, der bzw. dem das Repository gehört. |
| `repo` | — | Name des Repositorys. |
| `branch` | `"main"` | Branch, auf den die Bearbeitungslinks verweisen. |
| `dir` | — | Pfad vom Repository-Stammverzeichnis zum Projektstammverzeichnis (für Monorepos). |
| `host` | `"https://github.com"` | Origin der GitHub-Instanz, für Enterprise-Installationen. Muss HTTP(S) sein; wird auf ihren Origin normalisiert. |
| `api` | aus `host` abgeleitet | REST-API-Basis, für `<GithubInfo>` gegen eine Enterprise-Instanz. Muss HTTP(S) sein; wird auf einen Origin und Pfad normalisiert. |

### GitHub Enterprise

Dokumentationen, deren Repository auf einer GitHub-Enterprise-Instanz liegt, setzen `host`, und jeder aus dem Repository abgeleitete Link — die Bildmarke im Header, Bearbeitungslinks, das Agenten-Manifest — verweist dann auf diese Instanz statt auf die öffentliche Website:

```ts blume.config.ts lineNumbers
github: {
  host: "https://github.acme.com",
  owner: "acme",
  repo: "docs",
}
```

Die REST-API-Basis, die [`<GithubInfo>`](/docs/content/components) abfragt, wird aus `host` abgeleitet: Ein Enterprise-Cloud-Tenant mit Datenresidenz (`acme.ghe.com`) wird über seine `api.`-Subdomain ausgeliefert, und jeder andere Host wird als Enterprise Server behandelt (`/api/v3`). Setze `api` explizit, wenn deine Instanz woanders liegt.

:::warning
Eine Instanz, die nur über einfaches HTTP erreichbar ist, rendert ihre Zahlen weiterhin, aber `GITHUB_TOKEN` wird von der Anfrage zurückgehalten, statt im Klartext gesendet zu werden — die Karte eines privaten Repositorys kommt also ohne sie zurück.
:::

:::note
`host` deckt Links ab, die Blume aus `github` ableitet. Um nur die Bildmarke im Header woanders hinzuleiten — etwa auf eine Organisation, wenn das Docs-Repository selbst privat ist — verwende [`navigation.repo`](/docs/content/navigation#repository-link) mit einer absoluten URL.
:::

## Zuletzt geändert [#last-modified]

Zeige am Ende jeder Seite eine Zeile „Zuletzt aktualisiert am …“ an. Standardmäßig deaktiviert; setze `lastModified` auf `true`, um das Datum jeder Seite aus ihrer Git-Historie abzuleiten:

```ts blume.config.ts
lastModified: true,
```

| Wert | Beschreibung |
| --- | --- |
| `false` | Deaktiviert (Standard). |
| `true` | Datum aus der Git-Historie lesen (Commit-Daten). |
| `{ type: "git" }` | Dasselbe wie `true`, nur explizit geschrieben. |
| `{ type: "frontmatter" }` | Git nie ausführen — ausschließlich das Frontmatter-Feld `lastModified` verwenden. |

Die Git-Quelle liest den jüngsten Commit, der die jeweilige Datei berührt hat, funktioniert also in jedem Git-Repository — auch in Monorepos — und benötigt die Historie des Repositorys zur Build-Zeit. CI-Plattformen checken üblicherweise einen flachen Klon aus, wodurch die meisten Daten stillschweigend verloren gehen (der Build warnt in diesem Fall mit `BLUME_SHALLOW_GIT_HISTORY`): Setze auf Vercel die Umgebungsvariable `VERCEL_DEEP_CLONE=true`; bei `actions/checkout` setze `fetch-depth: 0`. Das seiteneigene `lastModified`-Frontmatter gewinnt immer, was praktisch ist, um ein Datum festzuschreiben oder für Dateien, die noch nicht committet sind:

```mdx page.mdx
---
title: My page
lastModified: 2026-06-20
---
```

Ist die Funktion aktiviert, wird das Datum außerdem als schema.org-`dateModified` in den strukturierten Daten der Seite ausgegeben.

## Datumsformat [#date-format]

Sowohl der Stempel „Zuletzt aktualisiert“ als auch die Zeitleiste des [Changelogs](/docs/advanced/changelog) rendern ihre Daten über dasselbe `dateFormat`, damit sie sich gleich lesen. Daten werden immer in der Sprache der Website gerendert; `dateFormat` steuert die _Form_. Standardmäßig wird die lange Form verwendet (`21. Juli 2026`, `2026年7月21日`):

```ts blume.config.ts
dateFormat: { dateStyle: "long" },
```

`dateFormat` wird direkt an die Optionen von [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) durchgereicht. Verwende eine `dateStyle`-Voreinstellung für eine bestimmte Länge:

```ts blume.config.ts
dateFormat: { dateStyle: "medium" },
```

Oder die einzelnen Komponentenfelder für einen numerischen Hausstil wie `2026/07/21`:

```ts blume.config.ts
dateFormat: { year: "numeric", month: "2-digit", day: "2-digit" },
```

| Option | Beschreibung |
| --- | --- |
| `dateStyle` | Voreingestellte Länge: `"full"`, `"long"`, `"medium"` oder `"short"`. Nicht mit den Komponentenfeldern kombinierbar. |
| `weekday`, `era`, `year`, `month`, `day` | Einzelne Komponenten, z. B. `year: "numeric"`, `month: "2-digit"`. |
| `timeZone` | IANA-Zeitzone. Standard ist `UTC`, sodass ein Datum unabhängig vom Build-Ort gleich gelesen wird. |
| `calendar`, `numberingSystem` | Kalendersystem (z. B. `"japanese"`) und Nummerierungssystem (z. B. `"arab"`). |

## SEO und KI [#seo-and-ai]

Metadaten, Open-Graph-Bilder, RSS-Feeds, JSON-LD, die Sitemap und `robots.txt` liegen unter `seo`; `llms.txt`, rohes Markdown, die JSON-API und der MCP-Server liegen unter `ai`. Beide werden Seite für Seite im Abschnitt [Auffindbarkeit](/docs/discoverability) behandelt, der Suchmaschinen und KI-Agents als zwei Zielgruppen derselben maschinenlesbaren Schicht betrachtet.

```ts blume.config.ts lineNumbers
seo: {
  og: { enabled: true },
  rss: { enabled: true, types: ["blog", "changelog"] },
  sitemap: true,
  robots: true,
  structuredData: true,
}
```

| Option | Standard | Beschreibung |
| --- | --- | --- |
| `og.enabled` | automatisch | Open-Graph-Bilder pro Seite — aktiv, sobald eine Website-URL gesetzt ist. |
| `rss.enabled` | `true` | Feeds für Blog- und Changelog-Inhalte erzeugen. |
| `rss.types` | `["blog", "changelog"]` | Inhaltstypen, die jeweils einen Feed erhalten. |
| `rss.limit` | `50` | Maximale Anzahl an Einträgen pro Feed. |
| `sitemap` | `true` | sitemap.xml erzeugen (benötigt deployment.site). |
| `robots` | `true` | robots.txt mit einem Sitemap-Link erzeugen. |
| `structuredData` | `true` | schema.org-JSON-LD im Head jeder Seite ausgeben. |

Diese Funktionen entfalten ihre volle Wirkung mit einer absoluten [`deployment.site`](/docs/deployment) für vollständige URLs.

## Inhaltsverzeichnis [#table-of-contents]

Die Gliederung „Auf dieser Seite“ ist standardmäßig aktiviert und listet `H2`–`H3`-Überschriften auf. Schalte sie mit `toc` ab oder ändere den Überschriftenbereich:

```ts blume.config.ts
export default defineConfig({
  toc: false, // hide it everywhere
});
```

Oder schränke stattdessen den Überschriftenbereich ein:

```ts blume.config.ts
export default defineConfig({
  toc: { minHeadingLevel: 2, maxHeadingLevel: 4 },
});
```

## Funktionsoptionen [#feature-options]

Zu jeder dieser Optionen gibt es eine eigene Anleitung. Das Konfigurationsfeld ist der Einstiegspunkt:

| Feld | Was es konfiguriert | Anleitung |
| --- | --- | --- |
| `theme` | Akzentfarbe, Eckenradius, Schriften, heller/dunkler Modus | [Theming](/docs/configuration/theming) |
| `navigation` | Explizite Seitenleiste und Header-Tabs | [Navigation](/docs/content/navigation) |
| `search` | Anbieter (Orama, Pagefind, Algolia und weitere) und Indizierung | [Suche](/docs/configuration/search) |
| `markdown` | Optionen für das Markdown-Rendering — Codeblöcke, Überschriftenanker, Bildzoom | [Syntax](/docs/content/syntax) |
| `ai` | `llms.txt`, Markdown-Spiegel, die JSON-API und der gehostete MCP-Server für Coding-Agents | [SEO und AEO](/docs/discoverability) |
| `ai.ask` | Der Ask-AI-Assistent direkt auf der Seite | [Ask AI](/docs/configuration/ask-ai) |
| `analytics` | Vercel, PostHog und benutzerdefinierte Skripte | [Analytics](/docs/configuration/analytics) |
| `seo` | Metadaten, OG-Bilder, Feeds, strukturierte Daten, Sitemap, robots | [SEO und AEO](/docs/discoverability) |
| `deployment` | Ausgabemodus, Adapter und Website-URL | [Deployment](/docs/deployment) |
| `redirects` | Permanente und temporäre Weiterleitungen | [Deployment](/docs/deployment#redirects) |
| `integrations` | Astro-Integrationen, die nach Blumes eingebauten angehängt werden | [Anpassung](/docs/configuration/customization#astro-integrations) |

## Rangfolge [#precedence]

Einstellungen werden von der niedrigsten zur höchsten Priorität aufgelöst, sodass du nur überschreibst, was du brauchst:

1. **Blume-Standardwerte**

    Ein sinnvoller Standardwert für jedes Feld.

2. **blume.config.ts**

    Deine projektweite Konfiguration.

3. **Ordner-Meta**

    [`meta.ts`](/docs/content/meta) für Titel und Sortierung eines Abschnitts.

4. **Seiten-Frontmatter**

    Überschreibungen pro Seite gewinnen.
