mirror of
https://github.com/fosrl/docs-v2.git
synced 2026-10-03 03:09:09 +02:00
port mintlify to fumadocs
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import { source } from '@/lib/source';
|
||||
import {
|
||||
DocsBody,
|
||||
DocsDescription,
|
||||
DocsPage,
|
||||
DocsTitle,
|
||||
MarkdownCopyButton,
|
||||
ViewOptionsPopover,
|
||||
} from 'fumadocs-ui/layouts/notebook/page';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { getMDXComponents } from '@/components/mdx';
|
||||
import type { Metadata } from 'next';
|
||||
import { createRelativeLink } from 'fumadocs-ui/mdx';
|
||||
import { getPageImageUrl, getPageMarkdownUrl, gitConfig, siteUrl } from '@/lib/shared';
|
||||
import { AskAIAboutPage } from '@/components/ai/ask-page';
|
||||
import { SiteFooter } from '@/components/site-footer';
|
||||
import { AskBar } from '@/components/ai/ask-bar';
|
||||
|
||||
export default async function Page(props: PageProps<'/[[...slug]]'>) {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
const MDX = page.data.body;
|
||||
const markdownUrl = getPageMarkdownUrl(page).url;
|
||||
|
||||
return (
|
||||
<DocsPage
|
||||
toc={page.data.toc}
|
||||
full={page.data.full}
|
||||
tableOfContent={{ style: 'clerk' }}
|
||||
// rendered after the previous / next page links
|
||||
footer={{
|
||||
children: (
|
||||
<>
|
||||
<SiteFooter />
|
||||
<AskBar />
|
||||
</>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription className="mb-0">{page.data.description}</DocsDescription>
|
||||
<div className="flex flex-row flex-wrap gap-2 items-center border-b pb-6">
|
||||
<MarkdownCopyButton markdownUrl={markdownUrl} />
|
||||
<ViewOptionsPopover
|
||||
markdownUrl={markdownUrl}
|
||||
pageUrl={`${siteUrl}${page.url}`}
|
||||
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/${page.path}`}
|
||||
/>
|
||||
<AskAIAboutPage title={page.data.title} />
|
||||
</div>
|
||||
<DocsBody>
|
||||
<MDX
|
||||
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: PageProps<'/[[...slug]]'>): Promise<Metadata> {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
const isHome = page.slugs.length === 0;
|
||||
return {
|
||||
title: isHome ? { absolute: `${page.data.title} - Pangolin Docs` } : page.data.title,
|
||||
description: page.data.description,
|
||||
alternates: {
|
||||
canonical: page.url,
|
||||
types: { 'text/markdown': getPageMarkdownUrl(page).url },
|
||||
},
|
||||
openGraph: {
|
||||
images: isHome ? '/images/home-social-graph.png' : getPageImageUrl(page).url,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/notebook';
|
||||
import type { LayoutTab } from 'fumadocs-ui/layouts/shared';
|
||||
import { Banner } from 'fumadocs-ui/components/banner';
|
||||
import Link from 'fumadocs-core/link';
|
||||
import { baseOptions } from '@/lib/layout.shared';
|
||||
import { getNavigationTree, navTabs } from '@/lib/navigation';
|
||||
import { banner } from '@/lib/shared';
|
||||
import { source } from '@/lib/source';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { AISearch, AISearchPanel } from '@/components/ai/search';
|
||||
import { headerSearchSlot } from '@/components/header-search';
|
||||
import { SidebarAnchors } from '@/components/sidebar-anchors';
|
||||
|
||||
const tabs: LayoutTab[] = [
|
||||
// every docs page counts as the "Documentation" tab
|
||||
{ title: 'Documentation', url: '/', urls: new Set(source.getPages().map((page) => page.url)) },
|
||||
...navTabs.map((tab) => ({
|
||||
title: tab.label,
|
||||
url: tab.href,
|
||||
props: { target: '_blank', rel: 'noreferrer noopener' },
|
||||
})),
|
||||
];
|
||||
|
||||
/** Mintlify-style grid, defined as `--pg-grid` in app/global.css (responsive) */
|
||||
const containerStyle = { gridTemplate: 'var(--pg-grid)' } as CSSProperties;
|
||||
|
||||
export default function Layout({ children }: LayoutProps<'/'>) {
|
||||
return (
|
||||
<>
|
||||
<Banner id={banner.id} className="pg-banner">
|
||||
<p>
|
||||
<strong>AI Gateway</strong> is now available
|
||||
<span className="max-md:hidden">
|
||||
: identity-aware access to any AI provider, eliminate API keys, and tunnel to
|
||||
self-hosted models
|
||||
</span>
|
||||
.{' '}
|
||||
<Link href={banner.link.href} className="underline underline-offset-2 font-medium">
|
||||
{banner.link.label}
|
||||
</Link>
|
||||
</p>
|
||||
</Banner>
|
||||
{/* chat state wraps the whole layout so the header "Ask AI" button can open it */}
|
||||
<AISearch>
|
||||
<DocsLayout
|
||||
{...baseOptions()}
|
||||
slots={{ searchTrigger: headerSearchSlot }}
|
||||
tree={getNavigationTree()}
|
||||
nav={{ ...baseOptions().nav, mode: 'top' }}
|
||||
tabMode="navbar"
|
||||
tabs={tabs}
|
||||
sidebar={{
|
||||
defaultOpenLevel: 0,
|
||||
collapsible: false,
|
||||
banner: SidebarAnchors,
|
||||
}}
|
||||
containerProps={{ style: containerStyle }}
|
||||
>
|
||||
<AISearchPanel />
|
||||
{children}
|
||||
</DocsLayout>
|
||||
</AISearch>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user