Fumadocs
문서 프레임워크 based on Next.js
설치
pnpm create fumadocs-app docs
cd docs
pnpm devdocs 폴더를 루트로 이동
Next.js의 Route Groups (괄호 폴더) 기능을 활용
1. Route Group 적용 ((docs) 폴더 생성)
app/docs 폴더의 이름을 app/(docs)로 변경하세요. 폴더명에 괄호를 붙이면 Next.js는 이를 "경로 계산에 포함하지 않는 그룹"으로 인식합니다.
- 기존 구조:
app/docs/[[...slug]]/page.tsx→ URL:localhost/docs/... - 변경 구조:
app/(docs)/[[...slug]]/page.tsx→ URL:localhost/...
이렇게 하면 실제 파일은 (docs) 폴더 안에 안전하게 보관되지만, 브라우저 주소창에서는 docs라는 글자가 사라집니다.
2. Fumadocs 로더 설정 업데이트
URL 구조가 바뀌었으므로 lib/source.ts 파일에서 baseUrl을 수정해줘야 링크들이 깨지지 않습니다.
// lib/source.ts
export const source = loader({
// 이제 루트('/')에서 문서가 시작됨을 명시합니다.
baseUrl: "/",
// 실제 콘텐츠(MDX)가 들어있는 폴더 경로는 그대로 둡니다.
rootDir: "docs",
source: createMdxfmSource(map),
})3. Middleware 또는 Redirect 설정 (권장)
기존에 /docs/... 주소로 접속하던 사용자가 있을 수 있으므로, next.config.mjs에서 리다이렉트를 걸어주는 것이 좋습니다.
/** @type {import('next').NextConfig} */
const nextConfig = {
async redirects() {
return [
{
source: "/docs/:path*",
destination: "/:path*",
permanent: true, // SEO를 위해 301 리다이렉트
},
]
},
}폴더별 사이드바
Fumadocs v16+ 버전에서 폴더별로 독립된 사이드바를 만드는 가장 깔끔한 방법은 meta.json의 root 설정을 활용하는 것입니다. source.ts를 복잡하게 수정할 필요 없이 아래 3단계만 확인하면 됩니다.
1. 폴더별 meta.json 설정
각 폴더가 독립된 사이드바의 시작점(Root)임을 선언합니다. 이 설정이 있어야 해당 폴더 진입 시 다른 폴더들이 사이드바에서 사라집니다.
- content/(docs)/A/meta.json
{
"title": "A 프로젝트",
"root": true
}- content/(docs)/B/meta.json
{
"title": "B 프로젝트",
"root": true
}2. app/(docs)/layout.tsx 설정
DocsLayout의 sidebar.tabs에 각 폴더의 경로를 등록합니다. 사용자가 이 탭을 클릭하거나 해당 URL로 접속하면 Fumadocs가 자동으로 사이드바를 교체합니다.
import { source } from "@/lib/source";
import { DocsLayout } from "fumadocs-ui/layout";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<DocsLayout
tree={source.pageTree}
sidebar={{
tabs: [
{
title: "전체 문서",
url: "/", // 루트 경로 (모든 폴더 노출)
},
{
title: "A 프로젝트",
url: "/A", // 클릭 시 /A 폴더 내용만 노출
},
{
title: "B 프로젝트",
url: "/B", // 클릭 시 /B 내용만 노출
},
],
}} >
{children}
</DocsLayout>
);
}- source.ts (기본 유지) collections/server를 사용하는 현재의 깔끔한 상태를 유지하면 됩니다. pageTree 관련 복잡한 코드는 생략 가능합니다.
export const source = loader({
baseUrl: "/",
source: docs.toFumadocsSource(),
plugins: [lucideIconsPlugin()],
});요약
- root: true: 사이드바를 해당 폴더 기준으로 격리시키는 스위치입니다.
- tabs: 사용자가 격리된 사이드바 사이를 이동하게 해주는 버튼입니다.
- 자동화: Fumadocs가 현재 URL을 인식해 root 폴더를 찾아 사이드바를 갈아끼워 줍니다.