Migrate from @fumadocs/astro
Move a site from the managed setup of @fumadocs/astro 0.1.
The managed setup of @fumadocs/astro 0.1, with src/fumadocs.config.ts, is now @fumapress/astro. Do the steps in order.
Migration Steps
Install the Packages
npm i @fumapress/astro
npm i @fumadocs/astro@latest takumi-js fumadocs-core@latest
npm i fumadocs-ui@npm:@fumadocs/base-ui@latestUpdate the Integration
Your layout and page modules move out of the integration. If you have them, see Migrating Features.
import fumadocs from "@fumadocs/astro";
import press from "@fumapress/astro";
export default defineConfig({
integrations: [
fumadocs({
components: "./src/components/mdx.tsx",
layout: "./src/lib/layout.shared.tsx",
page: "./src/components/docs.tsx",
}),
press({
components: "./src/components/mdx.tsx",
}),
],
});Move the Config
Replace src/fumadocs.config.ts and src/lib/source.ts with one file at the project root. The source is passed directly to createPress(), and baseUrl becomes baseDir.
import { getCollection } from "astro:content";
import { toFumadocsSource } from "@fumadocs/astro/source";
import { createPress } from "@fumapress/astro/config";
export const app = createPress(
toFumadocsSource(await getCollection("docs"), await getCollection("meta"), {
baseDir: "docs",
}),
);
export default app.config({
site: { name: "My Docs" },
});Rename the Stylesheet
Move src/styles/global.css to src/app.css. This file replaces the css option. @fumapress/astro/css/default.css has the Tailwind and Fumadocs imports:
@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/preset.css";
@import "@fumapress/astro/css/default.css";Run the Site
npm run devIf you didn't customize your site, you're done. Otherwise, open the section for each feature you use.
Migrating Features
The page module becomes an .astro layout with a React island. page is now pageData, layout is layoutProps, and ui.renderPage chooses the layout. See Islands for how the two files work together.
import { createIsland } from "@fumapress/astro/client";
import type { IslandProps } from "@fumapress/astro/config";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { DocsBody, DocsPage, DocsTitle } from "fumadocs-ui/layouts/docs/page";
import type { app } from "../../press.config";
export const DocsIsland = createIsland(
({ layoutProps, pageData, toc, children }: IslandProps<typeof app, "docs">) => (
<DocsLayout {...layoutProps}>
<DocsPage toc={toc} full={pageData.full}>
<DocsTitle>{pageData.title}</DocsTitle>
<DocsBody>{children}</DocsBody>
</DocsPage>
</DocsLayout>
),
);baseOptions() of the layout module moves to ui.layoutProps, and receives { lang } in place of locale.
export default app.config({
ui: {
layoutProps({ lang }) {
return { links: [{ url: this.localizePath(lang, "/blog"), text: "Blog" }] };
},
},
});Provider of the layout module becomes a slot item in the layout-wrapper region.
createPress(content).plugins({
name: "site:provider",
slots({ page }) {
if (!page) return [{ name: "site:provider", region: "layout-wrapper", component: Provider }];
},
});The default search is now FlexSearch. To keep Orama, turn FlexSearch off and add the Orama plugin:
import { createPress, recommendedPreset } from "@fumapress/astro/config";
import { oramaSearchPlugin } from "@fumapress/astro/plugins/orama-search";
export const app = createPress(content).plugins(oramaSearchPlugin());
export default app.config({ preset: recommendedPreset({ search: false }) });SearchDialog and useSearch of the layout module become one dialog in ui.providerProps. See Custom Search Dialog.
createPress(content).config({
ui: { providerProps: { search: { SearchDialog } } },
});The head component becomes a list of tags. See Head Tags.
export default app.config({
head: Head,
head: [{ tag: "link", attrs: { rel: "icon", href: "/favicon.svg" } }],
});i18n moves from loader() to createPress(), and translations to ui.translations. See Internationalization.
export const app = createPress(content, { i18n });
export default app.config({
ui: { translations: i18n.translations() },
});createPress(content).config({
preset: false,
preset: [],
});API docs and content sources are now the default export of their integration, and other plugins moved to @fumapress/astro:
import { openapiPlugin } from "@fumadocs/astro/plugins/openapi";
import { notionPlugin } from "@fumadocs/astro/plugins/notion";
import { takumiPlugin } from "@fumadocs/astro/plugins/takumi";
import openapiPlugin from "fumadocs-openapi/press";
import notionPlugin from "@fumadocs/notion/press";
import { takumiPlugin } from "@fumapress/astro/plugins/takumi";asyncapi,graphqlandsanitychange the same way asopenapi.flexsearch,llms.txt,orama-searchandlink-validationchange the same way astakumi, to@fumapress/astro/plugins/*.- Takumi, FlexSearch and llms.txt are default plugins. To pass them options, use
recommendedPreset()instead of listing them.
A few are removed:
contentSourcePlugin(): delete it. See Local Markdown.gitPlugin(): setsite.gitand thelastModifiedoption ofpress().plugins/mcp: usemcpPlugin()of@fumapress/ai.
Images move from /og/<page>/image.webp to <page>.webp, and the prefix option becomes path. Update any URL you hard-coded.
---
import HomeLayout from "@fumadocs/astro/components/HomeLayout.astro";
import HomeLayout from "@fumapress/astro/components/HomeLayout.astro";
---ReactContent.astro is removed. Render a React component on the page, like <Stars client:load />.
routes() calls functions instead of returning a list, and this is now the press context. See Writing Plugins.
routes() {
return [{
type: "file",
url: `${this.base}/status.json`,
GET: () => Response.json({ ok: true }),
}];
},
routes({ createApi }) {
createApi({ path: "/status.json", render: "static", GET: () => Response.json({ ok: true }) });
},The other changes are renames, with two changes in signature. middleware now receives a Request, and only runs for routes rendered on demand. transformPage receives the data first, and returns the changed fields.
| 0.1 | Now |
|---|---|
getBody | getPageBody |
getText | getPageText |
App | PressContext |
middleware(context, next) | middleware(request, next) |
transformPage(page, data) | transformPage(data, { page }) |
Last updated on