بنقرة واحدة
fumadocs-deploy
// Build and deploy Fumadocs documentation sites, supporting static export, PDF, RSS, and more
// Build and deploy Fumadocs documentation sites, supporting static export, PDF, RSS, and more
Create and configure Fumadocs projects using CLI, selecting frameworks, content sources, and UI components
Build documentation sites using Headless components library, including navigation, TOC, search API, and content collections
Configure internationalization support for Fumadocs, including multi-language routing and content organization
Configure and manage Fumadocs MDX content collections, including schema definition, type generation, and file imports
Configure and integrate document search engines for Fumadocs, supporting Orama, Algolia, Mixedbread, and other solutions
Customize documentation appearance and layouts using Fumadocs UI theme and component library
| name | Fumadocs Deploy |
| description | Build and deploy Fumadocs documentation sites, supporting static export, PDF, RSS, and more |
Build and deploy documentation sites.
Create or modify next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true,
},
trailingSlash: true,
};
module.exports = nextConfig;
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true,
},
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback = { fs: false };
}
return config;
},
};
module.exports = nextConfig;
npm run build
npm run start
Static files will be generated in the out/ directory:
out/
├── index.html
├── docs/
│ ├── index.html
│ ├── guide/
│ │ └── getting-started.html
│ └── api/
│ └── users.html
├── static/
│ ├── _next/
│ └── images/
└── 404.html
Create app/api/pdf/[slug]/route.ts:
import { pdf } from '@react-pdf/renderer';
import { source } from '@/lib/source';
export async function GET(
request: Request,
{ params }: { params: { slug: string } }
) {
const page = source.getPage(`/docs/${params.slug}`);
if (!page) {
return new Response('Page not found', { status: 404 });
}
const element = <MyDocument page={page} />;
const blob = await pdf(element).toBlob();
return new Response(blob, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': `attachment; filename="${page.data.title}.pdf"`,
},
});
}
import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer';
const styles = StyleSheet.create({
page: {
padding: 40,
},
title: {
fontSize: 24,
marginBottom: 20,
fontWeight: 'bold',
},
content: {
fontSize: 12,
lineHeight: 1.5,
},
});
interface MyDocumentProps {
page: any;
}
function MyDocument({ page }: MyDocumentProps) {
return (
<Document>
<Page style={styles.page}>
<Text style={styles.title}>{page.data.title}</Text>
<View style={styles.content}>
<Text>{page.data.description}</Text>
</View>
</Page>
</Document>
);
}
import { PDFDownloadLink } from '@react-pdf/renderer';
<PDFDownloadLink
document={<MyDocument page={page} />}
filename={`${page.data.title}.pdf`}
>
{({ loading }) => loading ? 'Loading...' : 'Download PDF'}
</PDFDownloadLink>
Create app/rss/route.ts:
import { source } from '@/lib/source';
export async function GET() {
const pages = source.getPageList().filter(p => p.data.published);
const feed = {
title: 'My Documentation',
link: 'https://example.com',
description: 'Documentation for my project',
language: 'en',
lastBuildDate: new Date().toUTCString(),
items: pages
.sort((a, b) => b.data.date.localeCompare(a.data.date))
.map(p => ({
title: p.data.title,
link: `https://example.com${p.url}`,
date: p.data.date,
description: p.data.description,
author: p.data.author,
})),
};
return new Response(feed.toString(), {
headers: { 'Content-Type': 'application/xml' },
});
}
<link
rel="alternate"
type="application/rss+xml"
title="Documentation RSS"
href="/rss"
/>
import { RSS } from 'rss';
export async function GET() {
const feed = new RSS({
title: 'My Documentation',
description: 'Documentation for my project',
feed_url: 'https://example.com/rss',
site_url: 'https://example.com',
});
const pages = source.getPageList().filter(p => p.data.published);
pages.forEach(p => {
feed.item({
title: p.data.title,
url: `https://example.com${p.url}`,
date: p.data.date,
description: p.data.description,
});
});
return new Response(feed.xml({ indent: true }), {
headers: { 'Content-Type': 'application/xml' },
});
}
export const pages = source.getPageList().filter(page => {
const role = page.data.role;
return role === 'public' || userRole === role;
});
import { getServerSession } from 'next-auth';
import { source } from '@/lib/source';
export async function GET(request: Request) {
const session = await getServerSession();
if (!session?.user) {
return new Response('Unauthorized', { status: 401 });
}
const pages = source.getPageList();
return new Response(JSON.stringify(pages));
}
Create vercel.json:
{
"buildCommand": "npm run build",
"outputDirectory": "out",
"framework": null,
"installCommand": "npm install"
}
Deploy:
vercel --prod
Create netlify.toml:
[build]
publish = "out"
command = "npm run build"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Deploy:
netlify deploy --prod --dir=out
Modify package.json:
{
"scripts": {
"export": "npm run build"
}
}
Create index.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=/docs" />
</head>
<body>
Redirecting to documentation...
</body>
</html>
Create wrangler.toml:
name = "my-docs"
compatibility_date = "2024-01-01"
[site]
bucket = "./out"
Deploy:
npx wrangler pages deploy ./out
Create .env.production:
NEXT_PUBLIC_BASE_URL=https://example.com
// next.config.js
const nextConfig = {
output: 'export',
compress: true,
};
module.exports = nextConfig;
const nextConfig = {
output: 'export',
headers: [
{
source: '/(.*)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
],
};
module.exports = nextConfig;
Reference Documentation: