Orientation
Content Processing
Search Infrastructure
Rendering and UI
Developer Tooling
How It Works
The following files were used as context for generating this wiki page:
The EPUB Exporter is a dedicated subsystem for converting Fumadocs documentation into the standard EPUB format. By transforming Markdown/MDX content into semantic HTML and packaging it according to the IDPF EPUB 3 specification, it allows users to consume documentation offline or on dedicated e-readers, bridging the gap between web-based documentation and portable digital book formats.
The exporter acts as an adapter, taking the source object provided by Fumadocs loaders and navigating the site structure to ensure the EPUB's Table of Contents (TOC) mirrors the logical navigation tree of the documentation. This ensures a coherent reading experience, preserving hierarchy and ordering defined in the site metadata.
At its architectural core, the exporter relies on epub-gen-memory to construct the EPUB bundle in memory, avoiding unnecessary filesystem I/O during the compilation phase. It employs a post-processing pipeline that transforms Markdown to HTML, resolving relative image paths and applying default styles, making it highly configurable for developers who need to customize the aesthetic or inclusion criteria of their exported books.
exportEpubThe exportEpub function is the primary entry point, orchestrating the document collection and conversion process. It accepts an EpubExportOptions object, which requires a Fumadocs source and various metadata (title, author, publisher).
import { exportEpub } from 'fumadocs-epub';
import { source } from '@/lib/source';
const buffer = await exportEpub({
source,
title: 'My Documentation',
author: 'My Team',
cover: '/cover.png',
});Sources: packages/epub/src/index.ts:64-150
To generate a sensible EPUB, the exporter must respect the documentation’s navigation structure. The system utilizes getPagesInTreeOrder, which recursively flattens the page tree to establish the order of chapters. If the tree contains no navigation items (common in multi-language setups), the exporter falls back to the flat list provided by source.getPages().
Note
The order of pages in the EPUB is dictated by the site's navigation tree structure. If a page is not part of the tree, it is relegated to the fallback logic, which may not maintain the intended sequence.
Sources: packages/epub/src/index.ts:92-99, packages/epub/src/toc-builder.ts:5-25
The transformation pipeline is handled by markdownToHtml, which uses a unified processor to sanitize and convert raw MDX content. A custom remark plugin remarkResolveImg is injected into the pipeline. This plugin visits all image nodes in the Markdown AST, invoking resolveImageSrc to convert local or relative path references into absolute URLs or file:// URIs, ensuring that images within the EPUB display correctly regardless of the reader's environment.
Sources: packages/epub/src/markdown-to-html.ts:10-37
The CLI command export-epub manages the lifecycle of the generation process, especially for frameworks like Next.js that do not generate static files. It includes a scaffolding feature that creates a dedicated API route (/export/epub/route.ts) within the user's project, protected by an EXPORT_SECRET.
Sources: packages/cli/src/commands/export-epub.ts:27-169
The exporter implements robust logic to resolve cover images and embedded images. resolveCoverPath distinguishes between remote URLs, absolute paths in the public directory, and relative paths based on the current working directory (cwd). By mapping paths to file URLs, the exporter guarantees that epub-gen-memory can successfully pull the resources into the archive.
Caution
If a file is not found, the image resolution logic will splice the image node out of the document entirely during the remark processing phase, preventing broken image placeholders in the final EPUB.
Sources: packages/epub/src/index.ts:26-39, packages/epub/src/markdown-to-html.ts:32-34
The epubOptions struct maps internal options to the generator's format. A critical design decision is the use of prependChapterTitles: true and numberChaptersInTOC: true. These are enabled by default because Fumadocs content often relies on existing heading hierarchy, and forcing these titles into the EPUB's explicit TOC facilitates easier navigation in standard e-readers that might not interpret nested HTML structure as deeply as a web browser.
Sources: packages/epub/src/index.ts:124-135