Skip to Content
Migrate

Upgrade to Fumapress 2

Move a Fumapress 1.x site to version 2.

Fumapress 2 replaces defineConfig() with createPress(). By default, the render mode of each page now matches its content source, so one site can have both prerendered and dynamic pages. Do the steps in order, then open the sections for the features your site uses.

Coming from 0.x, follow Upgrade to Fumapress 1 first.

Upgrade Steps

Update the Packages

Fumapress 2 needs Node.js 24 or later. Update Fumapress, Fumadocs, React and Vite together, and any @fumapress/* plugins that you use.

npm i fumapress@latest react@latest react-dom@latest
npm i fumadocs-core@latest fumadocs-mdx@latest
npm i fumadocs-ui@npm:@fumadocs/base-ui@latest
npm i vite@latest -D

Fumapress 2 needs the Base UI build of Fumadocs UI, which the third line installs as fumadocs-ui. Coming from the Radix UI build, your own code only changes where it passes Radix props like asChild to Fumadocs UI components.

Fumapress 2 installs @fumapress/core, and some plugins moved to @fumapress/*, like @fumapress/blog. If your package manager holds back new releases, like with the minimumReleaseAge setting of pnpm, exclude @fumapress/* from it.

If your package.json lists react-server-dom-webpack, uninstall it. A copy that you list replaces the one that matches the React version of Fumapress.

Rewrite the Config

content and i18n go to createPress(). Plugins go to .plugins(), called once. Everything else goes to .config().

The fields of loaderOptions also go to createPress(), without the loaderOptions wrapper. Rename plugins to loaderPlugins.

press.config.tsx
import { defineConfig } from "fumapress";
import { fumadocsMdx } from "fumapress/adapters/mdx";
import { createPress } from "fumapress";

export default defineConfig({
  content: docs.toFumadocsSource(),
  loaderOptions: { plugins: [lucideIconsPlugin()] },
  site: { name: "My Docs" },
})
  .adapters(fumadocsMdx())
  .plugins(linkValidationPlugin());
export const app = createPress(docs.toFumadocsSource(), {
  loaderPlugins: [lucideIconsPlugin()],
}).plugins(linkValidationPlugin());

export default app.config({ site: { name: "My Docs" } });

Delete the .adapters(fumadocsMdx()) call. MDX pages now render without it.

Update the Schema Import

press.config.tsx
import { metaSchema, pageSchema } from "fumapress/adapters/mdx/schema";
import { metaSchema, pageSchema } from "fumapress/schema";

Run the Site

npm run dev

If you didn't customize your site, you're done. To find the other changes, search your project for imports from fumapress/ and for the options you set, then open the matching sections below.

Site Options

Open the options your site sets.

Plugins

Open the plugins your site uses.

Custom Plugins

Start with the type and the hooks that create routes. This plugin has a page, a generated file and a response header:

acme/index.tsx
import type { AppShape, PressPlugin } from "fumapress";

export function statusPlugin<C extends AppShape = AppShape>(): PressPlugin<C> {
  return {
    name: "acme:status",
    createPages({ createPage, createApiIsomorphic }) {
      createPage({
        path: "/status",
        render: "static",
        component: () => <p>OK</p>,
      });
      createApiIsomorphic({
        path: "/status.json",
        render: "static",
        handler: async () => Response.json({ ok: true }),
      });
    },
    createMiddlewares() {
      return [
        async (c, next) => {
          await next();
          c.header("x-powered-by", "acme");
        },
      ];
    },
  };
}

Then rename these APIs:

1.x2.0
AppContextPressContext
core:get-bodygetPageBody
core:get-textgetPageText
core:render-tocgetPageToc
core:get-structured-datagetPageStructuredData
core:get-creation-dategetPageCreatedAt
core:get-modified-dategetPageLastModified
unstable_onServerEntrywaku.unstable_serverEntry

enforce is removed, since plugins run in list order. preinit is removed: to replace a default plugin, the site sets it to false in recommendedPreset(). this.mode becomes this.getContentRender().

These need more than a rename:

Last updated on

On this page