Zum Inhalt springen
Blume
Deutsch
Esc
navigierenöffnen⌘Jvorschau
Auf dieser Seite

Auf Blume 2 upgraden

Hebe eine Blume-1-Site mit einem Befehl auf Blume 2 und nutze dann diesen Leitfaden für jede Konfigurationsänderung – oder überlass das gesamte Upgrade Claude Code oder Codex.

Blume 2 ändert die Konfiguration, nicht die Inhalte: Deine Markdown- und MDX-Seiten brauchen keine Anpassungen, es sei denn, eine davon setzt das entfernte Frontmatter-Feld search.boost (siehe Frontmatter). Einstellungen, die früher ein benannter String oder ein Block mit Schlüssel waren – der Suchanbieter, das Deployment-Ziel, Content-Quellen, API-Referenzen, Analytics und das Ask-AI-Backend –, sind jetzt Adapter, die du aus einem blume/*-Subpath importierst und aufrufst. Die maschinenlesbaren Einstellungen wandern von ai in einen neuen Schlüssel agents, und Überschreibungen in components.ts werden vor dem Build geprüft. Eine Site ohne Konfiguration oder eine, die nichts davon setzt, braucht nur das Versions-Update.

Mit einem Befehl upgraden

Führe das Upgrade in deinem Projekt aus, also im Ordner mit blume.config.ts:

npx blume@latest upgrade
pnpm dlx blume@latest upgrade
yarn dlx blume@latest upgrade
bunx blume@latest upgrade
nubx blume@latest upgrade
aube dlx blume@latest upgrade

Der Befehl hebt blume in deiner package.json auf 2 an, installiert es mit dem Paketmanager, den dein Projekt nutzt, und prüft dann deine Konfiguration und components.ts gegen Blume 2. Jede noch nötige Änderung wird mit Datei, Zeile und Ersatz aufgelistet – einschließlich package.json-Scripts, die noch die entfernten blume build-Flags übergeben –, und der Befehl endet mit einem Exit-Code ungleich null, bis keine mehr übrig ist. Führst du ihn in einem Ordner ohne Konfiguration und ohne blume-Abhängigkeit aus, bricht er stattdessen mit einem Fehler ab. Starte ihn über npx blume@latest statt über blume: Der Befehl kommt mit Blume 2, ein Projekt auf Version 1 hat ihn also noch nicht. Unter pnpm 12 ergänzt du --allow-build=esbuild nach pnpm dlx, da pnpm 12 das Installationsskript von esbuild nicht ohne Freigabe ausführt.

Wenn du die Änderungen stattdessen einem Coding-Agent überlassen willst, ergänze --claude oder --codex:

npx blume@latest upgrade --claude
pnpm dlx blume@latest upgrade --claude
yarn dlx blume@latest upgrade --claude
bunx blume@latest upgrade --claude
nubx blume@latest upgrade --claude
aube dlx blume@latest upgrade --claude

Der Agent startet interaktiv mit den Befunden und diesem Leitfaden, setzt jede Änderung um und führt blume doctor und blume build aus, bis beide durchlaufen – so prüfst du jede Bearbeitung über seinen eigenen Freigabeablauf. Übergib --no-install, um package.json anzuheben, ohne zu installieren.

Die folgenden Abschnitte behandeln jede Änderung – zum Upgraden von Hand oder um zu prüfen, was der Agent gemacht hat.

search nimmt einen Adapter aus blume/search statt eines provider-Strings mit Zugangsdaten-Block. Die standardmäßige lokale Suche braucht keine Änderung.

export default defineConfig({
  search: {
    provider: "algolia",
    algolia: { appId: "APP_ID", indexName: "docs", searchApiKey: "SEARCH_KEY" },
  },
});
import { defineConfig } from "blume";
import { algolia } from "blume/search";

export default defineConfig({
  search: algolia({ appId: "APP_ID", indexName: "docs", apiKey: "SEARCH_KEY" }),
});
  • Orama Cloud, Typesense und Mixedbread werden genauso auf oramaCloud(), typesense() und mixedbread() abgebildet. Der reine Such-Key heißt in jedem Adapter, der einen erwartet, apiKey; mixedbread() nimmt statt eines Keys eine storeId, da seine Abfragen auf dem Docs-Server laufen. Alle weiteren Optionen, die du ihm übergibst, werden an den Store-Suchaufruf weitergereicht, bei dem top_k standardmäßig 8 ist. Admin-Keys bleiben in ihren Umgebungsvariablen (ALGOLIA_ADMIN_API_KEY, ORAMA_PRIVATE_API_KEY, TYPESENSE_ADMIN_API_KEY, MIXEDBREAD_API_KEY).
  • provider: "pagefind" wird zu pagefind(), und provider: "none" wird zu search: false.
  • Um popular-Links oder indexing-Optionen zu behalten, umschließt du den Adapter: search: { provider: algolia({ … }), popular: […] }.

Deployment

deployment nimmt einen Host-Adapter aus blume/deploy statt der Felder adapter und output. site und base wandern in die Optionen des Adapters.

export default defineConfig({
  deployment: {
    adapter: "vercel",
    output: "server",
    site: "https://docs.example.com",
  },
});
import { defineConfig } from "blume";
import { vercel } from "blume/deploy";

export default defineConfig({
  deployment: vercel({ site: "https://docs.example.com" }),
});
  • netlify(), cloudflare() und node() funktionieren genauso. Sobald du einen Host-Adapter angibst, wird auf Server-Output umgeschaltet; übergib output: "static", um einen statischen Build mit den Plattformdateien dieses Hosts zu behalten.
  • Eine Konfiguration, die nur site oder base setzt, bleibt, wie sie ist: deployment: { site, base } ist weiterhin die statische Form.
  • redirects erwarten exakte Pfade. Ein from oder to mit einem :param-Segment oder einer *-Wildcard besteht die Validierung jetzt nicht mehr; Blume 1 hat Muster nie unterstützt, und Hosts haben sie unterschiedlich behandelt. Verschiebe Regeln mit Mustern in die eigene Konfiguration deines Hosts (vercel.json, _redirects).
  • Die Flags --adapter, --output und --base von blume build gibt es nicht mehr; übergibst du eines davon, bricht der Build mit einem Fehler ab, der die deployment-Einstellung nennt, die es ersetzt. Setze den Adapter in blume.config.ts und gib ihn explizit an: Server-Output wird nicht mehr aus der Umgebung der Plattform abgeleitet.

Die Optionen der einzelnen Adapter findest du unter Deployment.

Content-Quellen

Jeder Eintrag in content.sources ist ein Adapter aus blume/sources statt eines { type }-Objekts.

export default defineConfig({
  content: {
    sources: [
      { type: "filesystem", root: "content" },
      {
        type: "github-releases",
        owner: "acme",
        repo: "sdk",
        prefix: "changelog",
      },
    ],
  },
});
import { defineConfig } from "blume";
import { filesystem, githubReleases } from "blume/sources";

export default defineConfig({
  content: {
    sources: [
      filesystem({ root: "content" }),
      githubReleases({ owner: "acme", repo: "sdk", prefix: "changelog" }),
    ],
  },
});
  • mdx-remote, sanity, notion und obsidian werden zu mdxRemote(), sanity(), notion() und obsidian(), wobei alle anderen Felder unverändert in den Aufruf wandern. { type: "custom", source } wird zu custom(source).
  • content.root, content.include und content.exclude sind weiterhin die Kurzform für einen einzelnen Ordner, können aber nicht mehr neben sources stehen. Verschiebe sie in den filesystem()-Eintrag.
  • Release-Seiten aus githubReleases() werden jetzt in nur einer Sprache veröffentlicht, eine mehrsprachige Site kopiert sie also nicht mehr unter die URL jeder anderen Locale (/de/changelog/…). Wenn andere Sites auf diese Kopien verlinken, füge Redirects auf die Seiten der Standard-Locale hinzu.

API-Referenzen

Die Top-Level-Blöcke openapi, asyncapi und graphql werden zu einer einzigen reference-Liste mit Adaptern aus blume/reference. Lass enabled weg.

export default defineConfig({
  openapi: { enabled: true, spec: "./openapi.yaml" },
  graphql: {
    enabled: true,
    spec: "./schema.graphql",
    endpoint: "https://api.example.com/graphql",
  },
});
import { defineConfig } from "blume";
import { graphql, openapi } from "blume/reference";

export default defineConfig({
  reference: [
    openapi({ spec: "./openapi.yaml" }),
    graphql({
      spec: "./schema.graphql",
      endpoint: "https://api.example.com/graphql",
    }),
  ],
});
  • asyncapi: { … } wird zu asyncapi({ … }) mit denselben Optionen.
  • Eine AsyncAPI-Spec in Version 1.x oder 2.x wird weiterhin automatisch nach 3.0 konvertiert, der Konverter ist jetzt aber eine optionale Peer-Dependency: Installiere @asyncapi/converter in deinem Projekt, sonst schlägt der Build fehl und nennt dir den Installationsbefehl. Eine 3.x-Spec braucht nichts.
  • renderer: "scalar" wird zu einem eigenen scalar({ spec, theme, … })-Eintrag in der Liste, der route und sources des Blocks übernimmt.
  • Ein Block mit enabled: false wird einfach aus der Liste weggelassen.

Analytics

Das analytics-Objekt wird zu einer Liste von Adaptern aus blume/analytics.

export default defineConfig({
  analytics: {
    posthog: { key: "phc_…" },
    vercel: true,
  },
});
import { defineConfig } from "blume";
import { posthog, vercel } from "blume/analytics";

export default defineConfig({
  analytics: [posthog({ key: "phc_…" }), vercel()],
});

cloudflare: { token } wird zu cloudflare({ token }), und jeder scripts[]-Eintrag wird zu script({ … }).

Ask AI

ai.ask.provider nimmt einen Adapter aus blume/ai, der das Modell und die zugehörigen Felder verwaltet.

export default defineConfig({
  ai: {
    ask: {
      enabled: true,
      provider: "openrouter",
      model: "anthropic/claude-sonnet-4-5",
      reasoning: "none",
    },
  },
});
import { defineConfig } from "blume";
import { openrouter } from "blume/ai";

export default defineConfig({
  ai: {
    ask: {
      enabled: true,
      provider: openrouter({
        model: "anthropic/claude-sonnet-4-5",
        reasoning: "none",
      }),
    },
  },
});

Die Adapter sind gateway(), openrouter(), llmgateway(), inkeep() und openaiCompatible({ baseUrl, name, model, apiKeyEnv }). model, apiKeyEnv, baseUrl, headers und reasoning wandern in den Adapter; enabled, instructions, retrieval, suggestions, cors und endpoint bleiben unter ai.ask. Lässt du provider weg, wird weiterhin das AI Gateway verwendet.

Agents und weitere Verschiebungen in der Konfiguration

Die maschinenlesbaren Einstellungen wandern von ai in einen neuen Schlüssel agents, und drei kleinere Felder ändern ihre Form.

export default defineConfig({
  ai: { mcp: { enabled: true }, skills: "./skills" },
  lastModified: true,
  markdown: {
    codeBlocks: { theme: { light: "github-light", dark: "github-dark" } },
  },
  theme: { layout: "sidebar" },
});
export default defineConfig({
  agents: { mcp: { enabled: true }, skills: "./skills" },
  lastModified: "git",
  markdown: {
    code: { theme: { light: "github-light", dark: "github-dark" } },
  },
});
  • ai.api, ai.catalog, ai.llmsTxt, ai.markdownComponents, ai.mcp, ai.skills, ai.webBotAuth und ai.webmcp werden zu agents.*, ebenso seo.agentReadability und seo.contentSignals. In ai bleiben nur ask und openInChat.
  • lastModified ist ein einfacher Wert: true wird zu "git", und { type: "git" } oder { type: "frontmatter" } wird zum bloßen String.
  • markdown.codeBlocks geht in markdown.code auf.
  • theme.layout entfällt. Es wurde nirgends gelesen, also lösch es.

Frontmatter

Ein Frontmatter-Feld entfällt: search.boost. Blume 1 hat es akzeptiert, die Suche hat es aber nie ausgewertet – eine Seite wurde ohne das Feld also genauso gerankt. Lösch es überall, wo es vorkommt; eine Seite, die es noch setzt, besteht die Validierung nicht und bekommt einen Hinweis, und blume upgrade listet jedes Vorkommen mit Datei und Zeile auf.

Komponenten-Überschreibungen

Blume 2 prüft jeden Eintrag in components.ts vor dem Build, statt zur Laufzeit auf einen Fallback zurückzugreifen. Jeder mdx- und layout-Eintrag muss eine importierte Komponente, ein Pfad-String oder ein { component, client, media }-Objekt sein, und die Gruppe islands entfällt: Ein mdx-Eintrag mit einem client-Modus ist eine Island.

import { defineComponents } from "blume";
import Counter from "./islands/Counter.tsx";

export default defineComponents({
  islands: { Counter },
});
import { defineComponents } from "blume";
import Counter from "./islands/Counter.tsx";

export default defineComponents({
  mdx: { Counter: { component: Counter, client: "visible" } },
});

Eine Inline-Funktion, eine direkt in components.ts deklarierte Komponente, ein Spread oder ein berechneter Schlüssel schlägt jetzt mit BLUME_COMPONENTS_INVALID fehl, wobei der betroffene Eintrag genannt wird. Verschiebe die Komponente in eine eigene Datei und importiere sie. Die Ordnerkonvention islands/ funktioniert wie bisher. Die akzeptierten Formen findest du unter Anpassung.

Apps nach einem Eject

Eine App, die du unter Blume 1 ejectet hast, läuft nicht mehr über die Blume-CLI, hängt aber weiterhin vom Paket blume ab. Ihre Seiten importieren Blumes Komponenten, src/generated/ enthält einen Snapshot deiner Site, den der Generator von Blume 1 geschrieben hat, und astro build lädt blume.config.ts erneut, um den Suchindex, llms.txt und die Sitemap zu schreiben. Hebst du blume darunter auf 2 an, trifft dieser Blume-1-Snapshot auf Blume-2-Komponenten, die die neuen Formen erwarten – ejecte also stattdessen erneut:

Copy the project out

Kopiere alles außer astro.config.mjs, src/, .blume/, dist/ und node_modules/ in einen leeren Ordner: deine Inhalte, blume.config.ts, components.ts, islands/, public/, alle Spec-Dateien, die deine Referenzen einlesen, und package.json. Lass die ejectete App, wie sie ist.

Upgrade the copy

Führe in der Kopie npx blume@latest upgrade aus und setz um, was der Befehl auflistet, damit blume.config.ts und components.ts gültiges Blume 2 sind. Führe dann npx blume build aus, um sicherzustellen, dass die Site baut, bevor du sie ejectest.

Eject a fresh copy

Führe npx blume eject --yes in der Kopie aus, installiere die Pakete, die der Befehl hinzufügt, und baue sie mit npm run build.

Carry your edits across

Vergleiche die frische astro.config.mjs und src/ per Diff mit deiner ejecteten App und übertrage deine eigenen Änderungen auf die neuen Dateien.

Bis die frische Kopie fertig ist, belässt du die ejectete App auf Blume 1 ("blume": "^1") und führst darin nicht blume upgrade aus: Solange du die Version nicht anhebst, ändert sich nichts.

Kommandozeilen-Flags

Jeder blume-Befehl lehnt jetzt Flags ab, die er nicht kennt – Blume 1 hat sie ignoriert. Ein Script oder CI-Schritt, der ein überflüssiges oder falsch geschriebenes Flag übergibt, schlägt fehl und nennt das nicht erkannte Flag sowie die Flags, die der Befehl akzeptiert. blume upgrade meldet nur die drei entfernten blume build-Flags (--adapter, --output, --base), prüf also auch deine anderen blume-Scripts.

Ergebnis prüfen

Sobald blume upgrade nichts mehr zu ändern meldet, führe die Prüfungen der Site selbst aus:

npx blume doctor
npx blume build

Die vollständige Liste der Änderungen samt Begründung findest du im Changelog.

Zuletzt aktualisiert am 24. September 2026

War diese Seite hilfreich?