make example for Python docs

This commit is contained in:
Fuma Nama
2025-04-18 09:22:52 +08:00
parent e9fc458be5
commit c50ca3f405
35 changed files with 492 additions and 189 deletions
+2
View File
@@ -0,0 +1,2 @@
content/docs/httpx
httpx.json
+7
View File
@@ -0,0 +1,7 @@
import type { ReactNode } from 'react';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/app/layout.config';
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions}>{children}</HomeLayout>;
}
+19
View File
@@ -0,0 +1,19 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main className="flex flex-1 flex-col justify-center text-center">
<h1 className="mb-4 text-2xl font-bold">Hello World</h1>
<p className="text-fd-muted-foreground">
You can open{' '}
<Link
href="/docs"
className="text-fd-foreground font-semibold underline"
>
/docs
</Link>{' '}
and see the documentation.
</p>
</main>
);
}
+4
View File
@@ -0,0 +1,4 @@
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
export const { GET } = createFromSource(source);
@@ -0,0 +1,52 @@
import { source } from '@/lib/source';
import {
DocsPage,
DocsBody,
DocsDescription,
DocsTitle,
} from 'fumadocs-ui/page';
import { notFound } from 'next/navigation';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { getMDXComponents } from '@/mdx-components';
export default async function Page(props: {
params: Promise<{ slug?: string[] }>;
}) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
const MDXContent = page.data.body;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<MDXContent
components={getMDXComponents({
// this allows you to link to other pages with relative file paths
a: createRelativeLink(source, page),
})}
/>
</DocsBody>
</DocsPage>
);
}
export async function generateStaticParams() {
return source.generateParams();
}
export async function generateMetadata(props: {
params: Promise<{ slug?: string[] }>;
}) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
return {
title: page.data.title,
description: page.data.description,
};
}
+12
View File
@@ -0,0 +1,12 @@
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import type { ReactNode } from 'react';
import { baseOptions } from '@/app/layout.config';
import { source } from '@/lib/source';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout tree={source.pageTree} {...baseOptions}>
{children}
</DocsLayout>
);
}
+6
View File
@@ -0,0 +1,6 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
@import 'fumadocs-python/preset.css';
@source '../node_modules/fumadocs-ui/dist/**/*.js';
+21
View File
@@ -0,0 +1,21 @@
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: 'Python Docs',
},
links: [
{
text: 'Documentation',
url: '/docs',
active: 'nested-url',
},
],
};
+18
View File
@@ -0,0 +1,18 @@
import './global.css';
import { RootProvider } from 'fumadocs-ui/provider';
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';
const inter = Inter({
subsets: ['latin'],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className} suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
+13
View File
@@ -0,0 +1,13 @@
---
title: Hello World
description: Your first document
---
Welcome to the docs! You can start writing documents in `/content/docs`.
## What is Next?
<Cards>
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
<Card title="Learn more about Fumadocs" href="https://fumadocs.vercel.app" />
</Cards>
+9
View File
@@ -0,0 +1,9 @@
import { docs } from '@/.source';
import { loader } from 'fumadocs-core/source';
// See https://fumadocs.vercel.app/docs/headless/source-api for more info
export const source = loader({
// it assigns a URL to your pages
baseUrl: '/docs',
source: docs.toFumadocsSource(),
});
+12
View File
@@ -0,0 +1,12 @@
import defaultMdxComponents from 'fumadocs-ui/mdx';
import type { MDXComponents } from 'mdx/types';
import * as Python from 'fumadocs-python/components';
// use this function to get MDX components, you will need it for rendering MDX
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
...defaultMdxComponents,
...Python,
...components,
};
}
+10
View File
@@ -0,0 +1,10 @@
import { createMDX } from 'fumadocs-mdx/next';
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
};
export default withMDX(config);
+31
View File
@@ -0,0 +1,31 @@
{
"name": "example-python",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "pnpm build:docs && next build",
"dev": "next dev --turbo",
"start": "next start",
"build:docs": "node ./scripts/generate-docs.mjs",
"python:generate": "pip3 install ./node_modules/fumadocs-python && fumapy-generate httpx"
},
"dependencies": {
"fumadocs-core": "workspace:*",
"fumadocs-mdx": "workspace:*",
"fumadocs-ui": "workspace:*",
"fumadocs-python": "workspace:*",
"next": "15.3.1",
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.3",
"@types/mdx": "^2.0.13",
"@types/node": "22.14.1",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.2",
"postcss": "^8.5.3",
"tailwindcss": "^4.1.3",
"typescript": "^5.8.3"
}
}
+5
View File
@@ -0,0 +1,5 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
+19
View File
@@ -0,0 +1,19 @@
import { rimraf } from 'rimraf';
import * as Python from 'fumadocs-python';
import * as fs from 'node:fs/promises';
async function generate() {
const pythonOUt = 'content/docs/httpx';
await rimraf(pythonOUt);
const content = JSON.parse((await fs.readFile('./httpx.json')).toString());
const converted = Python.convert(content, {
baseUrl: '/docs',
});
await Python.write(converted, {
outDir: pythonOUt,
});
}
void generate();
+12
View File
@@ -0,0 +1,12 @@
import { defineDocs, defineConfig } from 'fumadocs-mdx/config';
// Options: https://fumadocs.vercel.app/docs/mdx/collections#define-docs
export const docs = defineDocs({
dir: 'content/docs',
});
export default defineConfig({
mdxOptions: {
// MDX options
},
});
+30
View File
@@ -0,0 +1,30 @@
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/.source": ["./.source/index.ts"],
"@/*": ["./*"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}