Fumadocs v15

Tailwind CSS v4

Back

Overview

The purpose of v15 is mainly to support Tailwind CSS v4. Tailwind CSS v4 is a complete redesign of its API and internals, to fully adhere the new CSS-first config style, a breaking change is required.

Fumadocs v15 has no other significant changes than migrating the config to Tailwind CSS v4.

Breaking Changes

Before making the switch, upgrade your site to Tailwind CSS v4 following their upgrade guide. You can remove the unused tailwind.config.js file and fully rely on the new CSS-first config.

Add @import to the presets exported by Fumadocs UI, and include fumadocs-ui package into source.

Tailwind CSS
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
 
/* relative to the CSS file, make sure it's correct for your app */
@source '../node_modules/fumadocs-ui/dist/**/*.js';

Since v15, you will no longer pass options in JavaScript to customise plugins. Instead, you can use the new alternatives in Tailwind CSS v4.

addGlobalColors: true

Forward the colors again:

@theme {
  --color-primary: var(--color-fd-primary);
  /* same for other colors */
}

CSS Variables

Fumadocs no longer use --fd-<color> like --fd-primary: 0 0% 0% for colors, it directly defines and uses colors in @theme. Instead of the previous format, it uses hsl():

@theme {
  --color-fd-primary: hsl(0, 0%, 100%);
}

Steps

Previous Tailwind CSS utilities like steps & steps are renamed to fd-steps and fd-step to avoid conflicts.

Typography

Typography utilities including prose, prose-* modifiers will continue to work. Please report problems if they are no longer working or have unexpected change in behaviours.

Improvements

v15 also included some minor improvements to the UI and OpenAPI integration.

Code Block Tabs

In the past, you need to write the <Tabs /> manually when separating code blocks into tabs.

<Tabs items={["Tab 1", "Tab 2"]}>
 
```ts tab="Tab 1"
console.log('Hello World');
```
 
```ts tab="Tab 2"
console.log('Hello World');
```
 
</Tabs>

Now you can do:

```ts tab="Tab 1"
console.log('Hello World');
```
 
```ts tab="Tab 2"
console.log('Hello World');
```

Note that the previous usage still works for those who want to customise or pass props to the <Tabs /> component.

Reversed Items in meta.json

The rest item ... in the pages property of meta.json now supports reversed order:

{
  "pages": ["z...a"]
}

OpenAPI Playground

v15 improved the playground UI (inspired by the minimalism of Scalar), and brought Scalar API Client support to Fumadocs OpenAPI.

You can enable the Scalar API Client using useScalar option in createOpenAPI():

import { createOpenAPI } from 'fumadocs-openapi/server';
import { APIPlayground } from 'fumadocs-openapi/scalar';
 
export const openapi = createOpenAPI({
  renderer: {
    APIPlayground,
  },
});

And install & configure their @scalar/api-client-react:

npm install @scalar/api-client-react
global.css
@import '@scalar/api-client-react/style.css' layer(base);

Be careful that you must configure Tailwind CSS first, using the pre-built stylesheet of Fumadocs UI will conflict with their style.css because both libraries use Tailwind CSS for styling.

Future Plans

This update should be a simple migration for most developers updating to Tailwind CSS v4.

In the future, we also want to make further improvements to Fumadocs MDX:

  • remove transform API - you can easily do the same with .map() on runtime like:
import { blog } from "@/.source"
 
export const updatedBlog = blog.map(...)
  • remove Manifest API - it was designed to export search indexes, but now it's recommended to implement using route handlers.

  • Mention more about our MDX Remote package, it will be the primary solution to handle large docs sites with performance needs that bundler couldn't do, including lazy compilation of MDX files.

Written by

Fuma Nama

At

Fri Jan 24 2025