Fumadocs

Export EPUB

Export your documentation to EPUB format for e-readers

Introduction

The EPUB integration lets you export your Fumadocs documentation as an EPUB file, making it easy for readers to download and read your docs on e-readers, tablets, or any EPUB-compatible app.

It converts your MDX content to HTML, resolves images, and produces a standards-compliant EPUB with a table of contents.

Setup

Fumadocs CLI can set it up for you, it creates the export route protected by an EXPORT_SECRET and enables includeProcessedMarkdown:

npx @fumadocs/cli feature epub

Or manually:

Installation

npm install fumadocs-epub

Enable Processed Markdown

EPUB export requires includeProcessedMarkdown in your docs collection config:

source.config.ts
import { defineDocs } from 'fumadocs-mdx/config';

export const docs = defineDocs({
  docs: {
    postprocess: {
      includeProcessedMarkdown: true,
    },
  },
});

Create Export Route

createEpubExportAPI builds the route handler. It is guarded by secret: without a matching Authorization: Bearer <secret> header the request is rejected, and the route answers 503 when the secret itself is unset.

app/export/epub/route.ts
import { source } from '@/lib/source';
import { createEpubExportAPI } from 'fumadocs-epub';

export const revalidate = false;

export const { GET } = createEpubExportAPI({
  source,
  title: 'My Documentation',
  author: 'My Team',
  description: 'Documentation for my project',
  cover: '/cover.png',
  secret: process.env.EXPORT_SECRET,
});

For a public endpoint, or to build the file yourself (e.g. in a script), call exportEpub() directly and return the buffer.

Using the CLI

You can also export EPUB via the Fumadocs CLI:

fumadocs export epub --framework next
# or: astro | tanstack-start | react-router | waku

This fetches from your running server (Next.js) or copies from the build output (other frameworks). Run a production build first for non-Next.js frameworks.

Options

Both exportEpub and createEpubExportAPI accept these options:

OptionTypeDescription
titlestringRequired. Book title
authorstring | string[]Author name(s). Default: 'anonymous'
descriptionstringBook description
languagestringLanguage code (e.g. 'en'). Default: 'en'
publisherstringPublisher name. Default: 'anonymous'
isbnstringISBN
coverstringCover image. Supports file://, http(s)://, /public/..., or relative paths
outputPathstringIf set, writes the EPUB to file in addition to returning the buffer
includePages(page) => booleanFilter: include only pages where this returns true
excludePages(page) => booleanFilter: exclude pages where this returns true
cssstringCustom CSS for the EPUB. Uses defaultEpubStyles if omitted
publicDirstringPublic directory for resolving /public/... image paths. Default: ./public

createEpubExportAPI adds two more: secret (required, guards the route) and filename (the downloaded file name, default docs.epub).

Custom CSS

You can override the default EPUB styles:

import { exportEpub, defaultEpubStyles } from 'fumadocs-epub';

const buffer = await exportEpub({
  source,
  title: 'My Docs',
  author: 'Me',
  css: `${defaultEpubStyles}
/* Custom overrides */
body { font-size: 1.1em; }
`,
});

Filtering Pages

Use includePages and excludePages to control which docs are exported:

const buffer = await exportEpub({
  source,
  title: 'My Docs',
  author: 'Me',
  // Only include docs under /docs/getting-started
  includePages: (page) => page.path.startsWith('getting-started'),
  // Exclude specific paths
  excludePages: (page) => page.path === 'changelog',
});

Image Resolution

Images in your MDX are resolved automatically:

  • Relative paths (e.g. ./image.png) — resolved relative to the page file
  • Public paths (e.g. /og.png) — resolved from the public directory
  • Remote URLs (e.g. https://...) — embedded as-is

How is this guide?

Last updated on

On this page