Chore: include shared.ts in all templates

This commit is contained in:
Fuma Nama
2026-03-24 23:42:04 +08:00
parent 5325290cd8
commit d0503708da
48 changed files with 366 additions and 152 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'create-fumadocs-app': patch
---
include shared.ts in all templates
@@ -1,4 +1,4 @@
import { getPageImage, source } from '@/lib/source';
import { getPageImage, getPageMarkdownUrl, source } from '@/lib/source';
import {
DocsBody,
DocsDescription,
@@ -11,7 +11,7 @@ import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/components/mdx';
import type { Metadata } from 'next';
import { createRelativeLink } from '@fumadocs/base-ui/mdx';
import { gitConfig } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
const params = await props.params;
@@ -19,15 +19,16 @@ export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
if (!page) notFound();
const MDX = page.data.body;
const markdownUrl = getPageMarkdownUrl(page).url;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription className="mb-0">{page.data.description}</DocsDescription>
<div className="flex flex-row gap-2 items-center border-b pb-6">
<MarkdownCopyButton markdownUrl={`${page.url}.mdx`} />
<MarkdownCopyButton markdownUrl={markdownUrl} />
<ViewOptionsPopover
markdownUrl={`${page.url}.mdx`}
markdownUrl={markdownUrl}
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${page.path}`}
/>
</div>
@@ -1,11 +1,11 @@
import { getLLMText, source } from '@/lib/source';
import { getLLMText, getPageMarkdownUrl, source } from '@/lib/source';
import { notFound } from 'next/navigation';
export const revalidate = false;
export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) {
const { slug } = await params;
const page = source.getPage(slug);
const page = source.getPage(slug?.slice(0, -1));
if (!page) notFound();
return new Response(await getLLMText(page), {
@@ -16,5 +16,7 @@ export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/doc
}
export function generateStaticParams() {
return source.generateParams();
return source.getPages().map((page) => ({
slug: getPageMarkdownUrl(page).segments,
}));
}
+3 -8
View File
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from '@fumadocs/base-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'My App',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
+11
View File
@@ -0,0 +1,11 @@
export const appName = 'My App';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+13 -3
View File
@@ -1,10 +1,11 @@
import { docs } from 'collections/server';
import { type InferPageType, loader } from 'fumadocs-core/source';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { docsContentRoute, docsImageRoute, docsRoute } from './shared';
// See https://fumadocs.dev/docs/headless/source-api for more info
export const source = loader({
baseUrl: '/docs',
baseUrl: docsRoute,
source: docs.toFumadocsSource(),
plugins: [lucideIconsPlugin()],
});
@@ -14,14 +15,23 @@ export function getPageImage(page: InferPageType<typeof source>) {
return {
segments,
url: `/og/docs/${segments.join('/')}`,
url: `${docsImageRoute}/${segments.join('/')}`,
};
}
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
return `# ${page.data.title}
return `# ${page.data.title} (${page.url})
${processed}`;
}
-8
View File
@@ -5,14 +5,6 @@ const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
async rewrites() {
return [
{
source: '/docs/:path*.mdx',
destination: '/llms.mdx/docs/:path*',
},
];
},
};
export default withMDX(config);
+29
View File
@@ -0,0 +1,29 @@
import { NextRequest, NextResponse } from 'next/server';
import { isMarkdownPreferred, rewritePath } from 'fumadocs-core/negotiation';
import { docsContentRoute, docsRoute } from './lib/shared';
const { rewrite: rewriteDocs } = rewritePath(
`${docsRoute}{/*path}`,
`${docsContentRoute}{/*path}/content.md`,
);
const { rewrite: rewriteSuffix } = rewritePath(
`${docsRoute}{/*path}.mdx`,
`${docsContentRoute}{/*path}/content.md`,
);
export default function proxy(request: NextRequest) {
const result = rewriteSuffix(request.nextUrl.pathname);
if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl));
}
if (isMarkdownPreferred(request)) {
const result = rewriteDocs(request.nextUrl.pathname);
if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl));
}
}
return NextResponse.next();
}
@@ -1,4 +1,4 @@
import { getPageImage, source } from '@/lib/source';
import { getPageImage, getPageMarkdownUrl, source } from '@/lib/source';
import {
DocsBody,
DocsDescription,
@@ -11,7 +11,7 @@ import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/components/mdx';
import type { Metadata } from 'next';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { gitConfig } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
const params = await props.params;
@@ -19,7 +19,7 @@ export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
if (!page) notFound();
const MDX = page.data.body;
const markdownUrl = `/llms.mdx/docs/${[...page.slugs, 'index.mdx'].join('/')}`;
const markdownUrl = getPageMarkdownUrl(page).url;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
@@ -1,11 +1,11 @@
import { getLLMText, source } from '@/lib/source';
import { getLLMText, getPageMarkdownUrl, source } from '@/lib/source';
import { notFound } from 'next/navigation';
export const revalidate = false;
export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) {
const { slug } = await params;
// remove the appended "index.mdx"
// remove the appended "content.md"
const page = source.getPage(slug?.slice(0, -1));
if (!page) notFound();
@@ -18,6 +18,6 @@ export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/doc
export function generateStaticParams() {
return source.getPages().map((page) => ({
slug: [...page.slugs, 'index.mdx'],
slug: getPageMarkdownUrl(page).segments,
}));
}
+3 -8
View File
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'My App',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
+11
View File
@@ -0,0 +1,11 @@
export const appName = 'My App';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+13 -3
View File
@@ -1,9 +1,10 @@
import { docs } from 'collections/server';
import { type InferPageType, loader } from 'fumadocs-core/source';
import { docsContentRoute, docsImageRoute, docsRoute } from './shared';
// See https://fumadocs.dev/docs/headless/source-api for more info
export const source = loader({
baseUrl: '/docs',
baseUrl: docsRoute,
source: docs.toFumadocsSource(),
plugins: [],
});
@@ -13,14 +14,23 @@ export function getPageImage(page: InferPageType<typeof source>) {
return {
segments,
url: `/og/docs/${segments.join('/')}`,
url: `${docsImageRoute}/${segments.join('/')}`,
};
}
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
return `# ${page.data.title}
return `# ${page.data.title} (${page.url})
${processed}`;
}
+5 -4
View File
@@ -1,4 +1,4 @@
import { getPageImage, source } from '@/lib/source';
import { getPageImage, getPageMarkdownUrl, source } from '@/lib/source';
import {
DocsBody,
DocsDescription,
@@ -11,7 +11,7 @@ import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/components/mdx';
import type { Metadata } from 'next';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { gitConfig } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
const params = await props.params;
@@ -19,15 +19,16 @@ export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
if (!page) notFound();
const MDX = page.data.body;
const markdownUrl = getPageMarkdownUrl(page).url;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription className="mb-0">{page.data.description}</DocsDescription>
<div className="flex flex-row gap-2 items-center border-b pb-6">
<MarkdownCopyButton markdownUrl={`${page.url}.mdx`} />
<MarkdownCopyButton markdownUrl={markdownUrl} />
<ViewOptionsPopover
markdownUrl={`${page.url}.mdx`}
markdownUrl={markdownUrl}
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${page.path}`}
/>
</div>
@@ -1,11 +1,11 @@
import { getLLMText, source } from '@/lib/source';
import { getLLMText, getPageMarkdownUrl, source } from '@/lib/source';
import { notFound } from 'next/navigation';
export const revalidate = false;
export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) {
const { slug } = await params;
const page = source.getPage(slug);
const page = source.getPage(slug?.slice(0, -1));
if (!page) notFound();
return new Response(await getLLMText(page), {
@@ -16,5 +16,8 @@ export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/doc
}
export function generateStaticParams() {
return source.generateParams();
return source.getPages().map((page) => ({
lang: page.locale,
slug: getPageMarkdownUrl(page).segments,
}));
}
+3 -8
View File
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'My App',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
+11
View File
@@ -0,0 +1,11 @@
export const appName = 'My App';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+13 -3
View File
@@ -1,10 +1,11 @@
import { docs } from 'collections/server';
import { type InferPageType, loader } from 'fumadocs-core/source';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { docsContentRoute, docsImageRoute, docsRoute } from './shared';
// See https://fumadocs.dev/docs/headless/source-api for more info
export const source = loader({
baseUrl: '/docs',
baseUrl: docsRoute,
source: docs.toFumadocsSource(),
plugins: [lucideIconsPlugin()],
});
@@ -14,14 +15,23 @@ export function getPageImage(page: InferPageType<typeof source>) {
return {
segments,
url: `/og/docs/${segments.join('/')}`,
url: `${docsImageRoute}/${segments.join('/')}`,
};
}
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
return `# ${page.data.title}
return `# ${page.data.title} (${page.url})
${processed}`;
}
-8
View File
@@ -5,14 +5,6 @@ const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
async rewrites() {
return [
{
source: '/docs/:path*.mdx',
destination: '/llms.mdx/docs/:path*',
},
];
},
};
export default withMDX(config);
+29
View File
@@ -0,0 +1,29 @@
import { NextRequest, NextResponse } from 'next/server';
import { isMarkdownPreferred, rewritePath } from 'fumadocs-core/negotiation';
import { docsContentRoute, docsRoute } from './lib/shared';
const { rewrite: rewriteDocs } = rewritePath(
`${docsRoute}{/*path}`,
`${docsContentRoute}{/*path}/content.md`,
);
const { rewrite: rewriteSuffix } = rewritePath(
`${docsRoute}{/*path}.mdx`,
`${docsContentRoute}{/*path}/content.md`,
);
export default function proxy(request: NextRequest) {
const result = rewriteSuffix(request.nextUrl.pathname);
if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl));
}
if (isMarkdownPreferred(request)) {
const result = rewriteDocs(request.nextUrl.pathname);
if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl));
}
}
return NextResponse.next();
}
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'React Router',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
@@ -0,0 +1,11 @@
export const appName = 'React Router';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+11 -1
View File
@@ -1,11 +1,21 @@
import { loader, type InferPageType } from 'fumadocs-core/source';
import { docs } from 'collections/server';
import { docsContentRoute, docsRoute } from './shared';
export const source = loader({
source: docs.toFumadocsSource(),
baseUrl: '/docs',
baseUrl: docsRoute,
});
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
+1 -1
View File
@@ -3,7 +3,7 @@ import { getLLMText, source } from '@/lib/source';
export async function loader({ params }: Route.LoaderArgs) {
const slugs = params['*'].split('/').filter((v) => v.length > 0);
// remove the appended "index.mdx" that's added to avoid React Router issues
// remove the appended "content.md"
slugs.pop();
const page = source.getPage(slugs);
if (!page) {
@@ -8,9 +8,10 @@ import {
MarkdownCopyButton,
ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import { source } from '@/lib/source';
import { getPageMarkdownUrl, source } from '@/lib/source';
import browserCollections from 'collections/browser';
import { baseOptions, gitConfig } from '@/lib/layout.shared';
import { baseOptions } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
import { useFumadocsLoader } from 'fumadocs-core/source/client';
import { useMDXComponents } from '@/components/mdx';
@@ -20,8 +21,8 @@ export async function loader({ params }: Route.LoaderArgs) {
if (!page) throw new Response('Not found', { status: 404 });
return {
slugs: page.slugs,
path: page.path,
markdownUrl: getPageMarkdownUrl(page).url,
pageTree: await source.serializePageTree(source.getPageTree()),
};
}
@@ -60,8 +61,7 @@ const clientLoader = browserCollections.docs.createClientLoader({
});
export default function Page({ loaderData }: Route.ComponentProps) {
const { pageTree, slugs, path } = useFumadocsLoader(loaderData);
const markdownUrl = `/llms.mdx/docs/${[...slugs, 'index.mdx'].join('/')}`;
const { pageTree, path, markdownUrl } = useFumadocsLoader(loaderData);
return (
<DocsLayout {...baseOptions()} tree={pageTree}>
@@ -19,7 +19,7 @@ export default {
for await (const entry of glob('**/*.mdx', { cwd: 'content/docs' })) {
const slugs = getSlugs(entry);
paths.push(getUrl(slugs), `/llms.mdx/docs/${[...slugs, 'index.mdx'].join('/')}`);
paths.push(getUrl(slugs), `/llms.mdx/docs/${[...slugs, 'content.md'].join('/')}`);
}
return paths;
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'React Router',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
+11
View File
@@ -0,0 +1,11 @@
export const appName = 'React Router';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+11 -1
View File
@@ -1,11 +1,21 @@
import { loader, type InferPageType } from 'fumadocs-core/source';
import { docs } from 'collections/server';
import { docsContentRoute, docsRoute } from './shared';
export const source = loader({
source: docs.toFumadocsSource(),
baseUrl: '/docs',
baseUrl: docsRoute,
});
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
+1
View File
@@ -3,6 +3,7 @@ import { getLLMText, source } from '@/lib/source';
export async function loader({ params }: Route.LoaderArgs) {
const slugs = params['*'].split('/').filter((v) => v.length > 0);
slugs.pop();
const page = source.getPage(slugs);
if (!page) {
return new Response('not found', { status: 404 });
+18 -4
View File
@@ -9,8 +9,9 @@ import {
import { RootProvider } from 'fumadocs-ui/provider/react-router';
import type { Route } from './+types/root';
import './app.css';
import { rewritePath } from 'fumadocs-core/negotiation';
import { isMarkdownPreferred, rewritePath } from 'fumadocs-core/negotiation';
import NotFound from './routes/not-found';
import { docsContentRoute, docsRoute } from '@/lib/shared';
export const links: Route.LinksFunction = () => [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
@@ -74,11 +75,24 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
);
}
const { rewrite: rewriteLLM } = rewritePath('/docs{/*path}.mdx', '/llms.mdx/docs{/*path}');
const { rewrite: rewriteDocs } = rewritePath(
`${docsRoute}{/*path}`,
`${docsContentRoute}{/*path}/content.md`,
);
const { rewrite: rewriteSuffix } = rewritePath(
`${docsRoute}{/*path}.mdx`,
`${docsContentRoute}{/*path}/content.md`,
);
const serverMiddleware: Route.MiddlewareFunction = async ({ request }, next) => {
const url = new URL(request.url);
const path = rewriteLLM(url.pathname);
if (path) return Response.redirect(new URL(path, url));
const suffixPath = rewriteSuffix(url.pathname);
if (suffixPath) return Response.redirect(new URL(suffixPath, url));
if (isMarkdownPreferred(request)) {
const docsPath = rewriteDocs(url.pathname);
if (docsPath) return Response.redirect(new URL(docsPath, url));
}
return next();
};
export const middleware = [serverMiddleware];
+5 -5
View File
@@ -8,9 +8,10 @@ import {
MarkdownCopyButton,
ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import { source } from '@/lib/source';
import { getPageMarkdownUrl, source } from '@/lib/source';
import browserCollections from 'collections/browser';
import { baseOptions, gitConfig } from '@/lib/layout.shared';
import { baseOptions } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
import { useFumadocsLoader } from 'fumadocs-core/source/client';
import { getPageImagePath } from '@/lib/og';
import { useMDXComponents } from '@/components/mdx';
@@ -21,8 +22,8 @@ export async function loader({ params }: Route.LoaderArgs) {
if (!page) throw new Response('Not found', { status: 404 });
return {
slugs: page.slugs,
path: page.path,
markdownUrl: getPageMarkdownUrl(page).url,
pageTree: await source.serializePageTree(source.getPageTree()),
imagePath: getPageImagePath(slugs),
};
@@ -65,8 +66,7 @@ const clientLoader = browserCollections.docs.createClientLoader({
});
export default function Page({ loaderData }: Route.ComponentProps) {
const { slugs, path, pageTree, imagePath } = useFumadocsLoader(loaderData);
const markdownUrl = `/llms.mdx/docs/${slugs.join('/')}`;
const { path, pageTree, imagePath, markdownUrl } = useFumadocsLoader(loaderData);
return (
<DocsLayout {...baseOptions()} tree={pageTree}>
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'Tanstack Start',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
@@ -0,0 +1,11 @@
export const appName = 'Tanstack Start';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+12 -2
View File
@@ -1,17 +1,27 @@
import { type InferPageType, loader } from 'fumadocs-core/source';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { docs } from 'collections/server';
import { docsContentRoute, docsRoute } from './shared';
export const source = loader({
source: docs.toFumadocsSource(),
baseUrl: '/docs',
baseUrl: docsRoute,
plugins: [lucideIconsPlugin()],
});
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
return `# ${page.data.title}
return `# ${page.data.title} (${page.url})
${processed}`;
}
@@ -1,7 +1,7 @@
import { createFileRoute, Link, notFound } from '@tanstack/react-router';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { createServerFn } from '@tanstack/react-start';
import { source } from '@/lib/source';
import { getPageMarkdownUrl, source } from '@/lib/source';
import browserCollections from 'collections/browser';
import {
DocsBody,
@@ -11,7 +11,8 @@ import {
MarkdownCopyButton,
ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import { baseOptions, gitConfig } from '@/lib/layout.shared';
import { baseOptions } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
import { staticFunctionMiddleware } from '@tanstack/start-static-server-functions';
import { useFumadocsLoader } from 'fumadocs-core/source/client';
import { Suspense } from 'react';
@@ -37,8 +38,8 @@ const loader = createServerFn({
if (!page) throw notFound();
return {
slugs: page.slugs,
path: page.path,
markdownUrl: getPageMarkdownUrl(page).url,
pageTree: await source.serializePageTree(source.getPageTree()),
};
});
@@ -75,8 +76,7 @@ const clientLoader = browserCollections.docs.createClientLoader({
});
function Page() {
const { pageTree, slugs, path } = useFumadocsLoader(Route.useLoaderData());
const markdownUrl = `/llms.mdx/docs/${[...slugs, 'index.mdx'].join('/')}`;
const { pageTree, path, markdownUrl } = useFumadocsLoader(Route.useLoaderData());
return (
<DocsLayout {...baseOptions()} tree={pageTree}>
@@ -6,7 +6,7 @@ export const Route = createFileRoute('/llms.mdx/docs/$')({
handlers: {
GET: async ({ params }) => {
const slugs = (params._splat ?? '').split('/');
// remove the appended "index.mdx" to avoid build issues
// remove the appended "content.md"
slugs.pop();
const page = source.getPage(slugs);
if (!page) throw notFound();
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'Tanstack Start',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
+11
View File
@@ -0,0 +1,11 @@
export const appName = 'Tanstack Start';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+12 -2
View File
@@ -1,17 +1,27 @@
import { InferPageType, loader } from 'fumadocs-core/source';
import { docs } from 'collections/server';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { docsContentRoute, docsRoute } from './shared';
export const source = loader({
source: docs.toFumadocsSource(),
baseUrl: '/docs',
baseUrl: docsRoute,
plugins: [lucideIconsPlugin()],
});
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
return `# ${page.data.title}
return `# ${page.data.title} (${page.url})
${processed}`;
}
@@ -1,7 +1,7 @@
import { createFileRoute, notFound } from '@tanstack/react-router';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { createServerFn } from '@tanstack/react-start';
import { source } from '@/lib/source';
import { getPageMarkdownUrl, source } from '@/lib/source';
import browserCollections from 'collections/browser';
import {
DocsBody,
@@ -11,7 +11,8 @@ import {
MarkdownCopyButton,
ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import { baseOptions, gitConfig } from '@/lib/layout.shared';
import { baseOptions } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
import { useFumadocsLoader } from 'fumadocs-core/source/client';
import { Suspense } from 'react';
import { useMDXComponents } from '@/components/mdx';
@@ -35,8 +36,8 @@ const serverLoader = createServerFn({
if (!page) throw notFound();
return {
slugs: page.slugs,
path: page.path,
markdownUrl: getPageMarkdownUrl(page).url,
pageTree: await source.serializePageTree(source.getPageTree()),
};
});
@@ -73,8 +74,7 @@ const clientLoader = browserCollections.docs.createClientLoader({
});
function Page() {
const { path, pageTree, slugs } = useFumadocsLoader(Route.useLoaderData());
const markdownUrl = `/llms.mdx/docs/${slugs.join('/')}`;
const { path, pageTree, markdownUrl } = useFumadocsLoader(Route.useLoaderData());
return (
<DocsLayout {...baseOptions()} tree={pageTree}>
@@ -6,6 +6,7 @@ export const Route = createFileRoute('/llms.mdx/docs/$')({
handlers: {
GET: async ({ params }) => {
const slugs = params._splat?.split('/') ?? [];
slugs.pop();
const page = source.getPage(slugs);
if (!page) throw notFound();
+18 -3
View File
@@ -1,17 +1,32 @@
import { createMiddleware, createStart } from '@tanstack/react-start';
import { rewritePath } from 'fumadocs-core/negotiation';
import { isMarkdownPreferred, rewritePath } from 'fumadocs-core/negotiation';
import { redirect } from '@tanstack/react-router';
import { docsContentRoute, docsRoute } from '@/lib/shared';
const { rewrite: rewriteLLM } = rewritePath('/docs{/*path}.mdx', '/llms.mdx/docs{/*path}');
const { rewrite: rewriteDocs } = rewritePath(
`${docsRoute}{/*path}`,
`${docsContentRoute}{/*path}/content.md`,
);
const { rewrite: rewriteSuffix } = rewritePath(
`${docsRoute}{/*path}.mdx`,
`${docsContentRoute}{/*path}/content.md`,
);
const llmMiddleware = createMiddleware().server(({ next, request }) => {
const url = new URL(request.url);
const path = rewriteLLM(url.pathname);
const path = rewriteSuffix(url.pathname);
if (path) {
throw redirect(new URL(path, url));
}
if (isMarkdownPreferred(request)) {
const docsPath = rewriteDocs(url.pathname);
if (docsPath) {
throw redirect(new URL(docsPath, url));
}
}
return next();
});
+3 -8
View File
@@ -1,16 +1,11 @@
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: 'Waku',
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
+11
View File
@@ -0,0 +1,11 @@
export const appName = 'Waku';
export const docsRoute = '/docs';
export const docsImageRoute = '/og/docs';
export const docsContentRoute = '/llms.mdx/docs';
// fill this with your actual GitHub info, for example:
export const gitConfig = {
user: 'fuma-nama',
repo: 'fumadocs',
branch: 'main',
};
+14 -2
View File
@@ -1,10 +1,11 @@
import { type InferPageType, loader } from 'fumadocs-core/source';
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
import { docs } from 'collections/server';
import { docsContentRoute, docsImageRoute, docsRoute } from './shared';
export const source = loader({
source: docs.toFumadocsSource(),
baseUrl: '/docs',
baseUrl: docsRoute,
plugins: [lucideIconsPlugin()],
});
@@ -13,12 +14,23 @@ export function getPageImage(slugs: string[]) {
return {
segments,
url: `/og/docs/${segments.join('/')}`,
url: `${docsImageRoute}/${segments.join('/')}`,
};
}
export function getPageMarkdownUrl(page: InferPageType<typeof source>) {
const segments = [...page.slugs, 'content.md'];
return {
segments,
url: `${docsContentRoute}/${segments.join('/')}`,
};
}
export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');
return `# ${page.data.title} (${page.url})
${processed}`;
}
@@ -4,7 +4,7 @@ import { unstable_notFound } from 'waku/router/server';
export async function GET(
_: Request,
{ params }: ApiContext<'/llms.mdx/docs/[...slugs]/index.mdx'>,
{ params }: ApiContext<'/llms.mdx/docs/[...slugs]/content.md'>,
) {
const slugs = params.slugs;
const page = source.getPage(slugs);
+3 -4
View File
@@ -1,4 +1,4 @@
import { source } from '@/lib/source';
import { getPageImage, getPageMarkdownUrl, source } from '@/lib/source';
import { PageProps } from 'waku/router';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import {
@@ -9,9 +9,8 @@ import {
MarkdownCopyButton,
ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import { getPageImage } from '@/lib/source';
import { unstable_notFound } from 'waku/router/server';
import { gitConfig } from '@/lib/layout.shared';
import { gitConfig } from '@/lib/shared';
import { getMDXComponents } from '@/components/mdx';
export default function Page({ slugs }: PageProps<'/docs/[...slugs]'>) {
@@ -19,7 +18,7 @@ export default function Page({ slugs }: PageProps<'/docs/[...slugs]'>) {
if (!page) unstable_notFound();
const MDX = page.data.body;
const markdownUrl = `/llms.mdx/docs/${[...page.slugs, 'index.mdx'].join('/')}`;
const markdownUrl = getPageMarkdownUrl(page).url;
return (
<DocsPage toc={page.data.toc}>
<meta property="og:image" content={getPageImage(slugs).url} />