feat: add DocPage

This commit is contained in:
Oleg Proskurin 2025-10-21 22:47:45 +07:00
parent da33f96c35
commit f90fd8f65a
7 changed files with 244 additions and 203 deletions

View File

@ -33,11 +33,14 @@
"DATABASE_URI": "postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db"
}
},
"mastra": {
"perplexity": {
"type": "stdio",
"command": "npx",
"args": ["@mastra/mcp-docs-server@latest"],
"env": {}
"args": ["-y", "perplexity-mcp"],
"env": {
"PERPLEXITY_API_KEY": "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",
"PERPLEXITY_TIMEOUT_MS": "600000"
}
},
"browsermcp": {
"type": "stdio",

View File

@ -3,24 +3,23 @@
/**
* API Reference: Text to Image
*
* Refactored to use block components from @/components/docs/blocks
* Layout (SubsectionNav, DocsSidebar, Breadcrumb, TOC) handled by parent layout.tsx
* This page only provides TOC items and content.
* Refactored to use DocPage component for consistent layout
* Layout handles SubsectionNav and Left Sidebar
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
* This page provides only the content (Hero + sections)
*/
import { TipBox } from '@/components/docs/shared/TipBox';
import { Table } from '@/components/docs/shared/Table';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget';
import {
Hero,
SectionHeader,
InlineCode,
EndpointCard,
LinkCard,
LinkCardGrid,
} from '@/components/docs/blocks';
import { TocProvider } from '@/contexts/TocContext';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
@ -41,7 +40,30 @@ const parameters = [
export default function TextToImageAPIPage() {
return (
<TocProvider tocItems={tocItems}>
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'Text to Image' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/upload',
title: 'Upload API',
description: 'Learn how to upload reference images for image-to-image generation.',
accent: 'primary',
},
{
href: '/docs/guides/error-handling',
title: 'Error Handling',
description: 'Best practices for handling errors and retries in production.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
@ -199,27 +221,6 @@ export default function TextToImageAPIPage() {
/>
</section>
{/* Next Steps */}
<section id="next-steps" className="mb-12">
<SectionHeader level={2} id="next-steps" className="mb-6">
Next Steps
</SectionHeader>
<LinkCardGrid columns={2}>
<LinkCard
href="/docs/api/upload"
title="Upload API"
description="Learn how to upload reference images for image-to-image generation."
accent="primary"
/>
<LinkCard
href="/docs/guides/error-handling"
title="Error Handling"
description="Best practices for handling errors and retries in production."
accent="secondary"
/>
</LinkCardGrid>
</section>
</TocProvider>
</DocPage>
);
}

View File

@ -3,22 +3,21 @@
/**
* Authentication Guide
*
* Refactored to use block components from @/components/docs/blocks
* Layout (SubsectionNav, DocsSidebar, Breadcrumb, TOC) handled by parent layout.tsx
* This page only provides TOC items and content.
* Refactored to use DocPage component for consistent layout
* Layout handles SubsectionNav and Left Sidebar
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
* This page provides only the content (Hero + sections)
*/
import { TipBox } from '@/components/docs/shared/TipBox';
import { Table } from '@/components/docs/shared/Table';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
InlineCode,
LinkCard,
LinkCardGrid,
} from '@/components/docs/blocks';
import { TocProvider } from '@/contexts/TocContext';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
@ -33,7 +32,30 @@ const tocItems = [
export default function AuthenticationGuidePage() {
return (
<TocProvider tocItems={tocItems}>
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Guides', href: '/docs/guides' },
{ label: 'Authentication' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/text-to-image',
title: 'Start Generating Images',
description: 'Explore the Text to Image API and start building your integration.',
accent: 'primary',
},
{
href: '/docs/guides/error-handling',
title: 'Error Handling Guide',
description: 'Learn how to handle authentication errors and implement retry logic.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
@ -286,27 +308,6 @@ curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\
</div>
</section>
{/* Next Steps */}
<section id="next-steps" className="mb-12">
<SectionHeader level={2} id="next-steps" className="mb-6">
Next Steps
</SectionHeader>
<LinkCardGrid columns={2}>
<LinkCard
href="/docs/api/text-to-image"
title="Start Generating Images"
description="Explore the Text to Image API and start building your integration."
accent="primary"
/>
<LinkCard
href="/docs/guides/error-handling"
title="Error Handling Guide"
description="Learn how to handle authentication errors and implement retry logic."
accent="secondary"
/>
</LinkCardGrid>
</section>
</TocProvider>
</DocPage>
);
}

View File

@ -4,27 +4,24 @@ import { ReactNode } from 'react';
import { usePathname } from 'next/navigation';
import { SubsectionNav } from '@/components/shared/SubsectionNav';
import { DocsSidebar } from '@/components/docs/layout/DocsSidebar';
import { DocsTOC } from '@/components/docs/layout/DocsTOC';
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
import { useToc } from '@/contexts/TocContext';
/**
* Root Documentation Layout
*
* Centralized layout for all documentation pages providing:
* Provides shared layout elements for all documentation pages:
* - SubsectionNav at the top
* - Three-column layout (sidebar, content, TOC)
* - Automatic breadcrumb generation
* - Consistent background and styling
* - Left Sidebar (DocsSidebar)
* - Background gradients
* - Two-column flex wrapper (sidebar + main content)
*
* Pages only need to:
* 1. Wrap content with <TocProvider tocItems={...}>
* 2. Provide their content
* Pages handle their own:
* - Breadcrumbs (manually specified)
* - Article content
* - TOC sidebar (on the right)
*
* Features:
* - Animated gradient background matching landing page
* - Automatic active page detection via pathname
* - Auto-generated breadcrumbs from URL structure
* - Responsive layout (mobile tablet desktop)
*/
@ -38,40 +35,8 @@ const navItems = [
{ label: 'Examples', href: '/docs/examples' },
];
// Generate breadcrumb items from pathname
const getBreadcrumbItems = (pathname: string): { label: string; href?: string }[] => {
const segments = pathname.split('/').filter(Boolean);
if (segments.length === 1 && segments[0] === 'docs') {
return [
{ label: 'Documentation', href: '/docs' },
{ label: 'Getting Started' },
];
}
const items: { label: string; href?: string }[] = [
{ label: 'Documentation', href: '/docs' },
];
if (segments.includes('guides')) {
items.push({ label: 'Guides', href: '/docs/guides' });
if (segments.includes('authentication')) {
items.push({ label: 'Authentication' });
}
} else if (segments.includes('api')) {
items.push({ label: 'API Reference', href: '/docs/api' });
if (segments.includes('text-to-image')) {
items.push({ label: 'Text to Image' });
}
}
return items;
};
export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
const pathname = usePathname();
const { tocItems } = useToc();
const breadcrumbItems = getBreadcrumbItems(pathname);
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
@ -89,28 +54,17 @@ export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
ctaHref="/signup"
/>
{/* Three-column Documentation Layout */}
{/* Two-column Documentation Layout */}
<div className="relative z-10 flex">
{/* Left Sidebar - Thin, minimal design */}
<aside className="hidden lg:block w-64 border-r border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
<DocsSidebar currentPath={pathname} />
</aside>
{/* Main Content Area - Wide margins for comfortable reading */}
{/* Main Content Area - Pages render here with their own article + TOC structure */}
<main className="flex-1 min-w-0">
<div className="max-w-3xl mx-auto px-6 lg:px-12 py-12">
{/* Breadcrumb */}
<Breadcrumb items={breadcrumbItems} />
{/* Page Content */}
{children}
</div>
</main>
{/* Right TOC - Subtle and unobtrusive */}
<aside className="hidden xl:block w-56 border-l border-white/10 bg-slate-950/30 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
<DocsTOC items={tocItems} />
</aside>
</div>
</div>
);

View File

@ -3,21 +3,20 @@
/**
* Getting Started Page - Production Documentation
*
* Refactored to use block components from @/components/docs/blocks
* Layout (SubsectionNav, DocsSidebar, Breadcrumb, TOC) handled by parent layout.tsx
* This page only provides TOC items and content.
* Refactored to use DocPage component for consistent layout
* Layout handles SubsectionNav and Left Sidebar
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
* This page provides only the content (Hero + sections)
*/
import { TipBox } from '@/components/docs/shared/TipBox';
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
ResponseBlock,
LinkCard,
LinkCardGrid,
} from '@/components/docs/blocks';
import { TocProvider } from '@/contexts/TocContext';
const tocItems = [
{ id: 'introduction', text: 'Introduction', level: 2 },
@ -30,7 +29,31 @@ const tocItems = [
export default function GettingStartedPage() {
return (
<TocProvider tocItems={tocItems}>
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Getting Started' },
]}
tocItems={tocItems}
nextSteps={{
description:
'Now that you have generated your first image, explore these resources to build more advanced integrations:',
links: [
{
href: '/docs/api/text-to-image',
title: 'API Reference',
description: 'Explore all available endpoints, parameters, and response formats.',
accent: 'primary',
},
{
href: '/docs/guides/authentication',
title: 'Authentication Guide',
description: 'Learn about API keys, rate limits, and security best practices.',
accent: 'secondary',
},
],
}}
>
{/* Hero Section */}
<Hero
@ -168,30 +191,6 @@ export BANATIE_API_KEY="bnt_your_key_here"`}
</div>
</section>
{/* Next Steps - Simplified to 2 Cards */}
<section id="next-steps" className="mb-12">
<SectionHeader level={2} id="next-steps" className="mb-6">
Next Steps
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Now that you have generated your first image, explore these resources to build more advanced integrations:
</p>
<LinkCardGrid columns={2}>
<LinkCard
href="/docs/api/text-to-image"
title="API Reference"
description="Explore all available endpoints, parameters, and response formats."
accent="primary"
/>
<LinkCard
href="/docs/guides/authentication"
title="Authentication Guide"
description="Learn about API keys, rate limits, and security best practices."
accent="secondary"
/>
</LinkCardGrid>
</section>
</TocProvider>
</DocPage>
);
}

View File

@ -0,0 +1,136 @@
'use client';
/**
* Documentation Page Layout Component
*
* Provides consistent structure for all documentation pages:
* - Breadcrumb navigation at top
* - Article content area (passed as children)
* - Next Steps section at bottom
* - Table of Contents sidebar on the right
*
* This component extracts common layout patterns from all doc pages,
* reducing duplication and ensuring consistency.
*
* Usage:
* ```tsx
* <DocPage
* breadcrumbItems={[...]}
* tocItems={[...]}
* nextSteps={{ description: "...", links: [...] }}
* >
* <Hero ... />
* <section>...</section>
* </DocPage>
* ```
*/
import { ReactNode } from 'react';
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
import { DocsTOC } from '@/components/docs/layout/DocsTOC';
import { SectionHeader, LinkCard, LinkCardGrid } from '@/components/docs/blocks';
/**
* Next step link card configuration
*/
export interface NextStepLink {
href: string;
title: string;
description: string;
accent: 'primary' | 'secondary' | 'success' | 'warning';
}
/**
* Table of Contents item
*/
export interface TocItem {
id: string;
text: string;
level: number;
}
/**
* Breadcrumb navigation item
*/
export interface BreadcrumbItem {
label: string;
href?: string;
}
/**
* DocPage component props
*/
export interface DocPageProps {
/** Breadcrumb navigation items (top of page) */
breadcrumbItems: BreadcrumbItem[];
/** Table of contents items (right sidebar) */
tocItems: TocItem[];
/** Next steps section configuration */
nextSteps: {
/** Optional description text before link cards */
description?: string;
/** Link cards to display (typically 2) */
links: NextStepLink[];
};
/** Page content (Hero, sections, etc.) */
children: ReactNode;
}
/**
* Documentation Page Layout Component
*
* Wraps documentation content with consistent structure including
* breadcrumbs, TOC sidebar, and next steps section.
*/
export const DocPage = ({
breadcrumbItems,
tocItems,
nextSteps,
children,
}: DocPageProps) => {
return (
<div className="flex">
{/* Article Content */}
<article className="flex-1 max-w-3xl mx-auto px-6 lg:px-12 py-12">
{/* Breadcrumb Navigation */}
<Breadcrumb items={breadcrumbItems} />
{/* Page Content (Hero + Sections) */}
{children}
{/* Next Steps Section */}
<section id="next-steps" className="mb-12">
<SectionHeader level={2} id="next-steps" className="mb-6">
Next Steps
</SectionHeader>
{nextSteps.description && (
<p className="text-gray-300 leading-relaxed mb-6">
{nextSteps.description}
</p>
)}
<LinkCardGrid columns={2}>
{nextSteps.links.map((link, index) => (
<LinkCard
key={index}
href={link.href}
title={link.title}
description={link.description}
accent={link.accent}
/>
))}
</LinkCardGrid>
</section>
</article>
{/* Right TOC Sidebar */}
<aside className="hidden xl:block w-56 border-l border-white/10 bg-slate-950/30 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
<DocsTOC items={tocItems} />
</aside>
</div>
);
};

View File

@ -1,53 +0,0 @@
'use client';
/**
* Table of Contents Context
*
* Allows documentation pages to pass their TOC items up to the layout
* so the layout can render the TOC in the right sidebar.
*
* Usage in pages:
* ```tsx
* <TocProvider tocItems={[...]}>
* <page content>
* </TocProvider>
* ```
*
* Usage in layout:
* ```tsx
* const { tocItems } = useToc();
* return <DocsTOC items={tocItems} />;
* ```
*/
import { createContext, useContext, ReactNode } from 'react';
export interface TocItem {
id: string;
text: string;
level: number;
}
interface TocContextValue {
tocItems: TocItem[];
}
const TocContext = createContext<TocContextValue | undefined>(undefined);
interface TocProviderProps {
tocItems: TocItem[];
children: ReactNode;
}
export const TocProvider = ({ tocItems, children }: TocProviderProps) => {
return <TocContext.Provider value={{ tocItems }}>{children}</TocContext.Provider>;
};
export const useToc = (): TocContextValue => {
const context = useContext(TocContext);
if (!context) {
// Return empty array if no provider (allows layout to work without TOC)
return { tocItems: [] };
}
return context;
};