feat: implement new documentation layout and enhance middleware

- Added a new layout configuration for documentation with internationalization support.
- Created a dedicated DocsRootLayout and associated providers for better structure.
- Updated middleware to refine route handling for documentation.
- Removed outdated layout configurations and components to streamline the codebase.
- Enhanced localization support for documentation in English and Chinese.
This commit is contained in:
javayhu 2025-03-29 11:39:44 +08:00
parent 45d46082f2
commit c81447e2ef
11 changed files with 130 additions and 60 deletions

View File

@ -1,4 +1,4 @@
import { source } from '@/lib/source';
import { source } from '@/lib/docs/source';
import { MDXContent } from '@content-collections/mdx/react';
import defaultMdxComponents, { createRelativeLink } from 'fumadocs-ui/mdx';
import {

View File

@ -0,0 +1,36 @@
import { ThemeSwitcher } from '@/components/layout/theme-switcher';
import { Logo } from '@/components/logo';
import { websiteConfig } from '@/config';
import { defaultMessages } from '@/i18n/messages';
import { docsI18nConfig } from '@/lib/docs/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
/**
* Docs layout configurations
*
* https://fumadocs.vercel.app/docs/ui/layouts/docs
*/
export const baseOptions: BaseLayoutProps = {
i18n: docsI18nConfig,
githubUrl: websiteConfig.social.github ?? undefined,
nav: {
title: (
<>
<Logo className="size-6" />
{defaultMessages.Metadata.name}
</>
),
},
links: [
{
text: 'Homepage',
url: '/',
active: 'nested-url',
}
],
themeSwitch: {
enabled: true,
mode: 'light-dark-system',
component: <ThemeSwitcher />
},
};

View File

@ -0,0 +1,52 @@
import { baseOptions } from '@/app/[locale]/docs/layout.config';
import { source } from '@/lib/docs/source';
import { Translations } from 'fumadocs-ui/i18n';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { Locale } from 'next-intl';
import type { ReactNode } from 'react';
import { DocsProviders } from './providers-docs';
import { I18nProvider } from 'fumadocs-ui/i18n';
import '@/styles/docs.css';
const cn: Partial<Translations> = {
toc: '目录',
search: '搜索文档',
lastUpdate: '最后更新于',
searchNoResult: '没有结果',
previousPage: '上一页',
nextPage: '下一页',
chooseLanguage: '选择语言',
};
// available languages that will be displayed on UI
// make sure `locale` is consistent with your i18n config
const locales = [
{
name: 'English',
locale: 'en',
},
{
name: 'Chinese',
locale: 'cn',
},
];
interface DocsLayoutProps {
children: ReactNode;
params: Promise<{ locale: Locale }>;
}
export default async function DocsRootLayout({ children, params }: DocsLayoutProps) {
const { locale } = await params;
return (
<DocsProviders>
<I18nProvider locales={locales} locale={locale} translations={cn}>
<DocsLayout tree={source.pageTree[locale]} {...baseOptions}>
{children}
</DocsLayout>
</I18nProvider>
</DocsProviders>
);
}

View File

@ -0,0 +1,24 @@
'use client';
import { RootProvider } from 'fumadocs-ui/provider';
import { useTheme } from 'next-themes';
import { ReactNode } from 'react';
interface DocsProvidersProps {
children: ReactNode;
}
/***
* Docs Configuration
*
* https://fumadocs.vercel.app/docs/ui/theme#lightdark-modes
*/
export function DocsProviders({ children }: DocsProvidersProps) {
const theme = useTheme();
return (
<RootProvider theme={theme}>
{children}
</RootProvider>
);
}

View File

@ -34,7 +34,7 @@ export default async function LocaleLayout({
}
return (
<html lang={locale} suppressHydrationWarning>
<html suppressHydrationWarning lang={locale}>
<body
suppressHydrationWarning
className={cn(

View File

@ -1,4 +1,4 @@
import { source } from '@/lib/source';
import { source } from '@/lib/docs/source';
import { createFromSource } from 'fumadocs-core/search/server';
export const { GET } = createFromSource(source);

View File

@ -1,34 +0,0 @@
import { defaultMessages } from '@/i18n/messages';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
/**
* Shared layout configurations
*
* you can customise layouts individually from:
* Home Layout: app/(home)/layout.tsx
* Docs Layout: app/docs/layout.tsx
*/
export const baseOptions: BaseLayoutProps = {
nav: {
title: (
<>
<svg
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
aria-label="Logo"
>
<circle cx={12} cy={12} r={12} fill="currentColor" />
</svg>
{defaultMessages.Metadata.name}
</>
),
},
links: [
{
text: 'Documentation',
url: '/docs',
active: 'nested-url',
},
],
};

View File

@ -1,22 +0,0 @@
import { baseOptions } from '@/app/docs/layout.config';
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { RootProvider } from 'fumadocs-ui/provider';
import type { ReactNode } from 'react';
import { fontDMSans } from '@/assets/fonts';
import '@/styles/docs.css';
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={fontDMSans.className} suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<RootProvider>
<DocsLayout tree={source.pageTree} {...baseOptions}>
{children}
</DocsLayout>
</RootProvider>
</body>
</html>
);
}

12
src/lib/docs/i18n.ts Normal file
View File

@ -0,0 +1,12 @@
import { DEFAULT_LOCALE, LOCALES } from '@/i18n/routing';
import type { I18nConfig } from 'fumadocs-core/i18n';
/**
* Internationalization configuration for FumaDocs
*
* https://fumadocs.vercel.app/docs/ui/internationalization
*/
export const docsI18nConfig: I18nConfig = {
defaultLanguage: DEFAULT_LOCALE,
languages: LOCALES,
};

View File

@ -1,8 +1,10 @@
import { allDocs, allMetas } from 'content-collections';
import { loader } from 'fumadocs-core/source';
import { createMDXSource } from '@fumadocs/content-collections';
import { docsI18nConfig } from './i18n';
export const source = loader({
baseUrl: '/docs',
i18n: docsI18nConfig,
source: createMDXSource(allDocs, allMetas),
});

View File

@ -23,6 +23,6 @@ export const config = {
// (e.g. `/pathnames` -> `/zh/pathnames`)
// Exclude API routes and other Next.js internal routes
// if not exclude api routes, auth routes will not work
'/((?!api|_next|_vercel|docs|.*\\..*).*)',
'/((?!api|_next|_vercel|.*\\..*).*)',
],
};