Skip to content

Migrate documentation site to Fumadocs with monorepo structure and shared content#11

Merged
hotlong merged 11 commits intomainfrom
copilot/setup-fumadocs-site
Jan 19, 2026
Merged

Migrate documentation site to Fumadocs with monorepo structure and shared content#11
hotlong merged 11 commits intomainfrom
copilot/setup-fumadocs-site

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 18, 2026

Replace the custom @objectdocs/cli documentation tooling with Fumadocs, a modern Next.js-based documentation framework, and restructure it into a proper monorepo architecture under apps/docs/ while keeping documentation content at the root level for sharing.

Changes

Monorepo Structure

  • Multi-package Architecture: Moved all Next.js files to apps/docs/ to avoid polluting the root directory
  • Workspace Isolation: Documentation site now has its own package.json with isolated dependencies
  • Clean Separation: Clear boundary between protocol packages (packages/*) and applications (apps/*)
  • Shared Content: Documentation content remains at /content/docs/ (root level) for easy access and sharing across the repository

Core Infrastructure

  • Next.js 16 + App Router: Full static site generation for 136 documentation pages
  • Fumadocs MDX: Auto-compilation from /content/docs/ (root level) with type-safe collection handling
  • Tailwind CSS v4: New CSS architecture with @tailwindcss/postcss

Directory Structure

Repository Root:
├── content/docs/     # Documentation content (MDX files) - SHARED LOCATION
│   ├── concepts/
│   ├── references/
│   └── specifications/
└── apps/docs/
    ├── app/              # Next.js App Router
    ├── source.config.ts  # Fumadocs collection config (references ../../content/docs)
    ├── next.config.mjs   # Next.js configuration
    ├── tailwind.config.js
    ├── postcss.config.mjs
    ├── tsconfig.json
    └── package.json      # Isolated dependencies

Configuration

// apps/docs/source.config.ts - Collection definition
export const docs = defineDocs({
  dir: '../../content/docs',  // References root-level content
}) as any; // Workaround for pnpm zod@4 type portability

// apps/docs/app/source.ts - Loader setup
import { docs } from 'fumadocs-mdx:collections/server';
export const source = loader({
  baseUrl: '/docs',
  source: (docs as any).toFumadocsSource(),
});

UI Components

  • Collapsible sidebar with auto-generated navigation from meta.json files
  • Search (⌘K), theme toggle, GitHub integration
  • MDX components (Callout, Card, Cards) rendered via fumadocs-ui/mdx

Build Output

Route (app)
├ ○ /
└ ● /docs/[[...slug]] (136 pages)
  ├ /docs
  ├ /docs/concepts/*
  ├ /docs/references/*
  └ /docs/specifications/*

Workspace Configuration

  • Updated pnpm-workspace.yaml to include apps/*
  • Root package.json scripts use workspace filters: pnpm --filter @objectstack/docs
  • Root package.json includes shared dependencies (lucide-react) used by MDX files
  • Root tsconfig.json excludes apps directory
  • .gitignore updated for apps structure

Screenshot

Scripts

Scripts remain the same from repository root:

pnpm docs:dev    # Start development server
pnpm docs:build  # Build for production
pnpm docs:start  # Start production server

Benefits

  1. Clean Root Directory: No Next.js files in repository root
  2. Shared Content: Documentation content at /content/docs/ accessible to other tools and workflows
  3. Workspace Isolation: Each app/package manages its own dependencies
  4. Scalability: Easy to add more apps (e.g., apps/playground, apps/studio)
  5. Standard Pattern: Follows Turborepo/Nx monorepo conventions
  6. Maintainability: Clear separation of concerns

All existing MDX content preserved at the root level. The .source/ directory (auto-generated by Fumadocs) is gitignored.

Original prompt

帮我使用fumadocs搭建此文档站点


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
spec Error Error Jan 19, 2026 5:28am

Request Review

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
…rver

Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
Copilot AI changed the title [WIP] Add setup for Fumadocs documentation site Migrate documentation site from custom @objectdocs/cli to Fumadocs Jan 18, 2026
Copilot AI requested a review from huangyiirene January 18, 2026 17:46
@hotlong
Copy link
Copy Markdown
Collaborator

hotlong commented Jan 19, 2026

@copilot nextjs项目使用多包架构放到apps/docs,不要污染根目录

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot nextjs项目使用多包架构放到apps/docs,不要污染根目录

Done! The Next.js documentation site has been moved to apps/docs/ following monorepo best practices.

Changes:

  • ✅ All Next.js files moved to apps/docs/
  • ✅ Documentation content now in apps/docs/content/
  • ✅ Root directory cleaned up
  • ✅ Workspace configuration updated
  • ✅ Scripts still work from root: pnpm docs:dev, pnpm docs:build

See commit 3124fe9 for the complete restructuring.

Documentation Site

Copilot AI changed the title Migrate documentation site from custom @objectdocs/cli to Fumadocs Migrate documentation site to Fumadocs with monorepo structure (apps/docs) Jan 19, 2026
Copilot AI requested a review from hotlong January 19, 2026 01:02
@hotlong
Copy link
Copy Markdown
Collaborator

hotlong commented Jan 19, 2026

@copilot 我的文档还是放在很目录,不要换位置 /content/docs

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot 我的文档还是放在很目录,不要换位置 /content/docs

Done! Documentation content is now kept at the root directory /content/docs/ as requested.

Changes:

  • ✅ Content moved back to /content/docs/ (root level)
  • apps/docs/source.config.ts updated to reference ../../content/docs
  • lucide-react added to root dependencies (required by MDX files)
  • ✅ Build verified: All 136 pages generated successfully

The Next.js app remains in apps/docs/ but references the shared content at the root. This provides the best of both worlds: clean app structure while keeping content accessible at the root level.

See commit c60ebe7 for the changes.

Documentation Site

Copilot AI changed the title Migrate documentation site to Fumadocs with monorepo structure (apps/docs) Migrate documentation site to Fumadocs with monorepo structure and shared content Jan 19, 2026
…mprove documentation formatting, and refine build scripts
Moved reference .mdx files into protocol-based subdirectories (data, ui, system, ai, misc) and added meta.json files for each category. Updated build-docs.ts to generate documentation into these new directories and to update meta.json for navigation. This improves organization and navigation of API reference documentation.
@hotlong hotlong marked this pull request as ready for review January 19, 2026 05:29
Copilot AI review requested due to automatic review settings January 19, 2026 05:29
@hotlong hotlong merged commit 2984aaa into main Jan 19, 2026
5 of 7 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the documentation site from a custom @objectdocs/cli tooling to Fumadocs, a modern Next.js-based documentation framework, while restructuring the repository into a proper monorepo architecture. The documentation content remains at the root level (/content/docs/) for sharing, while the Next.js application is cleanly isolated in apps/docs/.

Changes:

  • Replaced custom documentation CLI with Fumadocs + Next.js 16
  • Restructured to monorepo with apps/docs/ containing the site and /content/docs/ containing shared MDX content
  • Updated build scripts to categorize auto-generated schema documentation by protocol (data, ui, system, ai)
  • Removed duplicate H1 headings from MDX files (now handled by page layout)
  • Added proper workspace configuration with isolated dependencies

Reviewed changes

Copilot reviewed 157 out of 160 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pnpm-workspace.yaml Added apps/* to workspace packages
package.json Updated scripts to use workspace filters, moved dependencies to appropriate locations
tsconfig.json Excluded apps and packages directories from root TypeScript config
apps/docs/**/* New Next.js 16 documentation site with Fumadocs integration
packages/spec/scripts/build-docs.ts Enhanced to categorize generated docs by protocol type
content/docs/**/*.mdx Removed duplicate H1 titles, escaped inline code with braces
content/docs/references/*/meta.json Added category metadata for navigation
.gitignore Added Next.js and Fumadocs specific ignores
pnpm-lock.yaml Removed @objectdocs/cli, added Fumadocs dependencies
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread apps/docs/app/page.tsx
</div>

<h1 className="text-4xl font-extrabold tracking-tight sm:text-6xl md:text-7xl bg-gradient-to-br from-foreground to-foreground/60 bg-clip-text text-transparent pb-2">
The Post-SaaS <br/> Operatings System
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error: "Operatings" should be "Operating". This is a critical typo in the main heading of the homepage.

Suggested change
The Post-SaaS <br/> Operatings System
The Post-SaaS <br/> Operating System

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +48
// 1. Scan source files to build map
Object.keys(CATEGORIES).forEach(category => {
const dir = path.join(SRC_DIR, category);
if (fs.existsSync(dir)) {
const files = fs.readdirSync(dir).filter(f => f.endsWith('.ts'));
for (const file of files) {
const content = fs.readFileSync(path.join(dir, file), 'utf-8');

// Regex to find exported const schemas (e.g. "export const ObjectSchema = ...")
// also matches "export const ObjectCapabilities = ..."
// We assume conventions are followed
const matches = content.matchAll(/export const (\w+)(?:Schema)?\s*=\s*z\./g);
for (const match of matches) {
// match[1] is the name (e.g. Object).
// Note: build-schemas.ts strips 'Schema' suffix.
// We match (\w+) which captures 'ObjectSchema' or 'ObjectCapabilities'.
// logic in build-schemas: `key.endsWith('Schema') ? key.replace('Schema', '') : key`

let schemaName = match[1]; // e.g. Object from ObjectSchema
if (!content.includes(`export const ${schemaName}Schema =`)) {
// Wait, regex above captures "Object" from "ObjectSchema" IF I put Schema in non-capturing group?
// No, (\w+) captures "ObjectSchema". (?:Schema)? is applied to verify/consume suffix but regex is tricky.
// Simplified regex: /export const (\w+)\s*=/
// Then apply naming logic.
}
}
}
}
});
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code: Lines 20-48 contain commented-out or incomplete code that was replaced by the scanCategories function starting at line 50. This dead code should be removed to improve maintainability and avoid confusion.

Copilot uses AI. Check for mistakes.

export const docs = defineDocs({
dir: '../../content/docs',
}) as any;
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type safety issue: The use of as any on line 5 bypasses TypeScript's type checking. The PR description mentions this is a "workaround for pnpm zod@4 type portability", but this defeats the purpose of TypeScript and could hide type errors. Consider finding a proper solution or at least adding a detailed comment explaining why this workaround is necessary and tracking it for future removal.

Suggested change
}) as any;
});

Copilot uses AI. Check for mistakes.
Comment thread apps/docs/app/source.ts

export const source = loader({
baseUrl: '/docs',
source: (docs as any).toFumadocsSource(),
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type safety issue: Another use of as any that bypasses TypeScript type checking. This is consistent with the workaround in source.config.ts but should be properly addressed or documented.

Suggested change
source: (docs as any).toFumadocsSource(),
// @ts-expect-error: fumadocs-mdx virtual module typings do not currently expose `toFumadocsSource`
source: docs.toFumadocsSource(),

Copilot uses AI. Check for mistakes.
if (!fs.existsSync(DOCS_DIR)) {
fs.mkdirSync(DOCS_DIR, { recursive: true });
// 2. Prepare Directories
const miscDir = path.join(DOCS_ROOT, 'misc');
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable miscDir.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants