From f90fd8f65a397c4b21f00d585527b71c67de9a71 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Tue, 21 Oct 2025 22:47:45 +0700 Subject: [PATCH] feat: add DocPage --- .mcp.json | 9 +- .../src/app/docs/api/text-to-image/page.tsx | 59 ++++---- .../app/docs/guides/authentication/page.tsx | 59 ++++---- apps/landing/src/app/docs/layout.tsx | 68 ++------- apps/landing/src/app/docs/page.tsx | 63 ++++---- .../src/components/docs/layout/DocPage.tsx | 136 ++++++++++++++++++ apps/landing/src/contexts/TocContext.tsx | 53 ------- 7 files changed, 244 insertions(+), 203 deletions(-) create mode 100644 apps/landing/src/components/docs/layout/DocPage.tsx delete mode 100644 apps/landing/src/contexts/TocContext.tsx diff --git a/.mcp.json b/.mcp.json index 0da2cd6..11633fe 100644 --- a/.mcp.json +++ b/.mcp.json @@ -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", diff --git a/apps/landing/src/app/docs/api/text-to-image/page.tsx b/apps/landing/src/app/docs/api/text-to-image/page.tsx index 93065e7..0d5fb8a 100644 --- a/apps/landing/src/app/docs/api/text-to-image/page.tsx +++ b/apps/landing/src/app/docs/api/text-to-image/page.tsx @@ -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 ( - + {/* Hero Section */} - {/* Next Steps */} -
- - Next Steps - - - - - - -
-
+ ); } diff --git a/apps/landing/src/app/docs/guides/authentication/page.tsx b/apps/landing/src/app/docs/guides/authentication/page.tsx index a8d1a73..e05dac7 100644 --- a/apps/landing/src/app/docs/guides/authentication/page.tsx +++ b/apps/landing/src/app/docs/guides/authentication/page.tsx @@ -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 ( - + {/* Hero Section */} - {/* Next Steps */} -
- - Next Steps - - - - - - -
-
+ ); } diff --git a/apps/landing/src/app/docs/layout.tsx b/apps/landing/src/app/docs/layout.tsx index 0f01a99..65616e6 100644 --- a/apps/landing/src/app/docs/layout.tsx +++ b/apps/landing/src/app/docs/layout.tsx @@ -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 - * 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 (
@@ -89,28 +54,17 @@ export default function DocsRootLayout({ children }: DocsRootLayoutProps) { ctaHref="/signup" /> - {/* Three-column Documentation Layout */} + {/* Two-column Documentation Layout */}
{/* Left Sidebar - Thin, minimal design */} - {/* Main Content Area - Wide margins for comfortable reading */} + {/* Main Content Area - Pages render here with their own article + TOC structure */}
-
- {/* Breadcrumb */} - - - {/* Page Content */} - {children} -
+ {children}
- - {/* Right TOC - Subtle and unobtrusive */} -
); diff --git a/apps/landing/src/app/docs/page.tsx b/apps/landing/src/app/docs/page.tsx index 969db2f..a1c3e0b 100644 --- a/apps/landing/src/app/docs/page.tsx +++ b/apps/landing/src/app/docs/page.tsx @@ -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 ( - + {/* Hero Section */} - {/* Next Steps - Simplified to 2 Cards */} -
- - Next Steps - -

- Now that you have generated your first image, explore these resources to build more advanced integrations: -

- - - - - -
-
+ ); } diff --git a/apps/landing/src/components/docs/layout/DocPage.tsx b/apps/landing/src/components/docs/layout/DocPage.tsx new file mode 100644 index 0000000..a14f9e1 --- /dev/null +++ b/apps/landing/src/components/docs/layout/DocPage.tsx @@ -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 + * + * + *
...
+ *
+ * ``` + */ + +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 ( +
+ {/* Article Content */} +
+ {/* Breadcrumb Navigation */} + + + {/* Page Content (Hero + Sections) */} + {children} + + {/* Next Steps Section */} +
+ + Next Steps + + + {nextSteps.description && ( +

+ {nextSteps.description} +

+ )} + + + {nextSteps.links.map((link, index) => ( + + ))} + +
+
+ + {/* Right TOC Sidebar */} + +
+ ); +}; diff --git a/apps/landing/src/contexts/TocContext.tsx b/apps/landing/src/contexts/TocContext.tsx deleted file mode 100644 index 7460375..0000000 --- a/apps/landing/src/contexts/TocContext.tsx +++ /dev/null @@ -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 - * - * - * - * ``` - * - * Usage in layout: - * ```tsx - * const { tocItems } = useToc(); - * return ; - * ``` - */ - -import { createContext, useContext, ReactNode } from 'react'; - -export interface TocItem { - id: string; - text: string; - level: number; -} - -interface TocContextValue { - tocItems: TocItem[]; -} - -const TocContext = createContext(undefined); - -interface TocProviderProps { - tocItems: TocItem[]; - children: ReactNode; -} - -export const TocProvider = ({ tocItems, children }: TocProviderProps) => { - return {children}; -}; - -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; -};