Turn your Markdown into a documentation site.
Fumapress is a site generator for docs, blogs and API references, offering a polished theme, search and other features with zero configuration.
Only the writing is left to you.
Each file you write becomes a page, and each folder a chapter in the sidebar. There are no routes to wire and no layouts to keep in step.
When words alone fall short, MDX lets you set a React component between the lines.
Publish content from any source as one site.
Keep pages as files in your repository, or fetch them from Notion, Obsidian, Sanity or a source of your own. Fumapress serves each source under its own path.
from Notion
/guides
from Obsidian
/notes
from Sanity
/blog
export default createPress({
docs: docs.toFumadocsSource({ baseDir: "docs" }),
guides: notion.dynamicSource({ baseDir: "guides" }),
// a vault and a Sanity dataset join the same way
}).plugins(notionPlugin({ notion }));It looks finished on day one, and stays yours to change.
Every page is built on Fumadocs UI, a design already refined on many documentation sites, with dark mode and phone layouts included. Pick a layout and a color theme, and there is nothing left to design.
When you want your own design, the Fumadocs CLI installs any component or layout into your project, where its source is yours to edit.
When your docs grow, the site grows with them.
A blog for your news, a changelog for your releases, an AI that answers from your pages, a reference drawn from your API spec. Each is one plugin away.
Turn a content collection into blog posts, an index and tag pages.
press.config.tsx
import { createPress } from "fumapress";
import { blogPlugin } from "@fumapress/blog";
import { defineDocs } from "fumadocs-mdx/macro";
const docs = defineDocs({
dir: "content/docs",
docs: { async: true },
});
const blog = defineDocs({
dir: "content/blog",
docs: { async: true },
});
export default createPress({
docs: docs.toFumadocsSource(),
blog: blog.toFumadocsSource({ baseDir: "blog" }),
}).plugins(blogPlugin({ source: "blog" }));Try it here before you install anything.
Settings
Appearance
Features
Details
import { createPress } from "fumapress";import { defineDocs } from "fumadocs-mdx/macro";import { createOpenAPI } from "fumadocs-openapi/server";import openapiPlugin from "fumadocs-openapi/press";import { DocsLayout } from "fumadocs-ui/layouts/docs";import { DocsBody, DocsDescription, DocsPage, DocsTitle,} from "fumadocs-ui/layouts/docs/page"; const docs = defineDocs({ dir: "content/docs" });const openapi = createOpenAPI({ input: ["./openapi.json"] }); export default createPress({ docs: docs.toFumadocsSource(), openapi: await openapi.staticSource(),}) .plugins( openapiPlugin({ server: openapi }), ) .config({ site: { name: "Acme Docs" }, ui: { renderPage(props) { const { renderDefault } = props; if (props.type !== "docs" && props.type !== "openapi") return renderDefault(); const { layoutProps, pageData, toc, body, slots } = props; return ( <DocsLayout {...layoutProps}> <DocsPage toc={toc} full={pageData.full}> <DocsTitle>{pageData.title}</DocsTitle> <DocsDescription>{pageData.description}</DocsDescription> <div className="flex gap-2"> {slots["core:markdown"]?.element} {slots["core:view-options"]?.element} </div> <DocsBody>{body}</DocsBody> </DocsPage> </DocsLayout> ); }, }, });Your first page is one command away.
Waku
Quick StartCustom pages are React Server Components.
Astro
Quick StartCustom pages are .astro files with React islands.
Welcome to Fumapress