chore: complete fumadocs -> @hanzo/docs rebrand

- Rename all packages from fumadocs-* to @hanzo/docs-*
- Update all imports across apps, examples, and packages
- Update documentation and content references
- Sync lockfile with new package names
This commit is contained in:
2025-12-17 14:49:52 -08:00
parent c673e6ac9e
commit 8ea4ad783e
735 changed files with 4538 additions and 1520 deletions
+90
View File
@@ -0,0 +1,90 @@
name: Deploy Docs to GitHub Pages
# BLOCKING ISSUE: Build fails due to incomplete package migration.
#
# The source files in apps/docs/ still import from:
# - fumadocs-ui (should be @hanzo/docs-ui)
# - fumadocs-core (should be @hanzo/docs-core)
#
# Files needing updates:
# - apps/docs/app/global.css (CSS imports)
# - apps/docs/app/provider.tsx
# - apps/docs/app/layout.tsx
# - apps/docs/app/docs/layout.tsx
# - apps/docs/mdx-components.tsx
# - apps/docs/components/*.tsx
# - apps/docs/scripts/*.ts
# - And ~40+ more files
#
# Additionally, GitHub Pages requires static export which disables:
# - API routes (/api/*)
# - Server-side rendering
# - Dynamic routes without generateStaticParams
#
# For full Next.js functionality, use Vercel or Cloudflare Pages instead.
on:
push:
branches:
- main
paths:
- 'apps/docs/**'
- 'packages/**'
- 'pnpm-lock.yaml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpm build --filter=!docs
- name: Build docs with static export
working-directory: apps/docs
env:
NEXT_OUTPUT: export
run: pnpm build
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: apps/docs/out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
File diff suppressed because one or more lines are too long
+31
View File
@@ -0,0 +1,31 @@
// @ts-nocheck
import { dynamic } from '@hanzo/docs/mdx/runtime/dynamic';
import * as Config from '../source.config';
const create = await dynamic<typeof Config, import("@hanzo/docs-mdx/runtime/types").InternalTypeConfig & {
DocData: {
docs: {
/**
* extracted references (e.g. hrefs, paths), useful for analyzing relationships between pages.
*/
extractedReferences: import("@hanzo/docs-mdx").ExtractedReference[];
},
}
} & {
DocData: {
blog: {
/**
* Last modified date of document file, obtained from version control.
*
*/
lastModified?: Date;
},
docs: {
/**
* Last modified date of document file, obtained from version control.
*
*/
lastModified?: Date;
},
}
}>(Config, {"configPath":"source.config.ts","environment":"next","outDir":".docs"}, {"doc":{"passthroughs":["extractedReferences","lastModified"]}});
+1
View File
@@ -0,0 +1 @@
{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"full":{"type":"boolean"},"_openapi":{"type":"object","properties":{},"additionalProperties":{}},"author":{"type":"string"},"date":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},{}]}},"required":["title","author","date"]}
@@ -0,0 +1 @@
{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"full":{"type":"boolean"},"_openapi":{"type":"object","properties":{},"additionalProperties":{}},"preview":{"type":"string"},"index":{"default":false,"type":"boolean"},"method":{"type":"string"}},"required":["title"]}
@@ -0,0 +1 @@
{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string"},"pages":{"type":"array","items":{"type":"string"}},"description":{"type":"string"},"root":{"type":"boolean"},"defaultOpen":{"type":"boolean"},"collapsible":{"type":"boolean"},"icon":{"type":"string"}}}
File diff suppressed because one or more lines are too long
+119
View File
@@ -0,0 +1,119 @@
// source.config.ts
import {
defineCollections,
defineConfig,
defineDocs,
frontmatterSchema,
metaSchema
} from "@hanzo/docs/mdx/config";
import { z } from "zod";
import jsonSchema from "@hanzo/docs/mdx/plugins/json-schema";
import lastModified from "@hanzo/docs/mdx/plugins/last-modified";
var docs = defineDocs({
docs: {
schema: frontmatterSchema.extend({
preview: z.string().optional(),
index: z.boolean().default(false),
/**
* API routes only
*/
method: z.string().optional()
}),
postprocess: {
includeProcessedMarkdown: true,
extractLinkReferences: true
},
async: true
},
meta: {
schema: metaSchema.extend({
description: z.string().optional()
})
}
});
var blog = defineCollections({
type: "doc",
dir: "content/blog",
schema: frontmatterSchema.extend({
author: z.string(),
date: z.iso.date().or(z.date())
}),
async: true
});
function transformerEscape() {
return {
name: "@shikijs/transformers:remove-notation-escape",
code(hast) {
function replace(node) {
if (node.type === "text") {
node.value = node.value.replace("[\\!code", "[!code");
} else if ("children" in node) {
for (const child of node.children) {
replace(child);
}
}
}
replace(hast);
return hast;
}
};
}
var source_config_default = defineConfig({
plugins: [
jsonSchema({
insert: true
}),
lastModified()
],
mdxOptions: async () => {
const { rehypeCodeDefaultOptions } = await import("@hanzo/docs/core/mdx-plugins/rehype-code");
const { remarkStructureDefaultOptions } = await import("@hanzo/docs/core/mdx-plugins/remark-structure");
const { remarkSteps } = await import("@hanzo/docs/core/mdx-plugins/remark-steps");
const { transformerTwoslash } = await import("@hanzo/docs/twoslash");
const { createFileSystemTypesCache } = await import("@hanzo/docs/twoslash/cache-fs");
const { default: remarkMath } = await import("remark-math");
const { remarkTypeScriptToJavaScript } = await import("@hanzo/docs/docgen/remark-ts2js");
const { default: rehypeKatex } = await import("rehype-katex");
const { remarkAutoTypeTable } = await import("@hanzo/docs/typescript");
return {
remarkStructureOptions: {
types: [...remarkStructureDefaultOptions.types, "code"]
},
rehypeCodeOptions: {
langs: ["ts", "js", "html", "tsx", "mdx"],
inline: "tailing-curly-colon",
themes: {
light: "catppuccin-latte",
dark: "catppuccin-mocha"
},
transformers: [
...rehypeCodeDefaultOptions.transformers ?? [],
transformerTwoslash({
typesCache: createFileSystemTypesCache()
}),
transformerEscape()
]
},
remarkCodeTabOptions: {
parseMdx: true
},
remarkNpmOptions: {
persist: {
id: "package-manager"
}
},
remarkPlugins: [
remarkSteps,
remarkMath,
remarkAutoTypeTable,
remarkTypeScriptToJavaScript
],
rehypePlugins: (v) => [rehypeKatex, ...v]
};
}
});
export {
blog,
source_config_default as default,
docs
};
@@ -2,7 +2,7 @@
import { Check, Share } from 'lucide-react';
import { cn } from '@/lib/cn';
import { buttonVariants } from '@/components/ui/button';
import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';
import { useCopyButton } from '@hanzo/docs/ui/utils/use-copy-button';
export function ShareButton({ url }: { url: string }) {
const [isChecked, onCopy] = useCopyButton(() => {
+25 -11
View File
@@ -1,7 +1,7 @@
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
import { InlineTOC } from '@hanzo/docs/ui/components/inline-toc';
import { blog } from '@/lib/source';
import { createMetadata } from '@/lib/metadata';
import { buttonVariants } from '@/components/ui/button';
@@ -10,36 +10,47 @@ import { getMDXComponents } from '@/mdx-components';
import path from 'node:path';
import { cn } from '@/lib/cn';
// Force dynamic rendering to avoid Turbopack proxy trap issues during SSG
export const dynamic = 'force-dynamic';
export default async function Page(props: PageProps<'/blog/[slug]'>) {
const params = await props.params;
const page = blog.getPage([params.slug]);
if (!page) notFound();
const { body: Mdx, toc } = await page.data.load();
// Create a clean copy of data to avoid proxy trap issues during static generation
// The proxy wrapping by Next.js can cause ownKeys invariant violations
const rawData = page.data as any;
const author = rawData.author;
const date = rawData.date;
const title = rawData.title;
const description = rawData.description;
const loadFn = rawData.load;
const { body: Mdx, toc } = await loadFn();
return (
<article className="flex flex-col mx-auto w-full max-w-[800px] px-4 py-8">
<div className="flex flex-row gap-4 text-sm mb-8">
<div>
<p className="mb-1 text-fd-muted-foreground">Written by</p>
<p className="font-medium">{page.data.author}</p>
<p className="font-medium">{author}</p>
</div>
<div>
<p className="mb-1 text-sm text-fd-muted-foreground">At</p>
<p className="font-medium">
{new Date(
page.data.date ??
path.basename(page.path, path.extname(page.path)),
date ?? path.basename(page.path, path.extname(page.path)),
).toDateString()}
</p>
</div>
</div>
<h1 className="text-3xl font-semibold mb-4">{page.data.title}</h1>
<p className="text-fd-muted-foreground mb-8">{page.data.description}</p>
<h1 className="text-3xl font-semibold mb-4">{title}</h1>
<p className="text-fd-muted-foreground mb-8">{description}</p>
<div className="prose min-w-0 flex-1">
<div className="flex flex-row gap-2 mb-8 not-prose">
<div className="flex flex-row items-center gap-2 mb-8 not-prose">
<ShareButton url={page.url} />
<Link
href="/blog"
@@ -69,10 +80,13 @@ export async function generateMetadata(
if (!page) notFound();
// Extract data properties to avoid proxy trap issues
const data = page.data as any;
const { title, description } = data;
return createMetadata({
title: page.data.title,
description:
page.data.description ?? 'The library for building documentation sites',
title,
description: description ?? 'The library for building documentation sites',
});
}
+31 -20
View File
@@ -1,9 +1,17 @@
import Link from 'next/link';
import { blog } from '@/lib/source';
import { PathUtils } from 'fumadocs-core/source';
import { PathUtils } from '@hanzo/docs/core/source';
import BannerImage from './banner.png';
import Image from 'next/image';
// Blog frontmatter type (matches source.config.ts schema)
interface BlogData {
title: string;
description?: string;
author: string;
date: string | Date;
}
function getName(path: string) {
return PathUtils.basename(path, PathUtils.extname(path));
}
@@ -11,8 +19,8 @@ function getName(path: string) {
export default function Page() {
const posts = [...blog.getPages()].sort(
(a, b) =>
new Date(b.data.date ?? getName(b.path)).getTime() -
new Date(a.data.date ?? getName(a.path)).getTime(),
new Date((b.data as unknown as BlogData).date ?? getName(b.path)).getTime() -
new Date((a.data as unknown as BlogData).date ?? getName(a.path)).getTime(),
);
return (
@@ -25,29 +33,32 @@ export default function Page() {
className="absolute inset-0 size-full -z-1 object-cover"
/>
<h1 className="mb-4 text-3xl text-landing-foreground font-mono font-medium">
Fumadocs Blog
Hanzo Docs Blog
</h1>
<p className="text-sm font-mono text-landing-foreground-200">
Latest announcements of Fumadocs.
Latest announcements and updates.
</p>
</div>
<div className="grid grid-cols-1 gap-2 md:grid-cols-3 xl:grid-cols-4">
{posts.map((post) => (
<Link
key={post.url}
href={post.url}
className="flex flex-col bg-fd-card rounded-2xl border shadow-sm p-4 transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
>
<p className="font-medium">{post.data.title}</p>
<p className="text-sm text-fd-muted-foreground">
{post.data.description}
</p>
{posts.map((post) => {
const data = post.data as unknown as BlogData;
return (
<Link
key={post.url}
href={post.url}
className="flex flex-col bg-fd-card rounded-2xl border shadow-sm p-4 transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground"
>
<p className="font-medium">{data.title}</p>
<p className="text-sm text-fd-muted-foreground">
{data.description}
</p>
<p className="mt-auto pt-4 text-xs text-brand">
{new Date(post.data.date ?? getName(post.path)).toDateString()}
</p>
</Link>
))}
<p className="mt-auto pt-4 text-xs text-brand">
{new Date(data.date ?? getName(post.path)).toDateString()}
</p>
</Link>
);
})}
</div>
</main>
);
+19 -8
View File
@@ -4,33 +4,44 @@ import { NextResponse } from 'next/server';
export const revalidate = false;
const baseUrl = 'https://fumadocs.dev';
// Blog frontmatter type (matches source.config.ts schema)
interface BlogData {
title: string;
description?: string;
author: string;
date: string | Date;
}
const baseUrl = 'https://docs.hanzo.ai';
export function GET() {
const feed = new Feed({
title: 'Fumadocs Blog',
title: 'Hanzo Docs Blog',
id: `${baseUrl}/blog`,
link: `${baseUrl}/blog`,
language: 'en',
image: `${baseUrl}/banner.png`,
favicon: `${baseUrl}/icon.png`,
copyright: 'All rights reserved 2025, Fuma Nama',
copyright: 'All rights reserved 2025, Hanzo AI',
});
for (const page of blog.getPages().sort((a, b) => {
return new Date(b.data.date).getTime() - new Date(a.data.date).getTime();
const aData = a.data as unknown as BlogData;
const bData = b.data as unknown as BlogData;
return new Date(bData.date).getTime() - new Date(aData.date).getTime();
})) {
const data = page.data as unknown as BlogData;
feed.addItem({
id: page.url,
title: page.data.title,
description: page.data.description,
title: data.title,
description: data.description,
link: `${baseUrl}${page.url}`,
date: new Date(page.data.date),
date: new Date(data.date),
author: [
{
name: page.data.author,
name: data.author,
},
],
});
+3 -3
View File
@@ -1,12 +1,12 @@
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { HomeLayout } from '@hanzo/docs/ui/layouts/home';
import { baseOptions, linkItems } from '@/lib/layout.shared';
import {
NavbarMenu,
NavbarMenuContent,
NavbarMenuLink,
NavbarMenuTrigger,
} from 'fumadocs-ui/layouts/home/navbar';
import Link from 'fumadocs-core/link';
} from '@hanzo/docs/ui/layouts/home/navbar';
import Link from '@hanzo/docs/core/link';
import Image from 'next/image';
import Preview from '@/public/banner.png';
import { Book, ComponentIcon, Pencil, PlusIcon, Server } from 'lucide-react';
+2 -2
View File
@@ -569,8 +569,8 @@ function ForEngineers() {
title: 'Fumadocs MDX',
}}
code={`
import { loader } from 'fumadocs-core/source';
import { docs } from 'fumadocs-mdx:collections/server';
import { loader } from '@hanzo/docs/core/source';
import { docs } from '@hanzo/docs-mdx:collections/server';
export const source = loader({
source: docs.toFumadocsSource(),
+1 -1
View File
@@ -12,7 +12,7 @@ import ArkType from '@/public/showcases/arktype.png';
import AssistantUI from '@/public/showcases/assistant-ui.png';
import VisionUI from '@/public/showcases/vision-ui.png';
import Design from './design.png';
import Link from 'fumadocs-core/link';
import Link from '@hanzo/docs/core/link';
import MixSpace from '@/public/showcases/mix-space.png';
import TurboStarter from '@/public/showcases/turbostarter.png';
import Nemo from '@/public/showcases/nemo.png';
+9 -9
View File
@@ -1,8 +1,8 @@
import type { Metadata } from 'next';
import { type ComponentProps, type FC, type ReactNode } from 'react';
import * as Twoslash from 'fumadocs-twoslash/ui';
import { Callout } from 'fumadocs-ui/components/callout';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import * as Twoslash from '@hanzo/docs/twoslash/ui';
import { Callout } from '@hanzo/docs/ui/components/callout';
import { TypeTable } from '@hanzo/docs/ui/components/type-table';
import * as Preview from '@/components/preview';
import { createMetadata, getPageImage } from '@/lib/metadata';
import { source } from '@/lib/source';
@@ -15,22 +15,22 @@ import {
HoverCardContent,
HoverCardTrigger,
} from '@/components/ui/hover-card';
import Link from 'fumadocs-core/link';
import { getPageTreePeers } from 'fumadocs-core/page-tree';
import { Card, Cards } from 'fumadocs-ui/components/card';
import Link from '@hanzo/docs/core/link';
import { getPageTreePeers } from '@hanzo/docs/core/page-tree';
import { Card, Cards } from '@hanzo/docs/ui/components/card';
import { getMDXComponents } from '@/mdx-components';
import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions';
import { Banner } from 'fumadocs-ui/components/banner';
import { Banner } from '@hanzo/docs/ui/components/banner';
import { Installation } from '@/components/preview/installation';
import { Customisation } from '@/components/preview/customisation';
import {
DocsBody,
DocsPage,
PageLastUpdate,
} from 'fumadocs-ui/layouts/docs/page';
} from '@hanzo/docs/ui/layouts/docs/page';
import { NotFound } from '@/components/not-found';
import { getSuggestions } from '@/app/docs/[...slug]/suggestions';
import { PathUtils } from 'fumadocs-core/source';
import { PathUtils } from '@hanzo/docs/core/source';
function PreviewRenderer({ preview }: { preview: string }): ReactNode {
if (preview && preview in Preview) {
+1 -1
View File
@@ -1,4 +1,4 @@
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
import { baseOptions, linkItems, logo } from '@/lib/layout.shared';
import { source } from '@/lib/source';
import {
+4 -4
View File
@@ -1,8 +1,8 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
@import 'fumadocs-twoslash/twoslash.css';
@import 'fumadocs-openapi/css/preset.css';
@import '@hanzo/docs/ui/css/neutral.css';
@import '@hanzo/docs/ui/css/preset.css';
@import '@hanzo/docs/twoslash/twoslash.css';
@import '@hanzo/docs/openapi/css/preset.css';
@plugin 'tailwindcss-animate';
@theme {
+2 -2
View File
@@ -5,9 +5,9 @@ import { Body } from '@/app/layout.client';
import { Provider } from './provider';
import type { ReactNode } from 'react';
import { Geist, Geist_Mono } from 'next/font/google';
import { TreeContextProvider } from 'fumadocs-ui/contexts/tree';
import { TreeContextProvider } from '@hanzo/docs/ui/contexts/tree';
import { source } from '@/lib/source';
import { NextProvider } from 'fumadocs-core/framework/next';
import { NextProvider } from '@hanzo/docs/core/framework/next';
export const metadata = createMetadata({
title: {
+1 -1
View File
@@ -1,6 +1,6 @@
'use client';
import { RootProvider } from 'fumadocs-ui/provider/base';
import { RootProvider } from '@hanzo/docs/ui/provider/base';
import dynamic from 'next/dynamic';
import type { ReactNode } from 'react';
import { TooltipProvider } from '@radix-ui/react-tooltip';
+2 -2
View File
@@ -1,6 +1,6 @@
import { source } from '@/lib/source';
import type { OramaDocument } from 'fumadocs-core/search/orama-cloud';
import { getBreadcrumbItems } from 'fumadocs-core/breadcrumb';
import type { OramaDocument } from '@hanzo/docs/core/search/orama-cloud';
import { getBreadcrumbItems } from '@hanzo/docs/core/breadcrumb';
export const revalidate = false;
+2 -2
View File
@@ -12,8 +12,8 @@ import {
useDeferredValue,
} from 'react';
import { Fragment, jsx, jsxs } from 'react/jsx-runtime';
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import defaultMdxComponents from 'fumadocs-ui/mdx';
import { DynamicCodeBlock } from '@hanzo/docs/ui/components/dynamic-codeblock';
import defaultMdxComponents from '@hanzo/docs/ui/mdx';
import { visit } from 'unist-util-visit';
import type { ElementContent, Root, RootContent } from 'hast';
+3 -3
View File
@@ -8,13 +8,13 @@ import {
MessageCircleIcon,
} from 'lucide-react';
import { cn } from '@/lib/cn';
import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
import { useCopyButton } from '@hanzo/docs/ui/utils/use-copy-button';
import { buttonVariants } from '@hanzo/docs/ui/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from 'fumadocs-ui/components/ui/popover';
} from '@hanzo/docs/ui/components/ui/popover';
import { cva } from 'class-variance-authority';
const cache = new Map<string, string>();
+2 -2
View File
@@ -13,8 +13,8 @@ import {
} from 'react';
import { Loader2, MessageCircleIcon, RefreshCw, Send, X } from 'lucide-react';
import { cn } from '@/lib/cn';
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
import Link from 'fumadocs-core/link';
import { buttonVariants } from '@hanzo/docs/ui/components/ui/button';
import Link from '@hanzo/docs/core/link';
import { type UIMessage, useChat, type UseChatHelpers } from '@ai-sdk/react';
import type { ProvideLinksToolSchema } from '@/lib/chat/inkeep-qa-schema';
import type { z } from 'zod';
+1 -1
View File
@@ -1,5 +1,5 @@
import { openapi } from '@/lib/openapi';
import { createAPIPage } from 'fumadocs-openapi/ui';
import { createAPIPage } from '@hanzo/docs/openapi/ui';
export const APIPage = createAPIPage(openapi, {
shikiOptions: {
+2 -2
View File
@@ -1,5 +1,5 @@
import * as Base from 'fumadocs-ui/components/codeblock';
import { getHighlighter, hastToJsx } from 'fumadocs-core/highlight';
import * as Base from '@hanzo/docs/ui/components/codeblock';
import { getHighlighter, hastToJsx } from '@hanzo/docs/core/highlight';
import { cn } from '@/lib/cn';
import type { BundledLanguage } from 'shiki';
+2 -2
View File
@@ -1,12 +1,12 @@
'use client';
import { cn } from '@/lib/cn';
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
import { buttonVariants } from '@hanzo/docs/ui/components/ui/button';
import { ThumbsDown, ThumbsUp } from 'lucide-react';
import { type SyntheticEvent, useEffect, useState, useTransition } from 'react';
import {
Collapsible,
CollapsibleContent,
} from 'fumadocs-ui/components/ui/collapsible';
} from '@hanzo/docs/ui/components/ui/collapsible';
import { cva } from 'class-variance-authority';
import { usePathname } from 'next/navigation';
+1 -1
View File
@@ -14,7 +14,7 @@ import type {
NodeObject,
} from 'react-force-graph-2d';
import { forceCollide, forceLink, forceManyBody } from 'd3-force';
import { useRouter } from 'fumadocs-core/framework';
import { useRouter } from '@hanzo/docs/core/framework';
export interface Graph {
links: Link[];
+2 -2
View File
@@ -1,7 +1,7 @@
import Link from 'fumadocs-core/link';
import Link from '@hanzo/docs/core/link';
import { type ReactNode, Suspense } from 'react';
import { cn } from '@/lib/cn';
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
import { buttonVariants } from '@hanzo/docs/ui/components/ui/button';
export interface Suggestion {
id: string;
@@ -1,5 +1,5 @@
'use client';
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
import { DynamicCodeBlock } from '@hanzo/docs/ui/components/dynamic-codeblock';
import { useState } from 'react';
import { bundledLanguages } from 'shiki';
+8 -8
View File
@@ -1,14 +1,14 @@
import { Home } from 'lucide-react';
import { Heading } from 'fumadocs-ui/components/heading';
import { Card } from 'fumadocs-ui/components/card';
import { Callout } from 'fumadocs-ui/components/callout';
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { Step, Steps } from 'fumadocs-ui/components/steps';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Heading } from '@hanzo/docs/ui/components/heading';
import { Card } from '@hanzo/docs/ui/components/card';
import { Callout } from '@hanzo/docs/ui/components/callout';
import { Accordion, Accordions } from '@hanzo/docs/ui/components/accordion';
import { Tab, Tabs } from '@hanzo/docs/ui/components/tabs';
import { Step, Steps } from '@hanzo/docs/ui/components/steps';
import { TypeTable } from '@hanzo/docs/ui/components/type-table';
import { type ReactNode } from 'react';
import { Wrapper } from './wrapper';
import { GithubInfo } from 'fumadocs-ui/components/github-info';
import { GithubInfo } from '@hanzo/docs/ui/components/github-info';
import { owner, repo } from '@/lib/github';
import {
Banner,
@@ -3,7 +3,7 @@ import {
TabsContent,
TabsList,
TabsTrigger,
} from 'fumadocs-ui/components/tabs.unstyled';
} from '@hanzo/docs/ui/components/tabs.unstyled';
import { CodeBlock } from '@/components/code-block';
export function Installation({ name }: { name: string }) {
+6 -6
View File
@@ -3,24 +3,24 @@ import dynamic from 'next/dynamic';
export const DynamicCodeBlock = dynamic(() => import('./dynamic-codeblock'));
export const Banner = dynamic(() =>
import('fumadocs-ui/components/banner').then((res) => res.Banner),
import('@hanzo/docs/ui/components/banner').then((res) => res.Banner),
);
export const InlineTOC = dynamic(() =>
import('fumadocs-ui/components/inline-toc').then((res) => res.InlineTOC),
import('@hanzo/docs/ui/components/inline-toc').then((res) => res.InlineTOC),
);
export const File = dynamic(() =>
import('fumadocs-ui/components/files').then((res) => res.File),
import('@hanzo/docs/ui/components/files').then((res) => res.File),
);
export const Files = dynamic(() =>
import('fumadocs-ui/components/files').then((res) => res.Files),
import('@hanzo/docs/ui/components/files').then((res) => res.Files),
);
export const Folder = dynamic(() =>
import('fumadocs-ui/components/files').then((res) => res.Folder),
import('@hanzo/docs/ui/components/files').then((res) => res.Folder),
);
export const ImageZoom = dynamic(() =>
import('fumadocs-ui/components/image-zoom').then((res) => res.ImageZoom),
import('@hanzo/docs/ui/components/image-zoom').then((res) => res.ImageZoom),
);
export const GraphView = dynamic(() =>
+4 -5
View File
@@ -1,4 +1,4 @@
import { type Registry } from '@fumadocs/cli/build';
import { type Registry } from '@hanzo/docs/cli/build';
import * as ui from '../../../packages/ui/src/_registry';
import { fileURLToPath } from 'node:url';
import * as path from 'node:path';
@@ -16,7 +16,7 @@ function selectFrom(r: Registry, component: string, filename: string) {
export const registry: Registry = {
dir: baseDir,
name: 'fumadocs',
name: 'hanzo-docs',
packageJson: './package.json',
tsconfigPath: './tsconfig.json',
onUnknownFile(absolutePath) {
@@ -43,7 +43,7 @@ export const registry: Registry = {
if (
ref.type === 'dependency' &&
ref.specifier === 'fumadocs-ui/components/ui/button'
ref.specifier === '@hanzo/docs/ui/components/ui/button'
) {
return {
type: 'sub-component',
@@ -140,8 +140,7 @@ export const registry: Registry = {
},
],
dependencies: {
'fumadocs-core': null,
'fumadocs-ui': null,
'@hanzo/docs': null,
next: null,
react: null,
},
+6 -6
View File
@@ -12,19 +12,19 @@ import {
SearchDialogOverlay,
type SearchItemType,
type SharedProps,
} from 'fumadocs-ui/components/dialog/search';
import { useDocsSearch } from 'fumadocs-core/search/client';
} from '@hanzo/docs/ui/components/dialog/search';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
import { useMemo, useState } from 'react';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from 'fumadocs-ui/components/ui/popover';
} from '@hanzo/docs/ui/components/ui/popover';
import { ArrowRight, ChevronDown } from 'lucide-react';
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
import { buttonVariants } from '@hanzo/docs/ui/components/ui/button';
import { cn } from '@/lib/cn';
import { useTreeContext } from 'fumadocs-ui/contexts/tree';
import type { Item, Node } from 'fumadocs-core/page-tree';
import { useTreeContext } from '@hanzo/docs/ui/contexts/tree';
import type { Item, Node } from '@hanzo/docs/core/page-tree';
import { useRouter } from 'next/navigation';
import { orama } from '@/lib/orama/client';
+1 -1
View File
@@ -4,7 +4,7 @@ import type { ComponentProps } from 'react';
import * as React from 'react';
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
import { cn } from '@/lib/cn';
import Link from 'fumadocs-core/link';
import Link from '@hanzo/docs/core/link';
const HoverCard = HoverCardPrimitive.Root;
+6 -6
View File
@@ -18,7 +18,7 @@ We will use Fumadocs MDX to manage the content, and implement our own UI with Ta
Define a `blogPosts` collection.
```ts title="source.config.ts"
import { defineCollections, frontmatterSchema } from 'fumadocs-mdx/config';
import { defineCollections, frontmatterSchema } from '@hanzo/docs/mdx/config';
import { z } from 'zod';
export const blogPosts = defineCollections({
@@ -35,9 +35,9 @@ export const blogPosts = defineCollections({
Parse the output collection in `source.ts`:
```ts title="lib/source.ts"
import { loader } from 'fumadocs-core/source';
import { toFumadocsSource } from 'fumadocs-mdx/runtime/server';
import { blogPosts } from 'fumadocs-mdx:collections/server';
import { loader } from '@hanzo/docs/core/source';
import { toFumadocsSource } from '@hanzo/docs/mdx/runtime/server';
import { blogPosts } from '@hanzo/docs-mdx:collections/server';
export const blog = loader({
baseUrl: '/blog',
@@ -94,8 +94,8 @@ Note that blog posts won't have nested slugs like `/slug1/slug2`. We don't need
```tsx title="app/(home)/blog/[slug]/page.tsx"
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { InlineTOC } from 'fumadocs-ui/components/inline-toc';
import defaultMdxComponents from 'fumadocs-ui/mdx';
import { InlineTOC } from '@hanzo/docs/ui/components/inline-toc';
import defaultMdxComponents from '@hanzo/docs/ui/mdx';
import { blog } from '@/lib/source';
export default async function Page(props: {
+1 -1
View File
@@ -83,7 +83,7 @@ console.log(await page.data.getText('processed'));
To access processed Markdown content, you need to enable `includeProcessedMarkdown` in collection config.
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export default defineDocs({
docs: {
+13 -13
View File
@@ -21,7 +21,7 @@ Refactor the import in `next.config`.
**From:**
```ts
import createMDX from 'fumadocs-mdx/config';
import createMDX from '@hanzo/docs/mdx/config';
const withMDX = createMDX();
@@ -36,7 +36,7 @@ export default withMDX(config);
**To:**
```ts
import { createMDX } from 'fumadocs-mdx/next';
import { createMDX } from '@hanzo/docs/mdx/next';
const withMDX = createMDX();
@@ -53,7 +53,7 @@ export default withMDX(config);
`mdx-components.tsx` is no longer used. It now allows only MDX components passed from `MDX` body's `components` prop.
```tsx
import defaultMdxComponents from 'fumadocs-ui/mdx';
import defaultMdxComponents from '@hanzo/docs/ui/mdx';
const MDX = page.data.body;
@@ -76,7 +76,7 @@ Every collection has its own config, you can have customised Zod schema to valid
You can create a source config file, and add the following:
```ts
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const { docs, meta } = defineDocs({
dir: 'content/docs',
@@ -108,8 +108,8 @@ Now to integrate it with Fumadocs framework, change your `source.ts` from:
```ts
import { map } from '@/.map';
import { createMDXSource } from 'fumadocs-mdx/runtime/next';
import { loader } from 'fumadocs-core/source';
import { createMDXSource } from '@hanzo/docs/mdx/runtime/next';
import { loader } from '@hanzo/docs/core/source';
export const { getPage, getPages, pageTree } = loader({
baseUrl: '/docs',
@@ -122,8 +122,8 @@ to:
```ts
import { docs, meta } from '@/.source';
import { createMDXSource } from 'fumadocs-mdx/runtime/next';
import { loader } from 'fumadocs-core/source';
import { createMDXSource } from '@hanzo/docs/mdx/runtime/next';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
baseUrl: '/docs',
@@ -151,7 +151,7 @@ page.data.title; // [!code ++]
Instead of passing them to `next.config` file, define a global config in `source.config.ts`:
```ts
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -171,9 +171,9 @@ For `defineDocs`, see [`schema`](/docs/mdx/collections#schema-1).
Same as before, you can call `loader` multiple times for different types (e.g. for docs and blog).
```ts
import { createMDXSource } from 'fumadocs-mdx/runtime/next';
import type { InferMetaType, InferPageType } from 'fumadocs-core/source';
import { loader } from 'fumadocs-core/source';
import { createMDXSource } from '@hanzo/docs/mdx/runtime/next';
import type { InferMetaType, InferPageType } from '@hanzo/docs/core/source';
import { loader } from '@hanzo/docs/core/source';
import { meta, docs, blog as blogPosts } from '@/.source';
export const source = loader({
@@ -198,7 +198,7 @@ import {
defineDocs,
defineCollections,
frontmatterSchema,
} from 'fumadocs-mdx/config';
} from '@hanzo/docs/mdx/config';
import { z } from 'zod';
export const { docs, meta } = defineDocs({
+2 -2
View File
@@ -60,8 +60,8 @@ This model works, but we started to see some problems:
Furthermore, the Zod schema is passed to the source adapter in `source.ts` rather than the loader:
```ts
import { loader } from 'fumadocs-core/source';
import { createMDXSource } from 'fumadocs-mdx/runtime/next';
import { loader } from '@hanzo/docs/core/source';
import { createMDXSource } from '@hanzo/docs/mdx/runtime/next';
export const source = loader({
source: createMDXSource(map, {
+20 -20
View File
@@ -24,7 +24,7 @@ You can add/update the path aliases in `tsconfig.json` for new entry files.
"compilerOptions": {
"paths": {
// [!code ++]
"fumadocs-mdx:collections/*": [".source/*"]
"@hanzo/docs-mdx:collections/*": [".source/*"]
}
}
}
@@ -34,19 +34,19 @@ Import your collections from the entry files instead of `@/.source`:
```ts
// ordinary collections
import { docs } from 'fumadocs-mdx:collections/server';
import { docs } from '@hanzo/docs-mdx:collections/server';
// collections in dynamic mode
import { docs } from 'fumadocs-mdx:collections/dynamic';
import { docs } from '@hanzo/docs-mdx:collections/dynamic';
// non-RSC environment
import browserCollections from 'fumadocs-mdx:collections/browser';
import browserCollections from '@hanzo/docs-mdx:collections/browser';
```
To use `loader()` with doc collections, use the new `toFumadocsSource()` utility instead.
```ts
import { blogPosts } from 'fumadocs-mdx:collections/server';
import { toFumadocsSource } from 'fumadocs-mdx/runtime/server';
import { loader } from 'fumadocs-core/source';
import { blogPosts } from '@hanzo/docs-mdx:collections/server';
import { toFumadocsSource } from '@hanzo/docs/mdx/runtime/server';
import { loader } from '@hanzo/docs/core/source';
export const blog = loader({
baseUrl: '/blog',
@@ -59,7 +59,7 @@ export const blog = loader({
On Next.js, **Async Mode** now aligns with the behaviour on Vite to generate async imports. This enables server-side chunking to improve memory usage.
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -73,7 +73,7 @@ export const docs = defineDocs({
Instead, we introduced a `dynamic` option to enable dynamic compilation. This is available for both Vite and Next.js.
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -91,17 +91,17 @@ By enabling Async or Dynamic modes, the relevant collections are considered lazy
It now accepts the framework plugin options, you can customise more properties:
```ts tab="Before"
import { postInstall } from 'fumadocs-mdx/next';
import { postInstall } from '@hanzo/docs/mdx/next';
// or
import { postInstall } from 'fumadocs-mdx/vite';
import { postInstall } from '@hanzo/docs/mdx/vite';
postInstall('source.config.ts');
```
```ts tab="After"
import { postInstall } from 'fumadocs-mdx/next';
import { postInstall } from '@hanzo/docs/mdx/next';
// or
import { postInstall } from 'fumadocs-mdx/vite';
import { postInstall } from '@hanzo/docs/mdx/vite';
postInstall({ configPath: 'source.config.ts' });
```
@@ -111,7 +111,7 @@ postInstall({ configPath: 'source.config.ts' });
To support a broader range of presets and accommodate dynamic modes, `getDefaultMDXOptions()` has been renamed to `applyMdxPreset()`.
```ts title="source.config.ts" tab="Before"
import { defineCollections, getDefaultMDXOptions } from 'fumadocs-mdx/config';
import { defineCollections, getDefaultMDXOptions } from '@hanzo/docs/mdx/config';
import { myPlugin } from './remark-plugin';
export const blog = defineCollections({
@@ -125,7 +125,7 @@ export const blog = defineCollections({
```
```ts title="source.config.ts" tab="After"
import { defineCollections, applyMdxPreset } from 'fumadocs-mdx/config';
import { defineCollections, applyMdxPreset } from '@hanzo/docs/mdx/config';
import { myPlugin } from './remark-plugin';
export const blog = defineCollections({
@@ -143,8 +143,8 @@ export const blog = defineCollections({
The `lastModifiedTime` option has been replaced by a dedicated `lastModified` plugin. This shift promotes a plugin-based architecture for better extensibility.
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import lastModified from 'fumadocs-mdx/plugins/last-modified';
import { defineConfig } from '@hanzo/docs/mdx/config';
import lastModified from '@hanzo/docs/mdx/plugins/last-modified';
export default defineConfig({
// [!code ++]
@@ -157,7 +157,7 @@ export default defineConfig({
Support for specifying multiple directories in a single collection has been discontinued. Instead, utilize the `files` property to filter and include specific files.
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/guides',
@@ -172,7 +172,7 @@ export const docs = defineDocs({
The automatic generation of `extractedReferences` is no longer enabled by default. To retain this functionality, explicitly activate it via the `postprocess` option.
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -191,7 +191,7 @@ The `generateIndexFile` option of our Vite plugin has been renamed to `index`.
```ts title="vite.config.ts"
import { defineConfig } from 'vite';
import mdx from 'fumadocs-mdx/vite';
import mdx from '@hanzo/docs/mdx/vite';
import * as MdxConfig from './source.config';
export default defineConfig({
+1 -1
View File
@@ -20,7 +20,7 @@ For existing users, you probably knew how to pass MDX components, and no further
But you can still make one:
```tsx title="mdx-components.tsx"
import defaultMdxComponents from 'fumadocs-ui/mdx';
import defaultMdxComponents from '@hanzo/docs/ui/mdx';
import type { MDXComponents } from 'mdx/types';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
+10 -10
View File
@@ -21,7 +21,7 @@ This redesign separates API page and server concerns, removes `disablePlayground
Previously, all options are located in `createOpenAPI()`.
```ts title="lib/openapi.ts"
import { createOpenAPI } from 'fumadocs-openapi/server';
import { createOpenAPI } from '@hanzo/docs/openapi/server';
import path from 'node:path';
export const openapi = createOpenAPI({
@@ -39,7 +39,7 @@ This redesign separates API page and server concerns, removes `disablePlayground
Now, you need to separate API page components and the server declaration.
```ts tab="lib/openapi.ts"
import { createOpenAPI } from 'fumadocs-openapi/server';
import { createOpenAPI } from '@hanzo/docs/openapi/server';
import path from 'node:path';
export const openapi = createOpenAPI({
@@ -50,7 +50,7 @@ This redesign separates API page and server concerns, removes `disablePlayground
```ts tab="components/api-page.tsx"
import { openapi } from '@/lib/openapi';
import { createAPIPage } from 'fumadocs-openapi/ui';
import { createAPIPage } from '@hanzo/docs/openapi/ui';
export const APIPage = createAPIPage(openapi, {
mediaAdapters: {
@@ -87,7 +87,7 @@ This redesign separates API page and server concerns, removes `disablePlayground
```typescript tab="components/api-page.client.tsx"
'use client';
import { defineClientConfig } from 'fumadocs-openapi/ui/client';
import { defineClientConfig } from '@hanzo/docs/openapi/ui/client';
export default defineClientConfig({
playground: {
@@ -103,7 +103,7 @@ This redesign separates API page and server concerns, removes `disablePlayground
```typescript title="components/api-page.client.tsx"
'use client';
import { defineClientConfig } from 'fumadocs-openapi/ui/client';
import { defineClientConfig } from '@hanzo/docs/openapi/ui/client';
import { adapters } from './my-media-adapters';
export default defineClientConfig({
@@ -121,7 +121,7 @@ Fumadocs OpenAPI now prefers per-feature customizations, eliminating the central
```tsx title="components/api-page.tsx"
import { openapi } from '@/lib/openapi';
import { createAPIPage } from 'fumadocs-openapi/ui';
import { createAPIPage } from '@hanzo/docs/openapi/ui';
export const APIPage = createAPIPage(openapi, {
content: {
@@ -136,7 +136,7 @@ For migrating Playground `fields` options, utilize client-side render APIs:
```tsx title="components/api-page.client.tsx"
'use client';
import { defineClientConfig } from 'fumadocs-openapi/ui/client';
import { defineClientConfig } from '@hanzo/docs/openapi/ui/client';
export default defineClientConfig({
playground: {
@@ -151,7 +151,7 @@ Additional layout customizations are available:
```tsx title="components/api-page.tsx"
import { openapi } from '@/lib/openapi';
import { createAPIPage } from 'fumadocs-openapi/ui';
import { createAPIPage } from '@hanzo/docs/openapi/ui';
export const APIPage = createAPIPage(openapi, {
content: {
@@ -189,7 +189,7 @@ void generateFiles({
```
```ts tab="After"
import { generateFiles } from 'fumadocs-openapi';
import { generateFiles } from '@hanzo/docs/openapi';
import { openapi } from '@/lib/openapi';
void generateFiles({
@@ -206,7 +206,7 @@ v10 introduced the `storageKeyPrefix` option to prevent state bleed across multi
```tsx title="components/api-page.client.tsx"
'use client';
import { defineClientConfig } from 'fumadocs-openapi/ui/client';
import { defineClientConfig } from '@hanzo/docs/openapi/ui/client';
export default defineClientConfig({
storageKeyPrefix: 'fumadocs-openapi-custom-',
+2 -2
View File
@@ -42,7 +42,7 @@ The behaviour of `groupBy` API is also changed.
The usage of `name` option is renewed, it can be used to customise the output path of files.
```ts
import { generateFiles } from 'fumadocs-openapi';
import { generateFiles } from '@hanzo/docs/openapi';
void generateFiles({
name: (output, document) => {
@@ -60,7 +60,7 @@ void generateFiles({
You can start using the latest algorithm, or keep the current behaviour with:
```ts
import { generateFiles } from 'fumadocs-openapi';
import { generateFiles } from '@hanzo/docs/openapi';
void generateFiles({
name: {
+2 -2
View File
@@ -41,7 +41,7 @@ Now, you can use the `<RootToggle />` component directly, and the docs has a bet
You can now attach properties to page trees easily with the Source API.
```ts
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
export const utils = loader({
pageTree: {
@@ -58,7 +58,7 @@ export const utils = loader({
The language switch is now added to Docs Layout.
```tsx
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
export default function Layout({ children }: { children: React.ReactNode }) {
return <DocsLayout i18n>{children}</DocsLayout>;
+8 -8
View File
@@ -16,7 +16,7 @@ Fumadocs v13 has been released. It aims to fix the CSS pollution problem and rem
Now supports keeping the original background generated by Shiki on `CodeBlock` component.
```tsx
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
import { Pre, CodeBlock } from '@hanzo/docs/ui/components/codeblock';
<MDX
components={{
@@ -42,7 +42,7 @@ Callout is now a default MDX component, you can use it in MDX files without an i
The headless component of Table of Contents (TOC) now has a separate scroll container provider.
```tsx
import * as Base from 'fumadocs-core/toc';
import * as Base from '@hanzo/docs/core/toc';
return (
<Base.AnchorProvider>
@@ -61,7 +61,7 @@ The anchor provider can be placed anywhere.
Now supports disabling the default container styles of Tailwind CSS added by Fumadocs UI.
```js
import { createPreset } from 'fumadocs-ui/tailwind-plugin';
import { createPreset } from '@hanzo/docs/ui/tailwind-plugin';
/** @type {import('tailwindcss').Config} */
export default {
@@ -91,7 +91,7 @@ A `fd-` prefix is added to them to allow the flexibility to have a separated des
To use the Fumadocs UI colors on your primary app, enable the `addGlobalColors` option.
```js
import { createPreset } from 'fumadocs-ui/tailwind-plugin';
import { createPreset } from '@hanzo/docs/ui/tailwind-plugin';
/** @type {import('tailwindcss').Config} */
export default {
@@ -114,7 +114,7 @@ Since Tailwind CSS supports TypeScript configuration, it makes sense to migrate
Use ESM syntax in your configuration.
```ts
import { createPreset } from 'fumadocs-ui/tailwind-plugin';
import { createPreset } from '@hanzo/docs/ui/tailwind-plugin';
/** @type {import('tailwindcss').Config} */
export default {
@@ -144,9 +144,9 @@ You have to pass the active translations directly.
`locales` is passed as the available options on the Language Select component.
```tsx
import { RootProvider } from 'fumadocs-ui/provider';
import { RootProvider } from '@hanzo/docs/ui/provider';
import type { ReactNode } from 'react';
import { I18nProvider } from 'fumadocs-ui/i18n';
import { I18nProvider } from '@hanzo/docs/ui/i18n';
export default function Layout({
params: { lang },
@@ -196,7 +196,7 @@ With v13, pass all props to the `CodeBlock` component.
This also includes class names, you may change your custom styles if necessary.
```tsx
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
import { Pre, CodeBlock } from '@hanzo/docs/ui/components/codeblock';
<MDX
components={{
+15 -15
View File
@@ -53,7 +53,7 @@ You can use our new `createFromSource` API to create the route handler, which of
```ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { createFromSource } from '@hanzo/docs/core/search/server';
export const { GET } = createFromSource(source);
```
@@ -62,7 +62,7 @@ In favour of this, the new search client of Fumadocs is introduced with support
This includes Algolia, Orama (static and dynamic with route handlers).
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const client = useDocsSearch({
type: 'static',
@@ -92,7 +92,7 @@ To improve code organization, we made a Metadata Image API on Fumadocs Core.
It is a tiny wrapper over Next.js Metadata API, composes seamlessly with Source API.
```ts title="lib/metadata.ts"
import { createMetadataImage } from 'fumadocs-core/server';
import { createMetadataImage } from '@hanzo/docs/core/server';
import { source } from '@/lib/source';
export const metadataImage = createMetadataImage({
@@ -102,7 +102,7 @@ export const metadataImage = createMetadataImage({
```
```ts title="route.ts"
import { generateOGImage } from 'fumadocs-ui/og';
import { generateOGImage } from '@hanzo/docs/ui/og';
import { metadataImage } from '@/lib/metadata';
export const GET = metadataImage.createAPI((page) => {
@@ -172,7 +172,7 @@ Now it accepts the source object via `from` prop.
```tsx title="page.tsx"
import { source } from '@/lib/source';
import { DocsCategory } from 'fumadocs-ui/page';
import { DocsCategory } from '@hanzo/docs/ui/page';
const page = source.getPage(params.slug);
@@ -184,7 +184,7 @@ You can also force a page tree.
```tsx title="page.tsx (i18n enabled)"
import { source } from '@/lib/source';
import { DocsCategory } from 'fumadocs-ui/page';
import { DocsCategory } from '@hanzo/docs/ui/page';
const page = source.getPage(params.slug, params.lang);
@@ -260,7 +260,7 @@ You can disable the default theme switcher with `disableThemeSwitch` on layouts.
### Move `dir` option from `defineDocs`
```ts
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const { docs, meta } = defineDocs({
dir: 'my/content/dir', // define once
@@ -272,17 +272,17 @@ export const { docs, meta } = defineDocs({
**Previous**
```ts
import { DocsLayout } from 'fumadocs-ui/layout';
import { HomeLayout } from 'fumadocs-ui/home-layout';
import { HomeLayoutProps } from 'fumadocs-ui/home-layout';
import { DocsLayout } from '@hanzo/docs/ui/layout';
import { HomeLayout } from '@hanzo/docs/ui/home-layout';
import { HomeLayoutProps } from '@hanzo/docs/ui/home-layout';
```
**New Import Path**
```ts
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
import { HomeLayout } from '@hanzo/docs/ui/layouts/home';
import { BaseLayoutProps } from '@hanzo/docs/ui/layouts/shared';
```
### Twoslash UI
@@ -293,9 +293,9 @@ This isolates some logic from Fumadocs UI, allowing a better code organization.
Import the CSS styles and `Popup` component differently.
```ts
import 'fumadocs-twoslash/twoslash.css';
import '@hanzo/docs/twoslash/twoslash.css';
import { Popup } from 'fumadocs-twoslash/ui';
import { Popup } from '@hanzo/docs/twoslash/ui';
```
<Callout>It requires Tailwind CSS.</Callout>
+3 -3
View File
@@ -23,7 +23,7 @@ This is a minor release, it shouldn't break any previous usages unless you're re
Fumadocs Core now requires a `FrameworkProvider`. It's as simple as wrapping it with appropriate provider:
```tsx
import { NextProvider } from 'fumadocs-core/framework/next';
import { NextProvider } from '@hanzo/docs/core/framework/next';
export function Provider({ children }) {
return <NextProvider>{children}</NextProvider>;
@@ -33,7 +33,7 @@ export function Provider({ children }) {
If you're using Fumadocs UI, there's no need to change. `RootProvider` included it by default, and allows you to provide your own framework with:
```tsx
import { RootProvider } from 'fumadocs-ui/provider/base';
import { RootProvider } from '@hanzo/docs/ui/provider/base';
export function Provider({ children }) {
// now it doesn't add the Next.js provider
@@ -60,7 +60,7 @@ pnpm update -i -r
If you want to try the React Router example:
```bash
pnpm create fumadocs-app
pnpm create hanzo-app
```
### Future Plans
+4 -4
View File
@@ -21,8 +21,8 @@ Add `@import` to the presets exported by Fumadocs UI, and include the `fumadocs-
```css title="Tailwind CSS"
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
@import '@hanzo/docs/ui/css/neutral.css';
@import '@hanzo/docs/ui/css/preset.css';
/* relative to the CSS file, make sure it's correct for your app */
@source '../node_modules/fumadocs-ui/dist/**/*.js';
@@ -114,8 +114,8 @@ v15 improves the playground UI (inspired by the minimalism of Scalar), and broug
You can enable the Scalar API Client using `useScalar` option in `createOpenAPI()`:
```ts
import { createOpenAPI } from 'fumadocs-openapi/server';
import { APIPlayground } from 'fumadocs-openapi/scalar';
import { createOpenAPI } from '@hanzo/docs/openapi/server';
import { APIPlayground } from '@hanzo/docs/openapi/scalar';
export const openapi = createOpenAPI({
renderer: {
+3 -3
View File
@@ -92,9 +92,9 @@ Make sure to import the appropriate page layout based on your docs layout:
```ts
// For docs layout
import { DocsPage } from 'fumadocs-ui/layouts/docs/page';
import { DocsPage } from '@hanzo/docs/ui/layouts/docs/page';
// For notebook layout
import { DocsPage } from 'fumadocs-ui/layouts/notebook/page';
import { DocsPage } from '@hanzo/docs/ui/layouts/notebook/page';
```
**Migration Steps:** Update your imports accordingly. Although the default `fumadocs-ui/page` will redirect to the correct layout, we strongly advise explicit imports for clarity and future-proofing.
@@ -110,7 +110,7 @@ Styles related to the abandoned `container` utility, and `--spacing-fd-container
The `fumadocs-ui/contexts/sidebar` module has been removed. Access the context via:
```ts
import { useSidebar } from 'fumadocs-ui/components/sidebar/base';
import { useSidebar } from '@hanzo/docs/ui/components/sidebar/base';
```
**Migration Steps:** Update import paths, ensure the context is only accessed within `<DocsLayout />`.
+4 -4
View File
@@ -44,7 +44,7 @@ Fumadocs 16 removed substantial amount of deprecated APIs accumulated since v15.
- **Migration to Orama Cloud's New SDK**: The `@orama/core` package replaces the prior client. Update your synchronization code as follows:
```ts
import { sync } from 'fumadocs-core/search/orama-cloud';
import { sync } from '@hanzo/docs/core/search/orama-cloud';
import { OramaCloud } from '@orama/core';
// [!code highlight:4]
@@ -85,8 +85,8 @@ We introduced Plugins API, enabling extensible modifications to MDX configuratio
There's a `json-schema` plugin natively provided by Fumadocs MDX.
```ts title="source.config.ts"
import jsonSchema from 'fumadocs-mdx/plugins/json-schema';
import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
import jsonSchema from '@hanzo/docs/mdx/plugins/json-schema';
import { defineConfig, defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -137,7 +137,7 @@ We also supported index file generation targeting other runtimes like Bun/Node.j
```ts title="vite.config.ts"
import { defineConfig } from 'vite';
import mdx from 'fumadocs-mdx/vite';
import mdx from '@hanzo/docs/mdx/vite';
import * as MdxConfig from './source.config';
export default defineConfig({
+1 -1
View File
@@ -68,7 +68,7 @@ npx @fumadocs/cli tree -h
#### Example Output
```tsx title="output.tsx"
import { File, Folder, Files } from 'fumadocs-ui/components/files';
import { File, Folder, Files } from '@hanzo/docs/ui/components/files';
export default (
<Files>
@@ -15,7 +15,7 @@ It exports a `useBreadcrumb` hook:
declare const tree: any;
import { usePathname } from 'next/navigation';
// ---cut---
import { useBreadcrumb } from 'fumadocs-core/breadcrumb';
import { useBreadcrumb } from '@hanzo/docs/core/breadcrumb';
// obtain `pathname` using the hook provided by your React framework.
const pathname = usePathname();
@@ -30,8 +30,8 @@ A styled example for Next.js.
```tsx
'use client';
import { usePathname } from 'next/navigation';
import { useBreadcrumb } from 'fumadocs-core/breadcrumb';
import type { PageTree } from 'fumadocs-core/page-tree';
import { useBreadcrumb } from '@hanzo/docs/core/breadcrumb';
import type { PageTree } from '@hanzo/docs/core/page-tree';
import { Fragment } from 'react';
import { ChevronRight } from 'lucide-react';
import Link from 'next/link';
@@ -13,7 +13,7 @@ The `rel` property is automatically generated.
Usage is the same as using `<a>`.
```mdx
import Link from 'fumadocs-core/link';
import Link from '@hanzo/docs/core/link';
<Link href="/docs/components">Click Me</Link>
```
@@ -27,7 +27,7 @@ You can force a URL to be external by passing an `external` prop.
You can enable dynamic hrefs by importing `dynamic-link`.
```mdx
import { DynamicLink } from 'fumadocs-core/dynamic-link';
import { DynamicLink } from '@hanzo/docs/core/dynamic-link';
<DynamicLink href="/[lang]/components">Click Me</DynamicLink>
```
@@ -3,7 +3,7 @@ import {
ScrollProvider,
TOCItem,
type TOCItemType,
} from 'fumadocs-core/toc';
} from '@hanzo/docs/core/toc';
import { type ReactNode, useRef } from 'react';
export function Page({
@@ -8,7 +8,7 @@ A Table of Contents with active anchor observer and auto scroll.
## Usage
```tsx
import * as Base from 'fumadocs-core/toc';
import * as Base from '@hanzo/docs/core/toc';
return (
<Base.AnchorProvider>
@@ -38,7 +38,7 @@ See [Definitions of Page Tree](/docs/headless/page-tree).
Pass your page tree to `DocsLayout` (usually in a `layout.tsx`):
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
@@ -70,7 +70,7 @@ For docs page, it's the same logic:
You may need table of contents, which can be generated on your own, or using the [`getTableOfContents`](/docs/headless/utils/get-toc) utility (Markdown/MDX only).
```tsx
import { DocsPage, DocsBody } from 'fumadocs-ui/layouts/docs/page';
import { DocsPage, DocsBody } from '@hanzo/docs/ui/layouts/docs/page';
import { getPage } from './my-content-source';
import { notFound } from 'next/navigation';
@@ -145,7 +145,7 @@ It's compatible with Server Components. For example:
```tsx
import { createCompiler } from '@fumadocs/mdx-remote';
import { getPage } from './my-content-source';
import { DocsBody, DocsPage } from 'fumadocs-ui/layouts/docs/page';
import { DocsBody, DocsPage } from '@hanzo/docs/ui/layouts/docs/page';
import { getMDXComponents } from '@/mdx-components';
const compiler = createCompiler({
+4 -4
View File
@@ -33,7 +33,7 @@ For some components, a framework provider is needed:
```tsx tab="Next.js"
import type { ReactNode } from 'react';
import { NextProvider } from 'fumadocs-core/framework/next';
import { NextProvider } from '@hanzo/docs/core/framework/next';
export function RootLayout({ children }: { children: ReactNode }) {
// or if you're using Fumadocs UI, use `<RootProvider />`
@@ -43,7 +43,7 @@ export function RootLayout({ children }: { children: ReactNode }) {
```tsx tab="React Router"
import type { ReactNode } from 'react';
import { ReactRouterProvider } from 'fumadocs-core/framework/react-router';
import { ReactRouterProvider } from '@hanzo/docs/core/framework/react-router';
export function Root({ children }: { children: ReactNode }) {
return <ReactRouterProvider>{children}</ReactRouterProvider>;
@@ -52,7 +52,7 @@ export function Root({ children }: { children: ReactNode }) {
```tsx tab="Tanstack Start/Router"
import type { ReactNode } from 'react';
import { TanstackProvider } from 'fumadocs-core/framework/tanstack';
import { TanstackProvider } from '@hanzo/docs/core/framework/tanstack';
export function Root({ children }: { children: ReactNode }) {
return <TanstackProvider>{children}</TanstackProvider>;
@@ -61,7 +61,7 @@ export function Root({ children }: { children: ReactNode }) {
```tsx tab="Waku"
import type { ReactNode } from 'react';
import { WakuProvider } from 'fumadocs-core/framework/waku';
import { WakuProvider } from '@hanzo/docs/core/framework/waku';
export function Root({ children }: { children: ReactNode }) {
return <WakuProvider>{children}</WakuProvider>;
@@ -18,7 +18,7 @@ You can define a config to share between utilities.
To hide the locale prefix (e.g. `/en/page` -> `/page`), use the `hideLocale` option.
```ts
import { defineI18n } from 'fumadocs-core/i18n';
import { defineI18n } from '@hanzo/docs/core/i18n';
export const i18n = defineI18n({
defaultLanguage: 'en',
@@ -51,7 +51,7 @@ Supported:
- When set to `null`, no fallback will be used.
```ts
import { defineI18n } from 'fumadocs-core/i18n';
import { defineI18n } from '@hanzo/docs/core/i18n';
export const i18n = defineI18n({
languages: ['en', 'cn'],
@@ -9,7 +9,7 @@ Applies ids to headings.
```ts title="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkHeading } from 'fumadocs-core/mdx-plugins';
import { remarkHeading } from '@hanzo/docs/core/mdx-plugins';
await compile('...', {
remarkPlugins: [remarkHeading],
@@ -24,7 +24,7 @@ By default, it extracts the headings (table of contents) of a document to `vfile
You can disable it with:
```ts
import { remarkHeading } from 'fumadocs-core/mdx-plugins';
import { remarkHeading } from '@hanzo/docs/core/mdx-plugins';
export default {
remarkPlugins: [[remarkHeading, { generateToc: false }]],
@@ -54,7 +54,7 @@ Exports table of contents (an array of `TOCItemType`), it allows JSX nodes which
### Usage
```ts
import { rehypeToc } from 'fumadocs-core/mdx-plugins';
import { rehypeToc } from '@hanzo/docs/core/mdx-plugins';
export default {
rehypePlugins: [rehypeToc],
@@ -19,8 +19,8 @@ fumadocs-docgen
Add the remark plugin.
```ts title="source.config.ts" tab="Fumadocs MDX"
import { remarkInstall } from 'fumadocs-docgen';
import { defineConfig } from 'fumadocs-mdx/config';
import { remarkInstall } from '@hanzo/docs/docgen';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -31,7 +31,7 @@ export default defineConfig({
```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkInstall } from 'fumadocs-docgen';
import { remarkInstall } from '@hanzo/docs/docgen';
await compile('...', {
remarkPlugins: [remarkInstall],
@@ -41,8 +41,8 @@ await compile('...', {
Define the required components.
```tsx title="mdx-components.tsx (Fumadocs UI)"
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import defaultComponents from 'fumadocs-ui/mdx';
import { Tab, Tabs } from '@hanzo/docs/ui/components/tabs';
import defaultComponents from '@hanzo/docs/ui/mdx';
import type { MDXComponents } from 'mdx/types';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
@@ -96,8 +96,8 @@ my-package
When using with Fumadocs UI, you can enable persistence with the `persist` option.
```ts title="source.config.ts" tab="Fumadocs MDX"
import { remarkInstall } from 'fumadocs-docgen';
import { defineConfig } from 'fumadocs-mdx/config';
import { remarkInstall } from '@hanzo/docs/docgen';
import { defineConfig } from '@hanzo/docs/mdx/config';
const remarkInstallOptions = {
persist: {
@@ -114,7 +114,7 @@ export default defineConfig({
```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkInstall } from 'fumadocs-docgen';
import { remarkInstall } from '@hanzo/docs/docgen';
const remarkInstallOptions = {
persist: {
@@ -29,7 +29,7 @@ Add the rehype plugin.
```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { rehypeCode, type RehypeCodeOptions } from 'fumadocs-core/mdx-plugins';
import { rehypeCode, type RehypeCodeOptions } from '@hanzo/docs/core/mdx-plugins';
const rehypeCodeOptions: RehypeCodeOptions = {
themes: {
@@ -49,7 +49,7 @@ await compile('...', {
```
```ts tab="Fumadocs MDX"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -82,7 +82,7 @@ You may filter the meta string before processing it with the `filterMetaString`
You can enable it with `inline` option:
```ts
import { type RehypeCodeOptions } from 'fumadocs-core/mdx-plugins';
import { type RehypeCodeOptions } from '@hanzo/docs/core/mdx-plugins';
const rehypeCodeOptions: RehypeCodeOptions = {
// [!code ++]
@@ -19,8 +19,8 @@ Configure both plugins in your config.
```ts title="source.config.ts" tab="Fumadocs MDX"
import remarkDirective from 'remark-directive';
import { remarkDirectiveAdmonition } from 'fumadocs-core/mdx-plugins';
import { defineConfig } from 'fumadocs-mdx/config';
import { remarkDirectiveAdmonition } from '@hanzo/docs/core/mdx-plugins';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -31,7 +31,7 @@ export default defineConfig({
```ts tab="MDX Compiler"
import remarkDirective from 'remark-directive';
import { remarkDirectiveAdmonition } from 'fumadocs-core/mdx-plugins';
import { remarkDirectiveAdmonition } from '@hanzo/docs/core/mdx-plugins';
import { compile } from '@mdx-js/mdx';
await compile('...', {
@@ -11,7 +11,7 @@ Add it to your Remark plugins.
```ts title="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkImage } from 'fumadocs-core/mdx-plugins';
import { remarkImage } from '@hanzo/docs/core/mdx-plugins';
await compile('...', {
remarkPlugins: [remarkImage],
@@ -68,7 +68,7 @@ Where `./public/hello.png` points to the image in public directory.
For Next.js, you can disable static imports on local images.
```ts
import { remarkImage } from 'fumadocs-core/mdx-plugins';
import { remarkImage } from '@hanzo/docs/core/mdx-plugins';
export default {
remarkPlugins: [[remarkImage, { useImport: false }]],
@@ -109,7 +109,7 @@ For images in public directory, you can just reference them without relative pat
Customise the path of public directory
```ts
import { remarkImage } from 'fumadocs-core/mdx-plugins';
import { remarkImage } from '@hanzo/docs/core/mdx-plugins';
import path from 'node:path';
export default {
@@ -125,7 +125,7 @@ export default {
You can pass a URL too.
```ts
import { remarkImage } from 'fumadocs-core/mdx-plugins';
import { remarkImage } from '@hanzo/docs/core/mdx-plugins';
export default {
remarkPlugins: [
@@ -39,8 +39,8 @@ and convert into:
Add the remark plugin:
```tsx tab="Fumadocs MDX" title="source.config.ts"
import { remarkMdxFiles } from 'fumadocs-core/mdx-plugins';
import { defineConfig } from 'fumadocs-mdx/config';
import { remarkMdxFiles } from '@hanzo/docs/core/mdx-plugins';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -51,7 +51,7 @@ export default defineConfig({
```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkMdxFiles } from 'fumadocs-core/mdx-plugins';
import { remarkMdxFiles } from '@hanzo/docs/core/mdx-plugins';
await compile('...', {
remarkPlugins: [remarkMdxFiles],
@@ -9,7 +9,7 @@ Add the remark plugin.
```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkNpm } from 'fumadocs-core/mdx-plugins';
import { remarkNpm } from '@hanzo/docs/core/mdx-plugins';
await compile('...', {
remarkPlugins: [remarkNpm],
@@ -17,7 +17,7 @@ await compile('...', {
```
```ts title="source.config.ts" tab="Fumadocs MDX"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -51,7 +51,7 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents {
```
```tsx tab="Fumadocs UI" title="mdx-components.tsx"
import defaultComponents from 'fumadocs-ui/mdx';
import defaultComponents from '@hanzo/docs/ui/mdx';
import type { MDXComponents } from 'mdx/types';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
@@ -113,7 +113,7 @@ npm i my-package
When using with Fumadocs UI, you can enable persist the selected value with the `persist` option.
```ts title="source.config.ts" tab="Fumadocs MDX"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -128,7 +128,7 @@ export default defineConfig({
```ts tab="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkNpm, type RemarkNpmOptions } from 'fumadocs-core/mdx-plugins';
import { remarkNpm, type RemarkNpmOptions } from '@hanzo/docs/core/mdx-plugins';
const remarkNpmOptions: RemarkNpmOptions = {
persist: {
@@ -14,7 +14,7 @@ npm i fumadocs-docgen oxc-transform
For Next.js, externalize `oxc-transform`:
```js title="next.config.mjs (Next.js)"
import { createMDX } from 'fumadocs-mdx/next';
import { createMDX } from '@hanzo/docs/mdx/next';
/** @type {import('next').NextConfig} */
const config = {
@@ -30,8 +30,8 @@ export default withMDX(config);
Add the remark plugin:
```ts title="source.config.ts" tab="Fumadocs MDX"
import { remarkTypeScriptToJavaScript } from 'fumadocs-docgen/remark-ts2js';
import { defineConfig } from 'fumadocs-mdx/config';
import { remarkTypeScriptToJavaScript } from '@hanzo/docs/docgen/remark-ts2js';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -41,7 +41,7 @@ export default defineConfig({
```
```ts tab="MDX Compiler"
import { remarkTypeScriptToJavaScript } from 'fumadocs-docgen/remark-ts2js';
import { remarkTypeScriptToJavaScript } from '@hanzo/docs/docgen/remark-ts2js';
import { compile } from '@mdx-js/mdx';
await compile('...', {
@@ -52,8 +52,8 @@ await compile('...', {
Finally, make sure to define the required MDX components: `Tabs` and `Tab`.
```tsx title="mdx-components.tsx (Fumadocs UI)"
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import defaultComponents from 'fumadocs-ui/mdx';
import { Tab, Tabs } from '@hanzo/docs/ui/components/tabs';
import defaultComponents from '@hanzo/docs/ui/mdx';
import type { MDXComponents } from 'mdx/types';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
@@ -9,7 +9,7 @@ Add it as a remark plugin.
```ts title="MDX Compiler"
import { compile } from '@mdx-js/mdx';
import { remarkStructure } from 'fumadocs-core/mdx-plugins';
import { remarkStructure } from '@hanzo/docs/core/mdx-plugins';
const vfile = await compile('...', {
remarkPlugins: [remarkStructure],
@@ -54,7 +54,7 @@ array, each item contains a `heading` prop indicating the heading of paragraph.
Accepts MDX/markdown content and return structurized data.
```ts
import { structure } from 'fumadocs-core/mdx-plugins';
import { structure } from '@hanzo/docs/core/mdx-plugins';
structure(page.body.raw);
```
@@ -64,7 +64,7 @@ If you have custom remark plugins enabled, such as
`remark-math`, you have to pass these plugins to the function. This avoids unreadable content on paragraphs.
```ts
import { structure } from 'fumadocs-core/mdx-plugins';
import { structure } from '@hanzo/docs/core/mdx-plugins';
import remarkMath from 'remark-math';
structure(page.body.raw, [remarkMath]);
@@ -174,7 +174,7 @@ You can add an [`icon` handler](/docs/headless/source-api#icons) to `loader()`.
You can define different style for i18n routing.
```ts title="lib/i18n.ts"
import type { I18nConfig } from 'fumadocs-core/i18n';
import type { I18nConfig } from '@hanzo/docs/core/i18n';
export const i18n: I18nConfig = {
// default
@@ -22,7 +22,7 @@ The type definitions of page tree, for people who want to hardcode/generate it.
You can also import the type from Fumadocs.
```ts
import type * as PageTree from 'fumadocs-core/page-tree';
import type * as PageTree from '@hanzo/docs/core/page-tree';
const tree: PageTree.Root = {
// props
+5 -5
View File
@@ -1,8 +1,8 @@
import type * as Breadcrumb from 'fumadocs-core/breadcrumb';
import type * as TOC from 'fumadocs-core/toc';
import type * as Search from 'fumadocs-core/search';
import type * as PageTree from 'fumadocs-core/page-tree';
import type * as MDX from 'fumadocs-core/mdx-plugins';
import type * as Breadcrumb from '@hanzo/docs/core/breadcrumb';
import type * as TOC from '@hanzo/docs/core/toc';
import type * as Search from '@hanzo/docs/core/search';
import type * as PageTree from '@hanzo/docs/core/page-tree';
import type * as MDX from '@hanzo/docs/core/mdx-plugins';
export type SortedResult = Search.SortedResult;
@@ -47,7 +47,7 @@ Pre-render a static route `/static.json` to export search indexes into productio
```ts title="lib/export-search-indexes.ts"
import { source } from '@/lib/source';
import type { DocumentRecord } from 'fumadocs-core/search/algolia';
import type { DocumentRecord } from '@hanzo/docs/core/search/algolia';
export async function exportSearchIndexes() {
const results: DocumentRecord[] = [];
@@ -72,7 +72,7 @@ Make a script to sync search indexes:
```ts title="scripts/sync-content.ts" twoslash
import { algoliasearch } from 'algoliasearch';
import { sync, DocumentRecord } from 'fumadocs-core/search/algolia';
import { sync, DocumentRecord } from '@hanzo/docs/core/search/algolia';
import * as fs from 'node:fs';
// the path of pre-rendered `static.json`, choose one according to your React framework
@@ -119,7 +119,7 @@ You can consider different options for implementing the UI:
```ts twoslash
import { liteClient } from 'algoliasearch/lite';
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const client = liteClient('id', 'key');
@@ -140,7 +140,7 @@ To configure tag filtering, add a `tag` value to indexes.
```ts title="lib/export-search-indexes.ts"
import { source } from '@/lib/source';
import type { DocumentRecord } from 'fumadocs-core/search/algolia';
import type { DocumentRecord } from '@hanzo/docs/core/search/algolia';
export async function exportSearchIndexes() {
const results: DocumentRecord[] = [];
@@ -167,7 +167,7 @@ And update your search client:
- **Search Client**: You can add the tag filter like:
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const { search, setSearch, query } = useDocsSearch({
tag: '<your tag value>',
@@ -79,7 +79,7 @@ And update your search client:
- **Search Client**: You can add the tag filter like:
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const { search, setSearch, query } = useDocsSearch({
tag: '<your tag value>',
@@ -25,7 +25,7 @@ REST API integration requires your docs to upload the indexes.
```ts title="lib/export-search-indexes.ts"
import { source } from '@/lib/source';
import type { OramaDocument } from 'fumadocs-core/search/orama-cloud';
import type { OramaDocument } from '@hanzo/docs/core/search/orama-cloud';
export async function exportSearchIndexes() {
return source.getPages().map((page) => {
@@ -45,7 +45,7 @@ REST API integration requires your docs to upload the indexes.
3. Create a script to sync search indexes.
```ts title="scripts/sync-content.ts"
import { sync, type OramaDocument } from 'fumadocs-core/search/orama-cloud';
import { sync, type OramaDocument } from '@hanzo/docs/core/search/orama-cloud';
import * as fs from 'node:fs/promises';
import { OramaCloud } from '@orama/core';
@@ -95,7 +95,7 @@ To search documents on the client side, consider:
- Custom search UI using the built-in hook of Fumadocs:
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
import { OramaCloud } from '@orama/core';
const client = new OramaCloud({
@@ -124,7 +124,7 @@ To search documents on the client side, consider:
Same as REST API integration, but make sure to set `index` to `crawler`.
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
import { OramaCloud } from '@orama/core';
const client = new OramaCloud({
@@ -37,7 +37,7 @@ Usually, it is provided by your content source (e.g. Fumadocs MDX). You can also
```ts tab="Next.js" title="app/api/search/route.ts"
import { source } from '@/lib/source';
import { createSearchAPI } from 'fumadocs-core/search/server';
import { createSearchAPI } from '@hanzo/docs/core/search/server';
export const { GET } = createSearchAPI('advanced', {
language: 'english',
@@ -53,7 +53,7 @@ export const { GET } = createSearchAPI('advanced', {
```ts tab="React Router" title="app/docs/search.ts"
import type { Route } from './+types/search';
import { createSearchAPI } from 'fumadocs-core/search/server';
import { createSearchAPI } from '@hanzo/docs/core/search/server';
import { source } from '@/lib/source';
const server = createSearchAPI('advanced', {
@@ -75,7 +75,7 @@ export async function loader({ request }: Route.LoaderArgs) {
```ts tab="Tanstack Start" title="src/routes/api/search.ts"
import { createFileRoute } from '@tanstack/react-router';
import { source } from '@/lib/source';
import { createSearchAPI } from 'fumadocs-core/search/server';
import { createSearchAPI } from '@hanzo/docs/core/search/server';
const server = createSearchAPI('advanced', {
language: 'english',
@@ -99,7 +99,7 @@ export const Route = createFileRoute('/api/search')({
```ts tab="Waku" title="src/pages/api/search.ts"
import { source } from '@/lib/source';
import { createSearchAPI } from 'fumadocs-core/search/server';
import { createSearchAPI } from '@hanzo/docs/core/search/server';
export const { GET } = createSearchAPI('advanced', {
language: 'english',
@@ -121,7 +121,7 @@ You can search documents using:
- **Search Client**:
```ts twoslash
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const client = useDocsSearch({
type: 'fetch',
@@ -138,7 +138,7 @@ Support filtering results by tag, it's useful for implementing multi-docs simila
```ts
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { createFromSource } from '@hanzo/docs/core/search/server';
const server = createFromSource(source, {
buildIndex(page) {
@@ -161,7 +161,7 @@ and update your search client:
- **Search Client**: pass a tag to the hook.
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const client = useDocsSearch({
type: 'fetch',
@@ -175,7 +175,7 @@ To support usage with static site, use `staticGET` from search server and make t
```ts tab="Next.js" title="app/api/search/route.ts"
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { createFromSource } from '@hanzo/docs/core/search/server';
// statically cached [!code highlight:2]
export const revalidate = false;
@@ -222,7 +222,7 @@ export default defineConfig({
```ts tab="Waku" title="src/pages/api/search.ts"
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { createFromSource } from '@hanzo/docs/core/search/server';
// [!code highlight]
export const { staticGET: GET } = createFromSource(source);
@@ -242,7 +242,7 @@ and update your search clients:
- **Search Client**: use `static` instead of `fetch`.
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const client = useDocsSearch({
type: 'static',
@@ -266,7 +266,7 @@ Make sure your language is on the Orama [Supported Languages](https://docs.orama
```ts title="app/api/search/route.ts" tab="From Source"
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import { createFromSource } from '@hanzo/docs/core/search/server';
const server = createFromSource(source, {
localeMap: {
@@ -279,7 +279,7 @@ const server = createFromSource(source, {
```ts tab="From Search Indexes"
import { source } from '@/lib/source';
import { createI18nSearchAPI } from 'fumadocs-core/search/server';
import { createI18nSearchAPI } from '@hanzo/docs/core/search/server';
import { i18n } from '@/lib/i18n';
const server = createI18nSearchAPI('advanced', {
@@ -300,7 +300,7 @@ const server = createI18nSearchAPI('advanced', {
For **Static Mode**, you should configure from client-side instead:
```tsx title="components/search.tsx"
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
import { create } from '@orama/orama';
function initOrama(locale?: string) {
@@ -334,7 +334,7 @@ npm i @orama/tokenizers
</include>
```tsx tab="Static mode" title="components/search.tsx"
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
import { createTokenizer } from '@orama/tokenizers/mandarin';
import { create } from '@orama/orama';
@@ -364,7 +364,7 @@ and update your search clients:
Add `locale` to the search client, this will only allow pages with specified locale to be searchable by the user.
```ts
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useDocsSearch } from '@hanzo/docs/core/search/client';
const { search, setSearch, query } = useDocsSearch({
type: 'fetch',
@@ -377,7 +377,7 @@ const { search, setSearch, query } = useDocsSearch({
You can host the search server on other backend such as Express and Elysia.
```ts
import { initAdvancedSearch } from 'fumadocs-core/search/server';
import { initAdvancedSearch } from '@hanzo/docs/core/search/server';
const server = initAdvancedSearch({
// you still have to pass indexes
@@ -102,7 +102,7 @@ You can use their `SearchDialog` component:
```tsx title="components/search.tsx"
'use client';
import type { SharedProps } from 'fumadocs-ui/components/dialog/search';
import type { SharedProps } from '@hanzo/docs/ui/components/dialog/search';
import SearchDialog from 'trieve-fumadocs-adapter/components/dialog/search';
import { TrieveSDK } from 'trieve-ts-sdk';
@@ -18,8 +18,8 @@ It is a server-side API, but doesn't rely on the real file system (zero `node:fs
You can use it with built-in content sources like Fumadocs MDX.
```ts
import { loader } from 'fumadocs-core/source';
import { docs } from 'fumadocs-mdx:collections/server';
import { loader } from '@hanzo/docs/core/source';
import { docs } from '@hanzo/docs-mdx:collections/server';
export const source = loader({
source: docs.toFumadocsSource(),
@@ -32,7 +32,7 @@ export const source = loader({
You can override the base URL, or specify a function to generate URL for each page.
```ts
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
loader({
baseUrl: '/docs',
@@ -49,7 +49,7 @@ loader({
Load the [icon](/docs/headless/page-conventions#icons) property specified by pages and meta files.
```ts
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
import { icons } from 'lucide-react';
import { createElement } from 'react';
@@ -71,7 +71,7 @@ Pass the `i18n` config to loader.
```ts title="lib/source.ts"
import { i18n } from '@/lib/i18n';
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
i18n, // [!code highlight]
@@ -181,7 +181,7 @@ async function loader() {
```
```tsx tab="Client"
import { useFumadocsLoader } from 'fumadocs-core/source/client';
import { useFumadocsLoader } from '@hanzo/docs/core/source/client';
function MyComponent() {
// receives loader data
@@ -12,8 +12,8 @@ A list of built-in plugins:
- **Lucide Icons**: use icons from [Lucide React](https://lucide.dev) (require `lucide-react` to be installed).
```ts
import { loader } from 'fumadocs-core/source';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { loader } from '@hanzo/docs/core/source';
import { lucideIconsPlugin } from '@hanzo/docs/core/source/lucide-icons';
export const source = loader({
// ...
@@ -26,7 +26,7 @@ A list of built-in plugins:
Each plugin is an object:
```ts tab="Strictly Typed"
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
plugins: ({ typedPlugin }) => [
@@ -38,7 +38,7 @@ export const source = loader({
```
```ts tab="Simple"
import { loader, type LoaderPlugin } from 'fumadocs-core/source';
import { loader, type LoaderPlugin } from '@hanzo/docs/core/source';
export const source = loader({
plugins: [myPlugin()],
@@ -66,7 +66,7 @@ During the process, your input source files will be parsed and form a virtual st
To perform virtual file-system operations before processing, you can hook `transformStorage`.
```ts
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
plugins: ({ typedPlugin }) => [
@@ -86,7 +86,7 @@ The page tree is generated from your file system, some unnecessary information (
You can customise it using the `transformPageTree`, such as attaching custom properties to nodes, or customising the display name of pages.
```tsx
import { loader } from 'fumadocs-core/source';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
plugins: ({ typedPlugin }) => [
@@ -12,10 +12,10 @@ description: Setup sources for Loader API
Use `multiple` to combine multiple sources into one.
```ts
import { loader, multiple } from 'fumadocs-core/source';
import { openapiPlugin, openapiSource } from 'fumadocs-openapi/server';
import { blog, docs } from 'fumadocs-mdx:collections/server';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { loader, multiple } from '@hanzo/docs/core/source';
import { openapiPlugin, openapiSource } from '@hanzo/docs/openapi/server';
import { blog, docs } from '@hanzo/docs-mdx:collections/server';
import { lucideIconsPlugin } from '@hanzo/docs/core/source/lucide-icons';
export const source = loader(
multiple({
@@ -47,7 +47,7 @@ To plug your own content source, create a `Source` object.
Since Loader API doesn't rely on file system, file paths only allow virtual paths like `file.mdx` and `content/file.mdx`, `./file.mdx` and `D://content/file.mdx` are not allowed.
```ts twoslash
import { Source } from 'fumadocs-core/source';
import { Source } from '@hanzo/docs/core/source';
export function createMySource(): Source<{
metaData: { title: string; pages: string[] }; // Your custom type
@@ -11,7 +11,7 @@ previous page of a given page. It is useful for implementing a footer.
It requires a page tree and the url of page.
```ts
import { findNeighbour } from 'fumadocs-core/page-tree';
import { findNeighbour } from '@hanzo/docs/core/page-tree';
import { pageTree } from '@/lib/source';
const neighbours = findNeighbour(pageTree, '/url/to/page');
@@ -12,7 +12,7 @@ Parse Table of contents from markdown/mdx content.
Note: If you're using a CMS, you should use the API provided by the CMS instead.
```ts
import { getTableOfContents } from 'fumadocs-core/content/toc';
import { getTableOfContents } from '@hanzo/docs/core/content/toc';
const toc = getTableOfContents('## markdown content');
```
@@ -8,7 +8,7 @@ description: Get the last edit time of a file in Github repository
Pass your repository name, and the path to file.
```ts
import { getGithubLastEdit } from 'fumadocs-core/content/github';
import { getGithubLastEdit } from '@hanzo/docs/core/content/github';
const time = await getGithubLastEdit({
owner: 'fuma-nama',
@@ -27,7 +27,7 @@ Learn more about
[Authenticating to the REST API](https://docs.github.com/en/rest/overview/authenticating-to-the-rest-api).
```ts
import { getGithubLastEdit } from 'fumadocs-core/content/github'
import { getGithubLastEdit } from '@hanzo/docs/core/content/github'
const time = await getGithubLastEdit({
...,
@@ -47,7 +47,7 @@ process.env.NODE_ENV === 'development'? null : getGithubLastEdit(...)
If you need to access GitHub a instance at a url other than `https://api.github.com`, you can override the base URL:
```ts
import { getGithubLastEdit } from 'fumadocs-core/content/github';
import { getGithubLastEdit } from '@hanzo/docs/core/content/github';
const time = await getGithubLastEdit({
owner: 'your-org',
@@ -15,7 +15,7 @@ Serve markdown or HTML depending on the `Accept` header, this can improve the ex
```ts title="proxy.ts (Next.js)"
import { NextRequest, NextResponse } from 'next/server';
import { isMarkdownPreferred, rewritePath } from 'fumadocs-core/negotiation';
import { isMarkdownPreferred, rewritePath } from '@hanzo/docs/core/negotiation';
const { rewrite: rewriteLLM } = rewritePath('/docs/*path', '/llms.mdx/*path');
@@ -5,7 +5,7 @@ Setup an import alias (recommended):
"compilerOptions": {
"paths": {
// [!code ++]
"fumadocs-mdx:collections/*": [".source/*"]
"@hanzo/docs-mdx:collections/*": [".source/*"]
}
}
}
@@ -12,7 +12,7 @@ preload = ["./scripts/preload.ts"]
```
```ts tab="scripts/preload.ts"
import { createMdxPlugin } from 'fumadocs-mdx/bun';
import { createMdxPlugin } from '@hanzo/docs/mdx/bun';
Bun.plugin(createMdxPlugin());
```
@@ -29,13 +29,13 @@ It is useful when the folder could be missing,
or you are using Vite, which defaults to generating code with Vite-specific APIs.
```ts title="preload.ts" tab="Next.js"
import { postInstall } from 'fumadocs-mdx/next';
import { postInstall } from '@hanzo/docs/mdx/next';
await postInstall({ configPath: 'source.config.ts' });
```
```ts title="preload.ts" tab="Vite"
import { postInstall } from 'fumadocs-mdx/vite';
import { postInstall } from '@hanzo/docs/mdx/vite';
await postInstall({
configPath: 'source.config.ts',
@@ -13,13 +13,13 @@ Set up Fumadocs MDX for your Next.js application.
### Installation
```npm
npm i fumadocs-mdx fumadocs-core @types/mdx
npm i @hanzo/docs @types/mdx
```
Create the configuration file:
```ts title="source.config.ts"
import { defineDocs, defineConfig } from 'fumadocs-mdx/config';
import { defineDocs, defineConfig } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -31,7 +31,7 @@ export default defineConfig();
Add the plugin to Next.js config:
```js title="next.config.mjs"
import { createMDX } from 'fumadocs-mdx/next';
import { createMDX } from '@hanzo/docs/mdx/next';
/** @type {import('next').NextConfig} */
const config = {
@@ -61,8 +61,8 @@ export default withMDX(config);
You can create a `lib/source.ts` file and obtain Fumadocs source from the `docs` collection output.
```ts title="lib/source.ts"
import { docs } from 'fumadocs-mdx:collections/server';
import { loader } from 'fumadocs-core/source';
import { docs } from '@hanzo/docs-mdx:collections/server';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
baseUrl: '/docs',
@@ -10,13 +10,13 @@ description: Use Fumadocs MDX with Vite
### Installation
```npm
npm i fumadocs-mdx fumadocs-core @types/mdx
npm i @hanzo/docs @types/mdx
```
Create the configuration file:
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -27,7 +27,7 @@ Add the Vite plugin:
```ts tab="Vite" title="vite.config.ts"
import { defineConfig } from 'vite';
import mdx from 'fumadocs-mdx/vite';
import mdx from '@hanzo/docs/mdx/vite';
import * as MdxConfig from './source.config';
export default defineConfig({
@@ -41,7 +41,7 @@ export default defineConfig({
```ts tab="Waku" title="waku.config.ts"
import { type Config, defineConfig } from 'waku/config';
import mdx from 'fumadocs-mdx/vite';
import mdx from '@hanzo/docs/mdx/vite';
import * as MdxConfig from './source.config.js';
import tsconfigPaths from 'vite-tsconfig-paths';
import type { UserConfig } from 'vite';
@@ -66,8 +66,8 @@ export default defineConfig({
To integrate with Fumadocs, make a `lib/source.ts` file:
```ts title="app/lib/source.ts"
import { docs } from 'fumadocs-mdx:collections/server';
import { loader } from 'fumadocs-core/source';
import { docs } from '@hanzo/docs-mdx:collections/server';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
baseUrl: '/docs',
+4 -4
View File
@@ -14,7 +14,7 @@ This may result in longer dev server start times for large docs sites. You can e
Async mode will generate collection outputs using async imports.
```ts tab="Docs Collection"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -26,7 +26,7 @@ export const docs = defineDocs({
```
```ts tab="Doc Collection"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const doc = defineCollections({
type: 'doc',
@@ -54,7 +54,7 @@ npm i @fumadocs/mdx-remote shiki
```
```ts tab="Docs Collection"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
@@ -66,7 +66,7 @@ export const docs = defineDocs({
```
```ts tab="Doc Collection"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const doc = defineCollections({
type: 'doc',
+13 -13
View File
@@ -8,7 +8,7 @@ description: Collection of content data for your app
Define a collection to parse a certain set of files.
```ts
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
import { z } from 'zod';
export const blog = defineCollections({
@@ -26,7 +26,7 @@ export const blog = defineCollections({
The accepted type of collection.
```ts
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
// only scan for json/yaml files
export const metaFiles = defineCollections({
@@ -52,7 +52,7 @@ export const metaFiles = defineCollections({
The schema to validate file data (frontmatter on `doc` type, content on `meta` type).
```ts
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
import { z } from 'zod';
export const blog = defineCollections({
@@ -70,7 +70,7 @@ Note that the validation is done at build time, hence the output must be seriali
You can also pass a function that receives the transform context.
```ts
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
import { z } from 'zod';
export const blog = defineCollections({
@@ -95,7 +95,7 @@ Customise MDX options at the collection level.
> This API is only available on `doc` type.
```ts title="source.config.ts"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const blog = defineCollections({
type: 'doc',
@@ -111,7 +111,7 @@ You have full control over MDX options.
You can use [`applyMdxPreset`](/docs/mdx/mdx) to apply the default MDX preset.
```ts title="source.config.ts"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const blog = defineCollections({
type: 'doc',
@@ -132,7 +132,7 @@ You can pass build-time information to runtime using the `postprocess` API.
Include the processed Markdown content (before being converted into HTML).
```ts tab="docs"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export default defineDocs({
docs: {
@@ -145,7 +145,7 @@ You can pass build-time information to runtime using the `postprocess` API.
```
```ts tab="doc"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const blog = defineCollections({
type: 'doc',
@@ -172,7 +172,7 @@ You can pass build-time information to runtime using the `postprocess` API.
You can specify the name of properties to include, they will get converted into ESM exports that you can access when importing the MDX file.
```ts tab="docs"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export default defineDocs({
docs: {
@@ -185,7 +185,7 @@ You can pass build-time information to runtime using the `postprocess` API.
```
```ts tab="doc"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const blog = defineCollections({
type: 'doc',
@@ -201,7 +201,7 @@ You can pass build-time information to runtime using the `postprocess` API.
Define a collection for Fumadocs.
```ts
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: '/my/content/dir',
@@ -219,7 +219,7 @@ export const docs = defineDocs({
Instead of per collection, you should customise content directory from `defineDocs`:
```ts
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/guides',
@@ -231,7 +231,7 @@ export const docs = defineDocs({
You can extend the default Zod 4 schema of `docs` and `meta`.
```ts
import { frontmatterSchema, metaSchema, defineDocs } from 'fumadocs-mdx/config';
import { frontmatterSchema, metaSchema, defineDocs } from '@hanzo/docs/mdx/config';
import { z } from 'zod';
export const docs = defineDocs({
+3 -3
View File
@@ -10,7 +10,7 @@ The generated outputs are optimized using async imports to optimize for browser
Only doc/docs collections are accessible on browser.
```tsx
import browserCollections from 'fumadocs-mdx:collections/browser';
import browserCollections from '@hanzo/docs-mdx:collections/browser';
// unloaded entries
console.log(browserCollections['collection name'].raw);
@@ -62,7 +62,7 @@ The examples are for non-RSC usage, we recommend using RSC whenever possible for
import { createFileRoute, notFound } from '@tanstack/react-router';
import { createServerFn } from '@tanstack/react-start';
import { source } from '@/lib/source';
import browserCollections from 'fumadocs-mdx:collections/browser';
import browserCollections from '@hanzo/docs-mdx:collections/browser';
export const Route = createFileRoute('/docs/$')({
component: Page,
@@ -110,7 +110,7 @@ function Page() {
```tsx
import type { Route } from './+types/page';
import { source } from '@/lib/source';
import browserCollections from 'fumadocs-mdx:collections/browser';
import browserCollections from '@hanzo/docs-mdx:collections/browser';
export async function loader({ params }: Route.LoaderArgs) {
const slugs = params['*'].split('/').filter((v) => v.length > 0);
+5 -5
View File
@@ -11,8 +11,8 @@ It offers the same output as `server` entry, while compiled properties have to b
```ts tab="Docs (Meta + Doc)"
// [!code highlight]
import { docs } from 'fumadocs-mdx:collections/dynamic';
import { loader } from 'fumadocs-core/source';
import { docs } from '@hanzo/docs-mdx:collections/dynamic';
import { loader } from '@hanzo/docs/core/source';
export const source = loader({
baseUrl: '/docs',
@@ -22,9 +22,9 @@ export const source = loader({
```ts tab="Doc"
// [!code highlight]
import { blogPosts } from 'fumadocs-mdx:collections/dynamic';
import { toFumadocsSource } from 'fumadocs-mdx/runtime/server';
import { loader } from 'fumadocs-core/source';
import { blogPosts } from '@hanzo/docs-mdx:collections/dynamic';
import { toFumadocsSource } from '@hanzo/docs/mdx/runtime/server';
import { loader } from '@hanzo/docs/core/source';
export const blog = loader({
baseUrl: '/blog',
+2 -2
View File
@@ -62,7 +62,7 @@ export default function Content(props: ComponentProps<'main'>) {
It doesn't have **MDX components** by default, you have to provide them:
```tsx tab="mdx-components.tsx"
import defaultMdxComponents from 'fumadocs-ui/mdx';
import defaultMdxComponents from '@hanzo/docs/ui/mdx';
import type { MDXComponents } from 'mdx/types';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
@@ -77,7 +77,7 @@ export const useMDXComponents = getMDXComponents; // [!code ++]
```
```ts tab="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
+5 -5
View File
@@ -8,8 +8,8 @@ description: Accessing collection outputs from server.
While you can access the collections directly from entry file, we suggest using it with [`loader()`](/docs/headless/source-api#output).
```ts tab="Docs (Meta + Doc)"
import { docs } from 'fumadocs-mdx:collections/server';
import { loader } from 'fumadocs-core/source';
import { docs } from '@hanzo/docs-mdx:collections/server';
import { loader } from '@hanzo/docs/core/source';
// raw collection
console.log(docs);
@@ -21,9 +21,9 @@ export const source = loader({
```
```ts tab="Doc"
import { blogPosts } from 'fumadocs-mdx:collections/server';
import { toFumadocsSource } from 'fumadocs-mdx/runtime/server';
import { loader } from 'fumadocs-core/source';
import { blogPosts } from '@hanzo/docs-mdx:collections/server';
import { toFumadocsSource } from '@hanzo/docs/mdx/runtime/server';
import { loader } from '@hanzo/docs/core/source';
// raw collection
console.log(blogPosts);
+3 -3
View File
@@ -8,7 +8,7 @@ description: Customise Fumadocs MDX
Shared options of Fumadocs MDX.
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
// global options
@@ -22,7 +22,7 @@ export default defineConfig({
Customise the [default MDX preset](/docs/mdx/mdx).
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
import rehypeKatex from 'rehype-katex';
import remarkMath from 'remark-math';
@@ -38,7 +38,7 @@ export default defineConfig({
Or using the minimal preset:
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
+1 -1
View File
@@ -22,7 +22,7 @@ To display content from another Markdown/MDX file, specify its path relative to
Markdown (`.md`) files do not support JSX syntax. To use `<include />`, you need to configure `remark-directive`.
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
import remarkDirective from 'remark-directive';
export default defineConfig({
+3 -3
View File
@@ -23,7 +23,7 @@ Fumadocs MDX transforms collections into type-safe data, accessible in your app.
Compile Markdown & MDX files into a React Server Component, with useful properties like **Table of Contents**.
```ts title="source.config.ts"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const test = defineCollections({
type: 'doc',
@@ -38,7 +38,7 @@ export const test = defineCollections({
Transform YAML/JSON files into an array of data.
```ts title="source.config.ts"
import { defineCollections } from 'fumadocs-mdx/config';
import { defineCollections } from '@hanzo/docs/mdx/config';
export const test = defineCollections({
type: 'meta',
@@ -52,7 +52,7 @@ export const test = defineCollections({
Combination of `meta` and `doc` collections, which is needed for Fumadocs.
```ts title="source.config.ts"
import { defineDocs } from 'fumadocs-mdx/config';
import { defineDocs } from '@hanzo/docs/mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
+2 -2
View File
@@ -13,8 +13,8 @@ You can add the plugin from the config file.
</Callout>
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import lastModified from 'fumadocs-mdx/plugins/last-modified';
import { defineConfig } from '@hanzo/docs/mdx/config';
import lastModified from '@hanzo/docs/mdx/plugins/last-modified';
export default defineConfig({
// [!code ++]
+6 -6
View File
@@ -22,7 +22,7 @@ These plugins are applied by default:
Add other remark plugins with:
```ts tab="Global Config"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
import { myPlugin } from './remark-plugin';
export default defineConfig({
@@ -35,7 +35,7 @@ export default defineConfig({
```
```ts tab="Collection Config"
import { defineCollections, applyMdxPreset } from 'fumadocs-mdx/config';
import { defineCollections, applyMdxPreset } from '@hanzo/docs/mdx/config';
import { myPlugin } from './remark-plugin';
export const blog = defineCollections({
@@ -58,7 +58,7 @@ These plugins are applied by default:
Same as remark plugins, you can pass an array or a function to add other rehype plugins.
```ts tab="Global Config"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
import { myPlugin } from './rehype-plugin';
export default defineConfig({
@@ -69,7 +69,7 @@ export default defineConfig({
```
```ts tab="Collection Config"
import { defineCollections, applyMdxPreset } from 'fumadocs-mdx/config';
import { defineCollections, applyMdxPreset } from '@hanzo/docs/mdx/config';
import { myPlugin } from './rehype-plugin';
export const blog = defineCollections({
@@ -85,7 +85,7 @@ export const blog = defineCollections({
Customise the options of built-in plugins like:
```ts tab="Global Config"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
mdxOptions: {
@@ -103,7 +103,7 @@ export default defineConfig({
```
```ts tab="Collection Config"
import { defineCollections, applyMdxPreset } from 'fumadocs-mdx/config';
import { defineCollections, applyMdxPreset } from '@hanzo/docs/mdx/config';
export const blog = defineCollections({
type: 'doc',
+1 -1
View File
@@ -2,4 +2,4 @@ export type {
GlobalConfig,
DocCollection,
MetaCollection,
} from 'fumadocs-mdx/config';
} from '@hanzo/docs/mdx/config';
+6 -6
View File
@@ -32,7 +32,7 @@ They do not need to have its own `package.json`, only a config file is needed.
To define a workspace, add:
```ts title="source.config.ts"
import { defineConfig } from 'fumadocs-mdx/config';
import { defineConfig } from '@hanzo/docs/mdx/config';
export default defineConfig({
workspaces: {
@@ -56,7 +56,7 @@ By running dev or build server, you should see collection entries from all works
You can access the generated files of a workspace at `.source/{workspace}/*`. For example:
```ts title="lib/source.ts"
import { docs } from 'fumadocs-mdx:collections/my-workspace/server';
import { docs } from '@hanzo/docs-mdx:collections/my-workspace/server';
```
> The output location of root workspace is not changed.
@@ -64,9 +64,9 @@ import { docs } from 'fumadocs-mdx:collections/my-workspace/server';
To integrate multiple sources in Fumadocs, use [`multiple`](/docs/headless/source-api/source#multiple-sources):
```ts title="lib/source.ts"
import { loader, multiple } from 'fumadocs-core/source';
import { docs } from 'fumadocs-mdx:collections/server';
import * as MyWorkspace from 'fumadocs-mdx:collections/my-workspace/server';
import { loader, multiple } from '@hanzo/docs/core/source';
import { docs } from '@hanzo/docs-mdx:collections/server';
import * as MyWorkspace from '@hanzo/docs-mdx:collections/my-workspace/server';
export const source = loader(
multiple({
@@ -94,5 +94,5 @@ This is cruial for use cases like storing content across multiple repos, a simpi
- when a commit is made to the content in $T_n$, it triggers a GitHub action (or CI), which creates a new deployment on $A$.
- when a deployment is triggered on $A$:
- Fumadocs MDX handles each $T_n$ as a workspace.
- each workspace generates its own collection entries, e.g. `fumadocs-mdx:collections/{repo}/server`.
- each workspace generates its own collection entries, e.g. `@hanzo/docs-mdx:collections/{repo}/server`.
- Fumadocs `loader()` integrate multiple sources into one.

Some files were not shown because too many files have changed in this diff Show More