From da476348059f9259d7746ed79726732130ba749b Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Mon, 13 Oct 2025 00:19:57 +0700 Subject: [PATCH 01/11] chore: preview variants --- apps/landing/src/app/docs/layout.tsx | 32 ++ apps/landing/src/app/docs/page.tsx | 269 ++++++++++++ .../docs/variant-a/api/text-to-image/page.tsx | 299 +++++++++++++ .../variant-a/guides/authentication/page.tsx | 300 +++++++++++++ apps/landing/src/app/docs/variant-a/page.tsx | 208 +++++++++ .../docs/variant-b/api/text-to-image/page.tsx | 304 ++++++++++++++ .../variant-b/guides/authentication/page.tsx | 305 ++++++++++++++ apps/landing/src/app/docs/variant-b/page.tsx | 211 ++++++++++ .../docs/variant-c/api/text-to-image/page.tsx | 369 ++++++++++++++++ .../variant-c/guides/authentication/page.tsx | 370 +++++++++++++++++ apps/landing/src/app/docs/variant-c/page.tsx | 268 ++++++++++++ .../src/components/docs/shared/Breadcrumb.tsx | 73 ++++ .../src/components/docs/shared/CodeBlock.tsx | 69 +++ .../components/docs/variant-a/DocsLayoutA.tsx | 62 +++ .../docs/variant-a/DocsSidebarA.tsx | 178 ++++++++ .../components/docs/variant-a/DocsTOCA.tsx | 102 +++++ .../docs/variant-a/InteractiveAPIWidgetA.tsx | 293 +++++++++++++ .../components/docs/variant-b/DocsLayoutB.tsx | 62 +++ .../docs/variant-b/DocsSidebarB.tsx | 205 +++++++++ .../components/docs/variant-b/DocsTOCB.tsx | 141 +++++++ .../docs/variant-b/InteractiveAPIWidgetB.tsx | 291 +++++++++++++ .../components/docs/variant-c/DocsLayoutC.tsx | 74 ++++ .../docs/variant-c/DocsSidebarC.tsx | 238 +++++++++++ .../components/docs/variant-c/DocsTOCC.tsx | 212 ++++++++++ .../docs/variant-c/InteractiveAPIWidgetC.tsx | 393 ++++++++++++++++++ 25 files changed, 5328 insertions(+) create mode 100644 apps/landing/src/app/docs/layout.tsx create mode 100644 apps/landing/src/app/docs/page.tsx create mode 100644 apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx create mode 100644 apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx create mode 100644 apps/landing/src/app/docs/variant-a/page.tsx create mode 100644 apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx create mode 100644 apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx create mode 100644 apps/landing/src/app/docs/variant-b/page.tsx create mode 100644 apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx create mode 100644 apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx create mode 100644 apps/landing/src/app/docs/variant-c/page.tsx create mode 100644 apps/landing/src/components/docs/shared/Breadcrumb.tsx create mode 100644 apps/landing/src/components/docs/shared/CodeBlock.tsx create mode 100644 apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx create mode 100644 apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx create mode 100644 apps/landing/src/components/docs/variant-a/DocsTOCA.tsx create mode 100644 apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx create mode 100644 apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx create mode 100644 apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx create mode 100644 apps/landing/src/components/docs/variant-b/DocsTOCB.tsx create mode 100644 apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx create mode 100644 apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx create mode 100644 apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx create mode 100644 apps/landing/src/components/docs/variant-c/DocsTOCC.tsx create mode 100644 apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx diff --git a/apps/landing/src/app/docs/layout.tsx b/apps/landing/src/app/docs/layout.tsx new file mode 100644 index 0000000..7c810cb --- /dev/null +++ b/apps/landing/src/app/docs/layout.tsx @@ -0,0 +1,32 @@ +import { ReactNode } from 'react'; + +/** + * Root Documentation Layout + * + * Simple wrapper for all documentation pages. + * Each variant handles its own layout/navigation. + * + * Features: + * - Consistent background gradient matching landing page + * - No navigation/sidebars at this level + * - Children render their own layouts + */ + +interface DocsRootLayoutProps { + children: ReactNode; +} + +export default function DocsRootLayout({ children }: DocsRootLayoutProps) { + return ( +
+ {/* Animated gradient background (matching landing page) */} +
+
+
+
+ + {/* Content */} +
{children}
+
+ ); +} diff --git a/apps/landing/src/app/docs/page.tsx b/apps/landing/src/app/docs/page.tsx new file mode 100644 index 0000000..34fdbce --- /dev/null +++ b/apps/landing/src/app/docs/page.tsx @@ -0,0 +1,269 @@ +'use client'; + +/** + * Documentation Variants Comparison Page + * + * Landing page that introduces users to the three documentation design variants. + * Helps users choose the variant that best suits their preferences. + * + * Three Variants: + * - Variant A: Clean & Minimal (Vercel-inspired) + * - Variant B: Dense & Information-Rich (Next.js docs-inspired) + * - Variant C: Modern & Visual (Shopify-inspired) + * + * Design: + * - Hero section explaining the concept + * - Three large gradient-bordered cards + * - Visual preview descriptions + * - Clear CTAs to each variant + */ + +export default function DocsIndexPage() { + return ( +
+ {/* Header with back to home */} +
+
+ + + + + Back to Home + +
Choose Your Documentation Style
+
+
+ +
+ {/* Hero Section */} +
+
+ πŸ“š + DOCUMENTATION +
+

+ Choose Your Documentation Style +

+

+ We've created three distinct documentation designs. Pick the style that works best for + youβ€”same content, different presentation. +

+
+ + {/* Variant Cards */} +
+ {/* Variant A: Clean & Minimal */} + +
✨
+

+ Variant A +

+

Clean & Minimal

+

+ Vercel-inspired spacious layout with generous whitespace, focused reading experience, + and subtle visual hierarchy. +

+ +
+
+ + + + Wide margins, comfortable reading +
+
+ + + + Subtle borders and minimal design +
+
+ + + + Focus on content clarity +
+
+ +
+ Explore Variant A + + + +
+
+ + {/* Variant B: Dense & Information-Rich */} + +
πŸ“Š
+

+ Variant B +

+

Dense & Information-Rich

+

+ Next.js docs-inspired compact layout with section numbers, nested navigation, and + maximum information density per screen. +

+ +
+
+ + + + Compact spacing, more content visible +
+
+ + + + Section numbers (1., 2.1, etc.) +
+
+ + + + Hierarchical nested tree navigation +
+
+ +
+ Explore Variant B + + + +
+
+ + {/* Variant C: Modern & Visual */} + +
🎨
+

+ Variant C +

+

Modern & Visual

+

+ Shopify-inspired colorful card-based design with large emoji icons, gradient borders, + and playful engaging visual style. +

+ +
+
+ + + + Colorful gradient borders everywhere +
+
+ + + + Large emoji icons and visual elements +
+
+ + + + Fun, engaging, playful design +
+
+ +
+ Explore Variant C + + + +
+
+
+ + {/* Feature Comparison */} +
+

+ All Variants Include +

+
+
+
πŸ“š
+

Same Content

+

+ Identical API documentation, just styled differently +

+
+
+
⚑
+

Interactive Widgets

+

+ Live API testing with your own keys +

+
+
+
πŸ”
+

Navigation & Search

+

+ Sidebar, TOC, and breadcrumb navigation +

+
+
+
+ + {/* Footer CTA */} +
+

+ Not sure which to choose? Try all three and see which feels right! +

+

+ Each variant links to the same API contentβ€”pick your preferred reading experience. +

+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx b/apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx new file mode 100644 index 0000000..61e796c --- /dev/null +++ b/apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx @@ -0,0 +1,299 @@ +'use client'; + +/** + * API Reference: Text to Image - Variant A: Clean & Minimal + * + * This page demonstrates the interactive API reference design with live code execution. + * Features placeholder content and a fully functional API widget. + */ + +import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA'; +import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA'; +import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { InteractiveAPIWidgetA } from '@/components/docs/variant-a/InteractiveAPIWidgetA'; + +const tocItems = [ + { id: 'overview', text: 'Overview', level: 2 }, + { id: 'endpoint', text: 'Endpoint', level: 2 }, + { id: 'request', text: 'Request', level: 2 }, + { id: 'headers', text: 'Headers', level: 3 }, + { id: 'body', text: 'Body Parameters', level: 3 }, + { id: 'response', text: 'Response', level: 2 }, + { id: 'examples', text: 'Examples', level: 2 }, + { id: 'errors', text: 'Error Codes', level: 2 }, +]; + +export default function TextToImageAPIPageA() { + return ( + } + toc={} + > + + + {/* Hero Section */} +
+
+ POST +
+

Text to Image

+

+ Generate high-quality images from text prompts using AI-powered models. +

+
+ + {/* Overview */} +
+

Overview

+

+ The Text to Image endpoint generates images from text descriptions. It supports various + aspect ratios, automatic prompt enhancement, and optional reference images for style + matching. +

+
+

+ Tip: Enable autoEnhance for better results. The AI will optimize your + prompt for higher quality outputs while preserving your intent. +

+
+
+ + {/* Endpoint */} +
+

Endpoint

+
+ POST + https://api.banatie.com/api/text-to-image +
+
+ + {/* Request */} +
+

Request

+ +
+

Headers

+
+ + + + + + + + + + + + + + + + + + + + +
HeaderValueRequired
X-API-KeyYour project API key + Yes +
Content-Typeapplication/json + Yes +
+
+
+ +
+

Body Parameters

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescriptionRequired
promptstringText description of the image to generate + Yes +
filenamestringName for the generated image file + Yes +
aspectRatiostring + Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9 + + No +
autoEnhancebooleanEnable automatic prompt enhancement (default: true) + No +
enhancementOptionsobjectTemplate and enhancement settings + No +
+
+
+
+ + {/* Interactive API Widget */} + + + {/* Response */} +
+

Response

+

+ Returns a JSON object with the generated image URL and metadata. +

+ +
+
+            {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
+    "filepath": "org/project/generated/2025-01/city.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "originalPrompt": "a futuristic city at sunset",
+      "enhancedPrompt": "A breathtaking futuristic cityscape...",
+      "template": "photorealistic"
+    },
+    "generatedAt": "2025-01-15T10:30:00Z"
+  }
+}`}
+          
+
+
+ + {/* Examples */} +
+

Examples

+ +
+
+

Basic Image Generation

+

Generate a simple image with default settings

+
+
+                {`{
+  "prompt": "a serene mountain landscape",
+  "filename": "mountain"
+}`}
+              
+
+
+ +
+

Custom Aspect Ratio

+

Generate a widescreen image

+
+
+                {`{
+  "prompt": "cinematic space battle scene",
+  "filename": "space_battle",
+  "aspectRatio": "21:9"
+}`}
+              
+
+
+
+
+ + {/* Error Codes */} +
+

Error Codes

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CodeDescription
400Invalid request parameters
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx b/apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx new file mode 100644 index 0000000..535e8bb --- /dev/null +++ b/apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx @@ -0,0 +1,300 @@ +'use client'; + +/** + * Guide: Authentication - Variant A: Clean & Minimal + * + * This page demonstrates a guide/tutorial style page with step-by-step instructions. + * Features placeholder content focused on authentication concepts. + */ + +import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA'; +import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA'; +import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'overview', text: 'Overview', level: 2 }, + { id: 'api-keys', text: 'API Keys', level: 2 }, + { id: 'key-types', text: 'Key Types', level: 3 }, + { id: 'creating-keys', text: 'Creating Keys', level: 3 }, + { id: 'using-keys', text: 'Using API Keys', level: 2 }, + { id: 'security', text: 'Security Best Practices', level: 2 }, + { id: 'rate-limits', text: 'Rate Limits', level: 2 }, +]; + +export default function AuthenticationGuidePageA() { + return ( + } + toc={} + > + + + {/* Hero Section */} +
+
+ GUIDE +
+

Authentication

+

+ Learn how to authenticate your requests and manage API keys securely. +

+
+ + {/* Overview */} +
+

Overview

+

+ Banatie uses API keys to authenticate requests. Each request must include a valid API key + in the X-API-Key header. API keys are tied to your organization and project, providing + secure, isolated access to resources. +

+
+

+ Security First: Never expose your API keys in client-side code, public + repositories, or logs. Treat them like passwords. +

+
+
+ + {/* API Keys */} +
+

API Keys

+ +
+

Key Types

+

+ Banatie provides two types of API keys, each with different permissions and use cases: +

+ +
+
+
+
+ πŸ”‘ +
+
+

Master Keys

+

+ Full administrative access to your organization. Can create and revoke other + keys, access all projects, and manage settings. +

+
    +
  • β€’ Never expire
  • +
  • β€’ Full API access
  • +
  • β€’ One per organization (initially)
  • +
  • β€’ Should be kept extremely secure
  • +
+
+
+
+ +
+
+
+ 🎫 +
+
+

Project Keys

+

+ Scoped to a specific project. Used for image generation and resource access + within that project only. +

+
    +
  • β€’ Expire after 90 days
  • +
  • β€’ Project-specific access
  • +
  • β€’ Rate limited
  • +
  • β€’ Safe for production use
  • +
+
+
+
+
+
+ +
+

Creating Keys

+ +
+

Bootstrap Your First Key

+

+ When setting up Banatie for the first time, create your initial master key using the + bootstrap endpoint: +

+ +
+

+ Important: This endpoint can only be used once. Save the returned + key immediately - it will never be shown again. +

+
+
+ +
+

Create Project Keys

+

+ Use your master key to create project-specific keys: +

+ +
+
+
+ + {/* Using Keys */} +
+

Using API Keys

+

+ Include your API key in every request using the X-API-Key header: +

+ + +
+ + {/* Security */} +
+

Security Best Practices

+ +
+
+
πŸ”’
+
+

Never Commit Keys

+

+ Use environment variables or secret management tools. Never commit keys to version + control. +

+
+
+ +
+
πŸ”„
+
+

Rotate Keys Regularly

+

+ Project keys expire after 90 days. Plan for rotation and implement graceful + handling. +

+
+
+ +
+
🚫
+
+

Server-Side Only

+

+ Never use API keys in client-side code. Always make requests from your backend. +

+
+
+ +
+
πŸ‘οΈ
+
+

Monitor Usage

+

+ Track API key usage patterns. Unusual activity may indicate a compromised key. +

+
+
+
+
+ + {/* Rate Limits */} +
+

Rate Limits

+

+ To ensure fair usage and system stability, all API keys are subject to rate limits: +

+ +
+ + + + + + + + + + + + + + + + + + + + +
Key TypeLimitWindow
Master Key500 requestsper hour
Project Key100 requestsper hour
+
+ +
+

+ Need Higher Limits? Contact our sales team to discuss enterprise plans + with custom rate limits. +

+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-a/page.tsx b/apps/landing/src/app/docs/variant-a/page.tsx new file mode 100644 index 0000000..972c2e6 --- /dev/null +++ b/apps/landing/src/app/docs/variant-a/page.tsx @@ -0,0 +1,208 @@ +'use client'; + +/** + * Getting Started Page - Variant A: Clean & Minimal + * + * This is the main landing page for the documentation. + * Features placeholder content to demonstrate the layout and design. + */ + +import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA'; +import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA'; +import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'introduction', text: 'Introduction', level: 2 }, + { id: 'quick-start', text: 'Quick Start', level: 2 }, + { id: 'installation', text: 'Installation', level: 3 }, + { id: 'authentication', text: 'Authentication', level: 3 }, + { id: 'first-request', text: 'Your First Request', level: 2 }, + { id: 'next-steps', text: 'Next Steps', level: 2 }, +]; + +export default function GettingStartedPageA() { + return ( + } + toc={} + > + + + {/* Hero Section */} +
+

Getting Started

+

+ Welcome to the Banatie API documentation. Learn how to integrate AI-powered image + generation into your applications in minutes. +

+
+ + {/* Introduction */} +
+

Introduction

+

+ Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini + 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into + production-ready visuals. +

+

+ Whether you're building a content creation platform, e-commerce site, or creative tool, + Banatie provides the infrastructure you need to generate high-quality images at scale. +

+
+ + {/* Quick Start */} +
+

Quick Start

+ +
+

Installation

+

+ Banatie is a REST API, so you don't need to install any libraries. However, we provide + SDKs for popular languages to make integration easier. +

+ + +
+ +
+

Authentication

+

+ All API requests require an API key. You can create an API key from your dashboard or + using the bootstrap endpoint for initial setup. +

+ +
+

+ Note: Keep your API keys secure. Never commit them to public + repositories or expose them in client-side code. +

+
+ + +
+
+ + {/* First Request */} +
+

Your First Request

+

+ Let's generate your first image! This example uses curl, but you can use any HTTP client + or our SDKs. +

+ + + +
+

Response:

+
+            {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
+    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "enhancedPrompt": "A breathtaking mountain landscape..."
+    }
+  }
+}`}
+          
+
+
+ + {/* Next Steps */} +
+

Next Steps

+ + +
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx b/apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx new file mode 100644 index 0000000..3c830bd --- /dev/null +++ b/apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx @@ -0,0 +1,304 @@ +'use client'; + +/** + * API Reference: Text to Image - Variant B: Dense & Information-Rich + * + * Design Philosophy: Compact, information-dense layout with section numbers + * + * Key Differences from Variant A: + * - Section numbers in all headings (1., 1.1, 1.2, etc.) + * - More compact spacing (mb-6 vs mb-12, p-3 vs p-4) + * - Smaller text sizes throughout + * - Denser tables and narrower content + */ + +import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB'; +import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB'; +import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { InteractiveAPIWidgetB } from '@/components/docs/variant-b/InteractiveAPIWidgetB'; + +const tocItems = [ + { id: 'overview', text: '1. Overview', level: 2 }, + { id: 'endpoint', text: '2. Endpoint', level: 2 }, + { id: 'request', text: '3. Request', level: 2 }, + { id: 'headers', text: '3.1 Headers', level: 3 }, + { id: 'body', text: '3.2 Body Parameters', level: 3 }, + { id: 'response', text: '4. Response', level: 2 }, + { id: 'examples', text: '5. Examples', level: 2 }, + { id: 'errors', text: '6. Error Codes', level: 2 }, +]; + +export default function TextToImageAPIPageB() { + return ( + } + toc={} + > + + + {/* Hero Section - More compact */} +
+
+ POST +
+

Text to Image

+

+ Generate high-quality images from text prompts using AI-powered models. +

+
+ + {/* Overview */} +
+

1. Overview

+

+ The Text to Image endpoint generates images from text descriptions. It supports various + aspect ratios, automatic prompt enhancement, and optional reference images for style + matching. +

+
+

+ Tip: Enable autoEnhance for better results. The AI will optimize your + prompt for higher quality outputs while preserving your intent. +

+
+
+ + {/* Endpoint */} +
+

2. Endpoint

+
+ POST + https://api.banatie.com/api/text-to-image +
+
+ + {/* Request */} +
+

3. Request

+ +
+

3.1 Headers

+
+ + + + + + + + + + + + + + + + + + + + +
HeaderValueRequired
X-API-KeyYour project API key + Yes +
Content-Typeapplication/json + Yes +
+
+
+ +
+

3.2 Body Parameters

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescriptionRequired
promptstringText description of the image to generate + Yes +
filenamestringName for the generated image file + Yes +
aspectRatiostring + Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9 + + No +
autoEnhancebooleanEnable automatic prompt enhancement (default: true) + No +
enhancementOptionsobjectTemplate and enhancement settings + No +
+
+
+
+ + {/* Interactive API Widget */} + + + {/* Response */} +
+

4. Response

+

+ Returns a JSON object with the generated image URL and metadata. +

+ +
+
+            {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
+    "filepath": "org/project/generated/2025-01/city.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "originalPrompt": "a futuristic city at sunset",
+      "enhancedPrompt": "A breathtaking futuristic cityscape...",
+      "template": "photorealistic"
+    },
+    "generatedAt": "2025-01-15T10:30:00Z"
+  }
+}`}
+          
+
+
+ + {/* Examples */} +
+

5. Examples

+ +
+
+

5.1 Basic Image Generation

+

Generate a simple image with default settings

+
+
+                {`{
+  "prompt": "a serene mountain landscape",
+  "filename": "mountain"
+}`}
+              
+
+
+ +
+

5.2 Custom Aspect Ratio

+

Generate a widescreen image

+
+
+                {`{
+  "prompt": "cinematic space battle scene",
+  "filename": "space_battle",
+  "aspectRatio": "21:9"
+}`}
+              
+
+
+
+
+ + {/* Error Codes */} +
+

6. Error Codes

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CodeDescription
400Invalid request parameters
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx b/apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx new file mode 100644 index 0000000..a4b8ffb --- /dev/null +++ b/apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx @@ -0,0 +1,305 @@ +'use client'; + +/** + * Guide: Authentication - Variant B: Dense & Information-Rich + * + * Design Philosophy: Compact, information-dense layout with section numbers + * + * Key Differences from Variant A: + * - Section numbers in all headings (1., 2., 2.1, etc.) + * - More compact spacing (mb-6 vs mb-12, p-3 vs p-4) + * - Smaller text sizes throughout (text-xs, text-sm) + * - Denser layout with narrower content area + */ + +import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB'; +import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB'; +import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'overview', text: '1. Overview', level: 2 }, + { id: 'api-keys', text: '2. API Keys', level: 2 }, + { id: 'key-types', text: '2.1 Key Types', level: 3 }, + { id: 'creating-keys', text: '2.2 Creating Keys', level: 3 }, + { id: 'using-keys', text: '3. Using API Keys', level: 2 }, + { id: 'security', text: '4. Security Best Practices', level: 2 }, + { id: 'rate-limits', text: '5. Rate Limits', level: 2 }, +]; + +export default function AuthenticationGuidePageB() { + return ( + } + toc={} + > + + + {/* Hero Section - More compact */} +
+
+ GUIDE +
+

Authentication

+

+ Learn how to authenticate your requests and manage API keys securely. +

+
+ + {/* Overview */} +
+

1. Overview

+

+ Banatie uses API keys to authenticate requests. Each request must include a valid API key + in the X-API-Key header. API keys are tied to your organization and project, providing + secure, isolated access to resources. +

+
+

+ Security First: Never expose your API keys in client-side code, public + repositories, or logs. Treat them like passwords. +

+
+
+ + {/* API Keys */} +
+

2. API Keys

+ +
+

2.1 Key Types

+

+ Banatie provides two types of API keys, each with different permissions and use cases: +

+ +
+
+
+
+ πŸ”‘ +
+
+

Master Keys

+

+ Full administrative access to your organization. Can create and revoke other + keys, access all projects, and manage settings. +

+
    +
  • β€’ Never expire
  • +
  • β€’ Full API access
  • +
  • β€’ One per organization (initially)
  • +
  • β€’ Should be kept extremely secure
  • +
+
+
+
+ +
+
+
+ 🎫 +
+
+

Project Keys

+

+ Scoped to a specific project. Used for image generation and resource access + within that project only. +

+
    +
  • β€’ Expire after 90 days
  • +
  • β€’ Project-specific access
  • +
  • β€’ Rate limited
  • +
  • β€’ Safe for production use
  • +
+
+
+
+
+
+ +
+

2.2 Creating Keys

+ +
+

2.2.1 Bootstrap Your First Key

+

+ When setting up Banatie for the first time, create your initial master key using the + bootstrap endpoint: +

+ +
+

+ Important: This endpoint can only be used once. Save the returned + key immediately - it will never be shown again. +

+
+
+ +
+

2.2.2 Create Project Keys

+

+ Use your master key to create project-specific keys: +

+ +
+
+
+ + {/* Using Keys */} +
+

3. Using API Keys

+

+ Include your API key in every request using the X-API-Key header: +

+ + +
+ + {/* Security */} +
+

4. Security Best Practices

+ +
+
+
πŸ”’
+
+

Never Commit Keys

+

+ Use environment variables or secret management tools. Never commit keys to version + control. +

+
+
+ +
+
πŸ”„
+
+

Rotate Keys Regularly

+

+ Project keys expire after 90 days. Plan for rotation and implement graceful + handling. +

+
+
+ +
+
🚫
+
+

Server-Side Only

+

+ Never use API keys in client-side code. Always make requests from your backend. +

+
+
+ +
+
πŸ‘οΈ
+
+

Monitor Usage

+

+ Track API key usage patterns. Unusual activity may indicate a compromised key. +

+
+
+
+
+ + {/* Rate Limits */} +
+

5. Rate Limits

+

+ To ensure fair usage and system stability, all API keys are subject to rate limits: +

+ +
+ + + + + + + + + + + + + + + + + + + + +
Key TypeLimitWindow
Master Key500 requestsper hour
Project Key100 requestsper hour
+
+ +
+

+ Need Higher Limits? Contact our sales team to discuss enterprise plans + with custom rate limits. +

+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-b/page.tsx b/apps/landing/src/app/docs/variant-b/page.tsx new file mode 100644 index 0000000..c8320e6 --- /dev/null +++ b/apps/landing/src/app/docs/variant-b/page.tsx @@ -0,0 +1,211 @@ +'use client'; + +/** + * Getting Started Page - Variant B: Dense & Information-Rich + * + * Same content as Variant A but with Variant B styling: + * - Compact spacing (py-10 vs py-12, p-4 vs p-6) + * - Narrower max-width (max-w-4xl) + * - Section numbers in headings where appropriate + * - Denser tables and lists + */ + +import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB'; +import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB'; +import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'introduction', text: '1. Introduction', level: 2 }, + { id: 'quick-start', text: '2. Quick Start', level: 2 }, + { id: 'installation', text: '2.1 Installation', level: 3 }, + { id: 'authentication', text: '2.2 Authentication', level: 3 }, + { id: 'first-request', text: '3. Your First Request', level: 2 }, + { id: 'next-steps', text: '4. Next Steps', level: 2 }, +]; + +export default function GettingStartedPageB() { + return ( + } + toc={} + > + + + {/* Hero Section - More compact */} +
+

Getting Started

+

+ Welcome to the Banatie API documentation. Learn how to integrate AI-powered image + generation into your applications in minutes. +

+
+ + {/* Introduction */} +
+

1. Introduction

+

+ Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini + 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into + production-ready visuals. +

+

+ Whether you're building a content creation platform, e-commerce site, or creative tool, + Banatie provides the infrastructure you need to generate high-quality images at scale. +

+
+ + {/* Quick Start */} +
+

2. Quick Start

+ +
+

2.1 Installation

+

+ Banatie is a REST API, so you don't need to install any libraries. However, we provide + SDKs for popular languages to make integration easier. +

+ + +
+ +
+

2.2 Authentication

+

+ All API requests require an API key. You can create an API key from your dashboard or + using the bootstrap endpoint for initial setup. +

+ +
+

+ Note: Keep your API keys secure. Never commit them to public + repositories or expose them in client-side code. +

+
+ + +
+
+ + {/* First Request */} +
+

3. Your First Request

+

+ Let's generate your first image! This example uses curl, but you can use any HTTP client + or our SDKs. +

+ + + +
+

Response:

+
+            {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
+    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "enhancedPrompt": "A breathtaking mountain landscape..."
+    }
+  }
+}`}
+          
+
+
+ + {/* Next Steps */} +
+

4. Next Steps

+ + +
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx b/apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx new file mode 100644 index 0000000..83665b8 --- /dev/null +++ b/apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx @@ -0,0 +1,369 @@ +'use client'; + +/** + * API Reference: Text to Image - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Colorful, card-based, engaging visual design + * + * Key Characteristics: + * - NO section numbers (more visual/playful) + * - Large emoji icons (text-3xl) + * - Gradient borders everywhere + * - Colorful method badge (large, gradient) + * - Visual cards for parameter tables + * - Generous spacing (mb-12, p-6) + */ + +import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC'; +import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC'; +import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { InteractiveAPIWidgetC } from '@/components/docs/variant-c/InteractiveAPIWidgetC'; + +const tocItems = [ + { id: 'overview', text: 'Overview', level: 2 }, + { id: 'endpoint', text: 'Endpoint', level: 2 }, + { id: 'request', text: 'Request', level: 2 }, + { id: 'headers', text: 'Headers', level: 3 }, + { id: 'body', text: 'Body Parameters', level: 3 }, + { id: 'response', text: 'Response', level: 2 }, + { id: 'examples', text: 'Examples', level: 2 }, + { id: 'errors', text: 'Error Codes', level: 2 }, +]; + +export default function TextToImageAPIPageC() { + return ( + } + toc={} + > + + + {/* Hero Section - Large and Colorful */} +
+
+ POST +
+

+ Text to Image +

+

+ Generate high-quality images from text prompts using AI-powered models. +

+
+ + {/* Overview */} +
+
+ πŸ“– +

Overview

+
+
+

+ The Text to Image endpoint generates images from text descriptions. It supports various + aspect ratios, automatic prompt enhancement, and optional reference images for style + matching. +

+
+
+ πŸ’‘ +
+

Pro Tip

+

+ Enable autoEnhance for better results. The AI will optimize your prompt for higher + quality outputs while preserving your intent. +

+
+
+
+
+
+ + {/* Endpoint */} +
+
+ πŸ”— +

Endpoint

+
+
+
+ + POST + + https://api.banatie.com/api/text-to-image +
+
+
+ + {/* Request */} +
+
+ πŸ“€ +

Request

+
+ +
+
+ 🏷️ +

Headers

+
+
+ + + + + + + + + + + + + + + + + + + + +
HeaderValueRequired
X-API-KeyYour project API key + + Required + +
Content-Typeapplication/json + + Required + +
+
+
+ +
+
+ βš™οΈ +

Body Parameters

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterTypeDescriptionRequired
promptstringText description of the image to generate + + Required + +
filenamestringName for the generated image file + + Required + +
aspectRatiostring + Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9 + + + Optional + +
autoEnhancebooleanEnable automatic prompt enhancement (default: true) + + Optional + +
enhancementOptionsobjectTemplate and enhancement settings + + Optional + +
+
+
+
+ + {/* Interactive API Widget */} + + + {/* Response */} +
+
+ πŸ“¦ +

Response

+
+

+ Returns a JSON object with the generated image URL and metadata. +

+ +
+
+ + βœ“ 200 Success + +
+
+            {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
+    "filepath": "org/project/generated/2025-01/city.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "originalPrompt": "a futuristic city at sunset",
+      "enhancedPrompt": "A breathtaking futuristic cityscape...",
+      "template": "photorealistic"
+    },
+    "generatedAt": "2025-01-15T10:30:00Z"
+  }
+}`}
+          
+
+
+ + {/* Examples */} +
+
+ πŸ’‘ +

Examples

+
+ +
+
+
+ 🎨 +

Basic Image Generation

+
+

Generate a simple image with default settings

+
+
+                {`{
+  "prompt": "a serene mountain landscape",
+  "filename": "mountain"
+}`}
+              
+
+
+ +
+
+ 🎬 +

Custom Aspect Ratio

+
+

Generate a widescreen image

+
+
+                {`{
+  "prompt": "cinematic space battle scene",
+  "filename": "space_battle",
+  "aspectRatio": "21:9"
+}`}
+              
+
+
+
+
+ + {/* Error Codes */} +
+
+ ⚠️ +

Error Codes

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CodeDescription
400Invalid request parameters
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx b/apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx new file mode 100644 index 0000000..1e9b3ef --- /dev/null +++ b/apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx @@ -0,0 +1,370 @@ +'use client'; + +/** + * Guide: Authentication - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Colorful, card-based, playful visual design + * + * Key Characteristics: + * - NO section numbers (more visual/playful) + * - Security best practices as large visual cards + * - Emoji icons prominent (text-3xl) + * - Gradient borders everywhere + * - Generous spacing and padding + */ + +import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC'; +import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC'; +import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'overview', text: 'Overview', level: 2 }, + { id: 'api-keys', text: 'API Keys', level: 2 }, + { id: 'key-types', text: 'Key Types', level: 3 }, + { id: 'creating-keys', text: 'Creating Keys', level: 3 }, + { id: 'using-keys', text: 'Using API Keys', level: 2 }, + { id: 'security', text: 'Security Best Practices', level: 2 }, + { id: 'rate-limits', text: 'Rate Limits', level: 2 }, +]; + +export default function AuthenticationGuidePageC() { + return ( + } + toc={} + > + + + {/* Hero Section - Large and Colorful */} +
+
+ πŸ“š + GUIDE +
+

+ Authentication +

+

+ Learn how to authenticate your requests and manage API keys securely. +

+
+ + {/* Overview */} +
+
+ πŸ” +

Overview

+
+
+

+ Banatie uses API keys to authenticate requests. Each request must include a valid API key + in the X-API-Key header. API keys are tied to your organization and project, providing + secure, isolated access to resources. +

+
+
+ πŸ›‘οΈ +
+

Security First

+

+ Never expose your API keys in client-side code, public repositories, or logs. Treat + them like passwords. +

+
+
+
+
+
+ + {/* API Keys */} +
+
+ πŸ”‘ +

API Keys

+
+ +
+
+ 🏷️ +

Key Types

+
+

+ Banatie provides two types of API keys, each with different permissions and use cases: +

+ +
+
+
+
+ πŸ”‘ +
+
+

Master Keys

+

+ Full administrative access to your organization. Can create and revoke other + keys, access all projects, and manage settings. +

+
    +
  • + βœ“ Never expire +
  • +
  • + βœ“ Full API access +
  • +
  • + βœ“ One per organization (initially) +
  • +
  • + βœ“ Should be kept extremely secure +
  • +
+
+
+
+ +
+
+
+ 🎫 +
+
+

Project Keys

+

+ Scoped to a specific project. Used for image generation and resource access + within that project only. +

+
    +
  • + βœ“ Expire after 90 days +
  • +
  • + βœ“ Project-specific access +
  • +
  • + βœ“ Rate limited +
  • +
  • + βœ“ Safe for production use +
  • +
+
+
+
+
+
+ +
+
+ ⚑ +

Creating Keys

+
+ +
+
+ πŸš€ +

Bootstrap Your First Key

+
+

+ When setting up Banatie for the first time, create your initial master key using the + bootstrap endpoint: +

+ +
+
+ ⚠️ +
+

Important

+

+ This endpoint can only be used once. Save the returned key immediately - it will + never be shown again. +

+
+
+
+
+ +
+
+ 🎨 +

Create Project Keys

+
+

+ Use your master key to create project-specific keys: +

+ +
+
+
+ + {/* Using Keys */} +
+
+ πŸ’» +

Using API Keys

+
+

+ Include your API key in every request using the X-API-Key header: +

+ + +
+ + {/* Security */} +
+
+ πŸ›‘οΈ +

Security Best Practices

+
+ +
+
+
πŸ”’
+

Never Commit Keys

+

+ Use environment variables or secret management tools. Never commit keys to version + control. +

+
+ +
+
πŸ”„
+

Rotate Keys Regularly

+

+ Project keys expire after 90 days. Plan for rotation and implement graceful handling. +

+
+ +
+
🚫
+

Server-Side Only

+

+ Never use API keys in client-side code. Always make requests from your backend. +

+
+ +
+
πŸ‘οΈ
+

Monitor Usage

+

+ Track API key usage patterns. Unusual activity may indicate a compromised key. +

+
+
+
+ + {/* Rate Limits */} +
+
+ ⏱️ +

Rate Limits

+
+

+ To ensure fair usage and system stability, all API keys are subject to rate limits: +

+ +
+ + + + + + + + + + + + + + + + + + + + +
Key TypeLimitWindow
Master Key + + 500 requests + + per hour
Project Key + + 100 requests + + per hour
+
+ +
+
+ πŸ’¬ +
+

Need Higher Limits?

+

+ Contact our sales team to discuss enterprise plans with custom rate limits. +

+
+
+
+
+
+ ); +} diff --git a/apps/landing/src/app/docs/variant-c/page.tsx b/apps/landing/src/app/docs/variant-c/page.tsx new file mode 100644 index 0000000..b80157e --- /dev/null +++ b/apps/landing/src/app/docs/variant-c/page.tsx @@ -0,0 +1,268 @@ +'use client'; + +/** + * Getting Started Page - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Colorful, card-based, playful visual design + * + * Key Characteristics: + * - NO section numbers (more visual/playful) + * - Large emoji icons throughout (text-3xl) + * - Gradient borders on all callout boxes + * - More colorful design (purple/cyan/amber accents) + * - Generous spacing (mb-12, p-6) + * - Larger padding and gaps throughout + * - Card-based sections with shadows + * - Floating visual effects + */ + +import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC'; +import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC'; +import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'introduction', text: 'Introduction', level: 2 }, + { id: 'quick-start', text: 'Quick Start', level: 2 }, + { id: 'installation', text: 'Installation', level: 3 }, + { id: 'authentication', text: 'Authentication', level: 3 }, + { id: 'first-request', text: 'Your First Request', level: 2 }, + { id: 'next-steps', text: 'Next Steps', level: 2 }, +]; + +export default function GettingStartedPageC() { + return ( + } + toc={} + > + + + {/* Hero Section - Large and Colorful */} +
+
+ πŸš€ + START HERE +
+

+ Getting Started +

+

+ Welcome to the Banatie API documentation. Learn how to integrate AI-powered image + generation into your applications in minutes. +

+
+ + {/* Introduction */} +
+
+ πŸ‘‹ +

Introduction

+
+
+

+ Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini + 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into + production-ready visuals. +

+

+ Whether you're building a content creation platform, e-commerce site, or creative tool, + Banatie provides the infrastructure you need to generate high-quality images at scale. +

+
+
+ + {/* Quick Start */} +
+
+ ⚑ +

Quick Start

+
+ +
+
+ πŸ“¦ +

Installation

+
+

+ Banatie is a REST API, so you don't need to install any libraries. However, we provide + SDKs for popular languages to make integration easier. +

+ + +
+ +
+
+ πŸ”‘ +

Authentication

+
+

+ All API requests require an API key. You can create an API key from your dashboard or + using the bootstrap endpoint for initial setup. +

+ +
+
+ πŸ’‘ +
+

Security Tip

+

+ Keep your API keys secure. Never commit them to public repositories or expose them + in client-side code. +

+
+
+
+ + +
+
+ + {/* First Request */} +
+
+ 🎨 +

Your First Request

+
+

+ Let's generate your first image! This example uses curl, but you can use any HTTP client + or our SDKs. +

+ + + +
+
+ ✨ +

Expected Response:

+
+
+            {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
+    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "enhancedPrompt": "A breathtaking mountain landscape..."
+    }
+  }
+}`}
+          
+
+
+ + {/* Next Steps */} +
+
+ 🎯 +

Next Steps

+
+ + +
+ + {/* Fun CTA Card */} +
+
πŸŽ‰
+

Ready to Build Something Amazing?

+

+ Start creating stunning AI-generated images for your applications today! +

+ + ⚑ + Explore the API + +
+
+ ); +} diff --git a/apps/landing/src/components/docs/shared/Breadcrumb.tsx b/apps/landing/src/components/docs/shared/Breadcrumb.tsx new file mode 100644 index 0000000..3656001 --- /dev/null +++ b/apps/landing/src/components/docs/shared/Breadcrumb.tsx @@ -0,0 +1,73 @@ +'use client'; + +/** + * Breadcrumb Navigation Component + * + * Displays hierarchical navigation path for documentation pages. + * Follows WCAG 2.1 AA accessibility guidelines with proper ARIA labels. + * + * Design: + * - Consistent with Banatie dark theme + * - Gray text with white hover for inactive items + * - White text for current page + * - Chevron separators between items + */ + +interface BreadcrumbItem { + label: string; + href?: string; +} + +interface BreadcrumbProps { + items: BreadcrumbItem[]; +} + +export const Breadcrumb = ({ items }: BreadcrumbProps) => { + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/shared/CodeBlock.tsx b/apps/landing/src/components/docs/shared/CodeBlock.tsx new file mode 100644 index 0000000..c345843 --- /dev/null +++ b/apps/landing/src/components/docs/shared/CodeBlock.tsx @@ -0,0 +1,69 @@ +'use client'; + +/** + * CodeBlock Component + * + * Wrapper for displaying syntax-highlighted code blocks in documentation. + * Uses the existing Banatie design pattern from the landing page. + * + * Design Features: + * - MacOS-style window with traffic light dots + * - Dark slate background with backdrop blur + * - Copy button in top-right + * - Scrollable code area + * - Optional language label + */ + +import { useState } from 'react'; + +interface CodeBlockProps { + code: string; + language?: string; + filename?: string; + showLineNumbers?: boolean; +} + +export const CodeBlock = ({ + code, + language = 'bash', + filename, + showLineNumbers = false, +}: CodeBlockProps) => { + const [copied, setCopied] = useState(false); + + const handleCopy = () => { + navigator.clipboard.writeText(code); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( +
+ {/* Header with traffic lights and copy button */} +
+
+
+
+
+
+
+ {(filename || language) && ( + {filename || language} + )} +
+ +
+ + {/* Code content */} +
+        {code}
+      
+
+ ); +}; diff --git a/apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx b/apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx new file mode 100644 index 0000000..66f33e5 --- /dev/null +++ b/apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx @@ -0,0 +1,62 @@ +'use client'; + +/** + * Documentation Layout - Variant A: Clean & Minimal + * + * Design Philosophy: Vercel-inspired spacious, focused reading experience + * + * Layout Structure: + * - Left Sidebar: Thin (256px) with minimal design + * - Content Area: Wide margins (max-w-3xl) for comfortable reading + * - Right TOC: Subtle and unobtrusive (224px) + * + * Responsive Behavior: + * - Mobile (<768px): Single column, sidebars become overlays + * - Tablet (768px-1024px): Content + TOC only + * - Desktop (>1024px): Full three-column layout + * + * Design Characteristics: + * - Generous whitespace + * - Subtle borders and shadows + * - Focus on content clarity + * - Minimal visual noise + */ + +import { ReactNode } from 'react'; + +interface DocsLayoutAProps { + sidebar: ReactNode; + children: ReactNode; + toc: ReactNode; +} + +export const DocsLayoutA = ({ sidebar, children, toc }: DocsLayoutAProps) => { + return ( +
+ {/* Animated gradient background (matching landing page) */} +
+
+
+
+ +
+ {/* Left Sidebar - Thin, minimal design */} + + + {/* Main Content Area - Wide margins for comfortable reading */} +
+
+ {children} +
+
+ + {/* Right TOC - Subtle and unobtrusive */} + +
+
+ ); +}; diff --git a/apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx b/apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx new file mode 100644 index 0000000..34bb8d4 --- /dev/null +++ b/apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx @@ -0,0 +1,178 @@ +'use client'; + +/** + * Documentation Sidebar - Variant A: Clean & Minimal + * + * Design Philosophy: Vercel-inspired minimal navigation + * + * Features: + * - Thin sidebar with subtle hover states + * - Collapsible section groups + * - Active state: Purple left border + text + * - Minimal icons (chevron for expandable items) + * - Clean, uncluttered appearance + * + * Navigation Structure: + * - Getting Started + * - API Reference (collapsible) + * - Text to Image + * - Upload + * - Images + * - Guides (collapsible) + * - Authentication + * - Error Handling + * - Rate Limits + * - Examples + */ + +import { useState } from 'react'; + +interface NavItem { + label: string; + href: string; + icon?: string; + children?: NavItem[]; +} + +interface DocsSidebarAProps { + currentPath: string; +} + +const navigationItems: NavItem[] = [ + { + label: 'Getting Started', + href: '/docs/variant-a', + icon: 'πŸš€', + }, + { + label: 'API Reference', + href: '/docs/variant-a/api', + icon: 'πŸ“š', + children: [ + { label: 'Text to Image', href: '/docs/variant-a/api/text-to-image' }, + { label: 'Upload', href: '/docs/variant-a/api/upload' }, + { label: 'Images', href: '/docs/variant-a/api/images' }, + ], + }, + { + label: 'Guides', + href: '/docs/variant-a/guides', + icon: 'πŸ“–', + children: [ + { label: 'Authentication', href: '/docs/variant-a/guides/authentication' }, + { label: 'Error Handling', href: '/docs/variant-a/guides/error-handling' }, + { label: 'Rate Limits', href: '/docs/variant-a/guides/rate-limits' }, + ], + }, + { + label: 'Examples', + href: '/docs/variant-a/examples', + icon: 'πŸ’‘', + }, +]; + +export const DocsSidebarA = ({ currentPath }: DocsSidebarAProps) => { + const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); + + const toggleSection = (label: string) => { + setExpandedSections((prev) => + prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] + ); + }; + + const isActive = (href: string) => currentPath === href; + const isExpanded = (label: string) => expandedSections.includes(label); + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/variant-a/DocsTOCA.tsx b/apps/landing/src/components/docs/variant-a/DocsTOCA.tsx new file mode 100644 index 0000000..330edf9 --- /dev/null +++ b/apps/landing/src/components/docs/variant-a/DocsTOCA.tsx @@ -0,0 +1,102 @@ +'use client'; + +/** + * Table of Contents - Variant A: Clean & Minimal + * + * Design Philosophy: Subtle, unobtrusive TOC + * + * Features: + * - Small indicator dots for section levels + * - Smooth scroll to section + * - Active section highlighting (purple text) + * - Sticky positioning + * - Minimal visual weight + * + * Behavior: + * - Extracts H2 and H3 headings from content + * - Tracks scroll position to highlight active section + * - Click to smooth scroll to section + */ + +import { useEffect, useState } from 'react'; + +interface TocItem { + id: string; + text: string; + level: number; +} + +interface DocsTOCAProps { + items: TocItem[]; +} + +export const DocsTOCA = ({ items }: DocsTOCAProps) => { + const [activeId, setActiveId] = useState(''); + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setActiveId(entry.target.id); + } + }); + }, + { rootMargin: '-20% 0px -35% 0px' } + ); + + items.forEach((item) => { + const element = document.getElementById(item.id); + if (element) observer.observe(element); + }); + + return () => observer.disconnect(); + }, [items]); + + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }; + + if (items.length === 0) { + return null; + } + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx b/apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx new file mode 100644 index 0000000..a1d443a --- /dev/null +++ b/apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx @@ -0,0 +1,293 @@ +'use client'; + +/** + * Interactive API Widget - Variant A: Clean & Minimal + * + * Design Philosophy: Inline playground with tabbed interface + * + * Features: + * - Multi-language code tabs (curl, JavaScript, Python, Go) + * - API key input field (persists via localStorage) + * - "Try It" button to execute live requests + * - Response viewer with syntax highlighting + * - Request/Response tabs + * - Error state handling + * - Clean, focused design + * + * Layout: + * - Top: Language tabs + Copy button + * - Middle: Code preview OR Request params + * - Bottom: Try It button + * - Response: Expandable section below + */ + +import { useState, useEffect } from 'react'; + +interface InteractiveAPIWidgetAProps { + endpoint: string; + method: 'GET' | 'POST' | 'PUT' | 'DELETE'; + description: string; + parameters?: Array<{ + name: string; + type: string; + required: boolean; + description: string; + defaultValue?: string; + }>; +} + +type Language = 'curl' | 'javascript' | 'python' | 'go'; +type ViewMode = 'code' | 'response'; + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; +const API_KEY_STORAGE = 'banatie_docs_api_key'; + +export const InteractiveAPIWidgetA = ({ + endpoint, + method, + description, + parameters = [], +}: InteractiveAPIWidgetAProps) => { + const [language, setLanguage] = useState('curl'); + const [apiKey, setApiKey] = useState(''); + const [isExecuting, setIsExecuting] = useState(false); + const [viewMode, setViewMode] = useState('code'); + const [response, setResponse] = useState(null); + const [error, setError] = useState(null); + + // Parameter values + const [paramValues, setParamValues] = useState>({}); + + // Load API key from localStorage + useEffect(() => { + const stored = localStorage.getItem(API_KEY_STORAGE); + if (stored) setApiKey(stored); + + // Initialize parameter default values + const defaults: Record = {}; + parameters.forEach((param) => { + if (param.defaultValue) { + defaults[param.name] = param.defaultValue; + } + }); + setParamValues(defaults); + }, [parameters]); + + // Save API key to localStorage + const handleApiKeyChange = (value: string) => { + setApiKey(value); + if (value) { + localStorage.setItem(API_KEY_STORAGE, value); + } else { + localStorage.removeItem(API_KEY_STORAGE); + } + }; + + // Generate code examples + const generateCode = (): string => { + const url = `${API_BASE_URL}${endpoint}`; + + switch (language) { + case 'curl': + return `curl -X ${method} "${url}" \\ + -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ + -H "Content-Type: application/json" \\ + -d '{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9" + }'`; + + case 'javascript': + return `const response = await fetch('${url}', { + method: '${method}', + headers: { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + prompt: 'a futuristic city at sunset', + filename: 'city', + aspectRatio: '16:9' + }) +}); + +const data = await response.json(); +console.log(data);`; + + case 'python': + return `import requests + +url = '${url}' +headers = { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' +} +data = { + 'prompt': 'a futuristic city at sunset', + 'filename': 'city', + 'aspectRatio': '16:9' +} + +response = requests.${method.toLowerCase()}(url, headers=headers, json=data) +print(response.json())`; + + case 'go': + return `package main + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +func main() { + url := "${url}" + data := map[string]interface{}{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9", + } + + jsonData, _ := json.Marshal(data) + req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) + req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, _ := client.Do(req) + defer resp.Body.Close() +}`; + + default: + return ''; + } + }; + + // Execute API request + const executeRequest = async () => { + if (!apiKey) { + setError('Please enter your API key'); + return; + } + + setIsExecuting(true); + setError(null); + setViewMode('response'); + + try { + const body: Record = {}; + parameters.forEach((param) => { + if (paramValues[param.name]) { + body[param.name] = paramValues[param.name]; + } + }); + + const res = await fetch(`${API_BASE_URL}${endpoint}`, { + method, + headers: { + 'X-API-Key': apiKey, + 'Content-Type': 'application/json', + }, + body: method !== 'GET' ? JSON.stringify(body) : undefined, + }); + + const data = await res.json(); + setResponse(data); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to execute request'); + } finally { + setIsExecuting(false); + } + }; + + // Copy code to clipboard + const copyCode = () => { + navigator.clipboard.writeText(generateCode()); + }; + + return ( +
+ {/* Header with API Key Input */} +
+
+
+

Try it out

+

{description}

+
+
+ handleApiKeyChange(e.target.value)} + placeholder="Enter your API key" + className="w-full px-3 py-2 text-xs bg-slate-800 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" + /> +
+
+
+ + {/* Language Tabs */} +
+
+ {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => ( + + ))} +
+ +
+ + {/* Code Display */} +
+
+          {generateCode()}
+        
+
+ + {/* Try It Button */} +
+ +
+ + {/* Response Section */} + {(response || error) && ( +
+
+

Response

+ {error ? ( +
+ {error} +
+ ) : ( +
+                {JSON.stringify(response, null, 2)}
+              
+ )} +
+
+ )} +
+ ); +}; diff --git a/apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx b/apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx new file mode 100644 index 0000000..c019a9e --- /dev/null +++ b/apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx @@ -0,0 +1,62 @@ +'use client'; + +/** + * Documentation Layout - Variant B: Dense & Information-Rich + * + * Design Philosophy: Next.js-inspired dense, hierarchical layout + * + * Layout Structure: + * - Left Sidebar: Wider (280px) with nested tree structure + * - Content Area: Narrower margins to show more content + * - Right TOC: Prominent with progress indicator (240px) + * + * Responsive Behavior: + * - Mobile (<768px): Bottom sheet navigation + * - Tablet (768px-1024px): Collapsible sidebar + TOC + * - Desktop (>1024px): Full three-column layout + * + * Design Characteristics: + * - Compact spacing + * - More content per screen + * - Nested navigation tree + * - Section numbers throughout + */ + +import { ReactNode } from 'react'; + +interface DocsLayoutBProps { + sidebar: ReactNode; + children: ReactNode; + toc: ReactNode; +} + +export const DocsLayoutB = ({ sidebar, children, toc }: DocsLayoutBProps) => { + return ( +
+ {/* Animated gradient background (matching landing page) */} +
+
+
+
+ +
+ {/* Left Sidebar - Wider with nested structure */} + + + {/* Main Content Area - Narrower margins for more content */} +
+
+ {children} +
+
+ + {/* Right TOC - Prominent with progress */} + +
+
+ ); +}; diff --git a/apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx b/apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx new file mode 100644 index 0000000..8f55dcf --- /dev/null +++ b/apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx @@ -0,0 +1,205 @@ +'use client'; + +/** + * Documentation Sidebar - Variant B: Dense & Information-Rich + * + * Design Philosophy: Next.js-inspired nested tree structure + * + * Features: + * - Wider sidebar with deep nesting + * - Section numbers for all items + * - Compact spacing (more items visible) + * - Indent levels for hierarchy + * - Active state: Purple background + bold + * - Expand/collapse all button + * + * Navigation Structure with numbers: + * 1. Getting Started + * 2. API Reference + * 2.1 Text to Image + * 2.2 Upload + * 2.3 Images + * 3. Guides + * 3.1 Authentication + * 3.2 Error Handling + * 3.3 Rate Limits + * 4. Examples + */ + +import { useState } from 'react'; + +interface NavItem { + label: string; + href: string; + number?: string; + children?: NavItem[]; +} + +interface DocsSidebarBProps { + currentPath: string; +} + +const navigationItems: NavItem[] = [ + { + label: 'Getting Started', + href: '/docs/variant-b', + number: '1', + }, + { + label: 'API Reference', + href: '/docs/variant-b/api', + number: '2', + children: [ + { label: 'Text to Image', href: '/docs/variant-b/api/text-to-image', number: '2.1' }, + { label: 'Upload', href: '/docs/variant-b/api/upload', number: '2.2' }, + { label: 'Images', href: '/docs/variant-b/api/images', number: '2.3' }, + ], + }, + { + label: 'Guides', + href: '/docs/variant-b/guides', + number: '3', + children: [ + { label: 'Authentication', href: '/docs/variant-b/guides/authentication', number: '3.1' }, + { label: 'Error Handling', href: '/docs/variant-b/guides/error-handling', number: '3.2' }, + { label: 'Rate Limits', href: '/docs/variant-b/guides/rate-limits', number: '3.3' }, + ], + }, + { + label: 'Examples', + href: '/docs/variant-b/examples', + number: '4', + }, +]; + +export const DocsSidebarB = ({ currentPath }: DocsSidebarBProps) => { + const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); + + const toggleSection = (label: string) => { + setExpandedSections((prev) => + prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] + ); + }; + + const isActive = (href: string) => currentPath === href; + const isExpanded = (label: string) => expandedSections.includes(label); + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/variant-b/DocsTOCB.tsx b/apps/landing/src/components/docs/variant-b/DocsTOCB.tsx new file mode 100644 index 0000000..4d6c274 --- /dev/null +++ b/apps/landing/src/components/docs/variant-b/DocsTOCB.tsx @@ -0,0 +1,141 @@ +'use client'; + +/** + * Table of Contents - Variant B: Dense & Information-Rich + * + * Design Philosophy: Prominent TOC with progress indicator + * + * Features: + * - Section numbers matching content + * - Progress bar showing read percentage + * - Larger, more prominent design + * - Active section with purple highlight + * - Sticky positioning with scroll progress + * + * Behavior: + * - Extracts H2 and H3 headings with numbers + * - Shows reading progress percentage + * - Click to smooth scroll to section + * - Visual progress bar + */ + +import { useEffect, useState } from 'react'; + +interface TocItem { + id: string; + text: string; + level: number; +} + +interface DocsTOCBProps { + items: TocItem[]; +} + +export const DocsTOCB = ({ items }: DocsTOCBProps) => { + const [activeId, setActiveId] = useState(''); + const [scrollProgress, setScrollProgress] = useState(0); + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setActiveId(entry.target.id); + } + }); + }, + { rootMargin: '-20% 0px -35% 0px' } + ); + + items.forEach((item) => { + const element = document.getElementById(item.id); + if (element) observer.observe(element); + }); + + // Track scroll progress + const handleScroll = () => { + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight; + const scrollTop = window.scrollY; + const progress = (scrollTop / (documentHeight - windowHeight)) * 100; + setScrollProgress(Math.min(progress, 100)); + }; + + window.addEventListener('scroll', handleScroll); + + return () => { + observer.disconnect(); + window.removeEventListener('scroll', handleScroll); + }; + }, [items]); + + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }; + + if (items.length === 0) { + return null; + } + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx b/apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx new file mode 100644 index 0000000..21c543d --- /dev/null +++ b/apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx @@ -0,0 +1,291 @@ +'use client'; + +/** + * Interactive API Widget - Variant B: Dense & Information-Rich + * + * Design Philosophy: Side-by-side code editor with persistent API key bar + * + * Features: + * - Persistent API key bar at the top of page (sticky) + * - Side-by-side code and response layout + * - Multi-language tabs (curl, JavaScript, Python, Go) + * - Live request execution + * - Compact, information-dense design + * - Parameter form on the left + * - Response on the right + * + * Layout: + * - Top: Sticky API key bar (global for page) + * - Left: Code + Parameters + * - Right: Response viewer + * - Bottom: Try It button + */ + +import { useState, useEffect } from 'react'; + +interface InteractiveAPIWidgetBProps { + endpoint: string; + method: 'GET' | 'POST' | 'PUT' | 'DELETE'; + description: string; + parameters?: Array<{ + name: string; + type: string; + required: boolean; + description: string; + defaultValue?: string; + }>; +} + +type Language = 'curl' | 'javascript' | 'python' | 'go'; + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; +const API_KEY_STORAGE = 'banatie_docs_api_key'; + +export const InteractiveAPIWidgetB = ({ + endpoint, + method, + description, + parameters = [], +}: InteractiveAPIWidgetBProps) => { + const [language, setLanguage] = useState('curl'); + const [apiKey, setApiKey] = useState(''); + const [isExecuting, setIsExecuting] = useState(false); + const [response, setResponse] = useState(null); + const [error, setError] = useState(null); + const [paramValues, setParamValues] = useState>({}); + + // Load API key from localStorage + useEffect(() => { + const stored = localStorage.getItem(API_KEY_STORAGE); + if (stored) setApiKey(stored); + + // Initialize parameter default values + const defaults: Record = {}; + parameters.forEach((param) => { + if (param.defaultValue) { + defaults[param.name] = param.defaultValue; + } + }); + setParamValues(defaults); + }, [parameters]); + + // Save API key to localStorage + const handleApiKeyChange = (value: string) => { + setApiKey(value); + if (value) { + localStorage.setItem(API_KEY_STORAGE, value); + } else { + localStorage.removeItem(API_KEY_STORAGE); + } + }; + + // Generate code examples + const generateCode = (): string => { + const url = `${API_BASE_URL}${endpoint}`; + + switch (language) { + case 'curl': + return `curl -X ${method} "${url}" \\ + -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ + -H "Content-Type: application/json" \\ + -d '{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9" + }'`; + + case 'javascript': + return `const response = await fetch('${url}', { + method: '${method}', + headers: { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + prompt: 'a futuristic city at sunset', + filename: 'city', + aspectRatio: '16:9' + }) +}); + +const data = await response.json();`; + + case 'python': + return `import requests + +url = '${url}' +headers = { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' +} +data = { + 'prompt': 'a futuristic city at sunset', + 'filename': 'city', + 'aspectRatio': '16:9' +} + +response = requests.${method.toLowerCase()}(url, headers=headers, json=data)`; + + case 'go': + return `package main + +import ( + "bytes" + "encoding/json" + "net/http" +) + +func main() { + url := "${url}" + data := map[string]interface{}{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9", + } + + jsonData, _ := json.Marshal(data) + req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) + req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, _ := client.Do(req) +}`; + + default: + return ''; + } + }; + + // Execute API request + const executeRequest = async () => { + if (!apiKey) { + setError('Please enter your API key in the bar above'); + return; + } + + setIsExecuting(true); + setError(null); + + try { + const body: Record = {}; + parameters.forEach((param) => { + if (paramValues[param.name]) { + body[param.name] = paramValues[param.name]; + } + }); + + const res = await fetch(`${API_BASE_URL}${endpoint}`, { + method, + headers: { + 'X-API-Key': apiKey, + 'Content-Type': 'application/json', + }, + body: method !== 'GET' ? JSON.stringify(body) : undefined, + }); + + const data = await res.json(); + setResponse(data); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to execute request'); + } finally { + setIsExecuting(false); + } + }; + + // Copy code to clipboard + const copyCode = () => { + navigator.clipboard.writeText(generateCode()); + }; + + return ( +
+ {/* API Key Bar - Persistent at top */} +
+
+ + handleApiKeyChange(e.target.value)} + placeholder="Enter your API key (persists across examples)" + className="flex-1 px-3 py-1.5 text-xs bg-slate-800 border border-slate-700 rounded text-white placeholder-gray-600 focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-transparent" + /> + + {apiKey ? 'βœ“ Set' : 'Not set'} + +
+
+ + {/* Main Widget - Two Column Layout */} +
+ {/* Left Column: Code */} +
+ {/* Language Tabs */} +
+
+ {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => ( + + ))} +
+ +
+ + {/* Code Display */} +
+
+              {generateCode()}
+            
+
+
+ + {/* Right Column: Response */} +
+
+

Response

+
+ +
+ {error ? ( +
+ {error} +
+ ) : response ? ( +
+                {JSON.stringify(response, null, 2)}
+              
+ ) : ( +

+ Click "Execute Request" to see the response +

+ )} +
+
+
+ + {/* Try It Button - Full Width */} + + +

{description}

+
+ ); +}; diff --git a/apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx b/apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx new file mode 100644 index 0000000..435ee90 --- /dev/null +++ b/apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx @@ -0,0 +1,74 @@ +'use client'; + +/** + * Documentation Layout - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Colorful, card-based, engaging visual layout + * + * Layout Structure: + * - Left Sidebar: Wide (320px) with large card-style navigation + * - Content Area: Generous padding (p-12) with wide max-width (max-w-5xl) + * - Right TOC: Floating card with gradient borders (280px) + * + * Design Characteristics: + * - Colorful gradient borders everywhere (purple/cyan) + * - Card-based design with shadows + * - Large, generous spacing (p-6, gap-6, mb-12) + * - Playful and engaging visual style + * - NO section numbers (more visual/intuitive) + * - Large emoji icons throughout + * - Floating shadow effects + * + * Responsive Behavior: + * - Mobile (<768px): Single column, cards stack + * - Tablet (768px-1024px): Content + floating TOC + * - Desktop (>1024px): Full three-column card layout + * + * Color Palette: + * - Purple gradients: from-purple-500/30 to-purple-600/20 + * - Cyan gradients: from-cyan-500/30 to-cyan-600/20 + * - Amber accents: amber-500, amber-600 + * - Background: slate-950, slate-900 + * - Borders: purple-500/40, cyan-500/40, slate-700 + * - Shadows: shadow-lg shadow-purple-500/20 + */ + +import { ReactNode } from 'react'; + +interface DocsLayoutCProps { + sidebar: ReactNode; + children: ReactNode; + toc: ReactNode; +} + +export const DocsLayoutC = ({ sidebar, children, toc }: DocsLayoutCProps) => { + return ( +
+ {/* Animated gradient background - More colorful */} +
+
+
+
+
+ +
+ {/* Left Sidebar - Wide with card-style navigation */} + + + {/* Main Content Area - Wide with generous padding */} +
+
+ {children} +
+
+ + {/* Right TOC - Floating card with gradient border */} + +
+
+ ); +}; diff --git a/apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx b/apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx new file mode 100644 index 0000000..7b96844 --- /dev/null +++ b/apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx @@ -0,0 +1,238 @@ +'use client'; + +/** + * Documentation Sidebar - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Card-based navigation with large colorful visual elements + * + * Features: + * - Navigation items as large gradient-bordered cards + * - Large emoji icons (text-2xl) for visual hierarchy + * - Alternating purple/cyan gradient accents + * - Generous spacing (gap-4, p-4 per item) + * - Touch-friendly minimum heights (min-h-12) + * - NO section numbers (more playful/intuitive) + * - Hover effects with shadow and scale + * - Active state with prominent gradient background + * + * Navigation Structure (NO numbers): + * - πŸš€ Getting Started + * - πŸ“š API Reference + * - 🎨 Text to Image + * - πŸ“€ Upload + * - πŸ–ΌοΈ Images + * - πŸ” Guides + * - πŸ”‘ Authentication + * - ⚠️ Error Handling + * - ⏱️ Rate Limits + * - πŸ’‘ Examples + * + * Color Palette: + * - Purple: from-purple-500/30 to-purple-600/20 + * - Cyan: from-cyan-500/30 to-cyan-600/20 + * - Active: bg-gradient-to-br from-purple-500/30 to-cyan-500/30 + * - Hover: shadow-lg shadow-purple-500/20, scale-102 + */ + +import { useState } from 'react'; + +interface NavItem { + label: string; + href: string; + icon: string; + color: 'purple' | 'cyan' | 'amber'; + children?: NavItem[]; +} + +interface DocsSidebarCProps { + currentPath: string; +} + +const navigationItems: NavItem[] = [ + { + label: 'Getting Started', + href: '/docs/variant-c', + icon: 'πŸš€', + color: 'purple', + }, + { + label: 'API Reference', + href: '/docs/variant-c/api', + icon: 'πŸ“š', + color: 'cyan', + children: [ + { label: 'Text to Image', href: '/docs/variant-c/api/text-to-image', icon: '🎨', color: 'purple' }, + { label: 'Upload', href: '/docs/variant-c/api/upload', icon: 'πŸ“€', color: 'cyan' }, + { label: 'Images', href: '/docs/variant-c/api/images', icon: 'πŸ–ΌοΈ', color: 'purple' }, + ], + }, + { + label: 'Guides', + href: '/docs/variant-c/guides', + icon: 'πŸ”', + color: 'purple', + children: [ + { label: 'Authentication', href: '/docs/variant-c/guides/authentication', icon: 'πŸ”‘', color: 'cyan' }, + { label: 'Error Handling', href: '/docs/variant-c/guides/error-handling', icon: '⚠️', color: 'purple' }, + { label: 'Rate Limits', href: '/docs/variant-c/guides/rate-limits', icon: '⏱️', color: 'cyan' }, + ], + }, + { + label: 'Examples', + href: '/docs/variant-c/examples', + icon: 'πŸ’‘', + color: 'amber', + }, +]; + +const getGradientClasses = (color: 'purple' | 'cyan' | 'amber', active: boolean) => { + if (active) { + return 'bg-gradient-to-br from-purple-500/30 to-cyan-500/30 border-purple-500/60 shadow-lg shadow-purple-500/30'; + } + + const baseClasses = 'border-2 hover:shadow-lg transition-all duration-300 hover:scale-[1.02]'; + + switch (color) { + case 'purple': + return `${baseClasses} border-purple-500/30 hover:border-purple-500/50 hover:shadow-purple-500/20 hover:bg-purple-500/10`; + case 'cyan': + return `${baseClasses} border-cyan-500/30 hover:border-cyan-500/50 hover:shadow-cyan-500/20 hover:bg-cyan-500/10`; + case 'amber': + return `${baseClasses} border-amber-500/30 hover:border-amber-500/50 hover:shadow-amber-500/20 hover:bg-amber-500/10`; + default: + return baseClasses; + } +}; + +export const DocsSidebarC = ({ currentPath }: DocsSidebarCProps) => { + const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); + + const toggleSection = (label: string) => { + setExpandedSections((prev) => + prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] + ); + }; + + const isActive = (href: string) => currentPath === href; + const isExpanded = (label: string) => expandedSections.includes(label); + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/variant-c/DocsTOCC.tsx b/apps/landing/src/components/docs/variant-c/DocsTOCC.tsx new file mode 100644 index 0000000..d23f756 --- /dev/null +++ b/apps/landing/src/components/docs/variant-c/DocsTOCC.tsx @@ -0,0 +1,212 @@ +'use client'; + +/** + * Table of Contents - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Floating card with colorful visual indicators + * + * Features: + * - Wrapped in large gradient-bordered card + * - Colorful dot indicators (alternating purple/cyan/amber) + * - Large text sizes (text-base for items) + * - Generous spacing (p-6, gap-4) + * - Floating shadow effect with colored glow + * - NO section numbers (more visual/playful) + * - Active state with gradient background + * - Smooth hover animations with scale + * - Fun, engaging design with emoji header + * + * Visual Elements: + * - Large colored dots instead of numbers + * - Gradient progress bar with rainbow colors + * - Active item with gradient highlight + * - Hover effects with shadow and scale + * + * Behavior: + * - Extracts H2 and H3 headings (no numbers) + * - Shows reading progress with colorful bar + * - Click to smooth scroll to section + * - Visual feedback with animations + */ + +import { useEffect, useState } from 'react'; + +interface TocItem { + id: string; + text: string; + level: number; +} + +interface DocsTOCCProps { + items: TocItem[]; +} + +const getColorForIndex = (index: number): string => { + const colors = ['purple', 'cyan', 'amber']; + return colors[index % colors.length]; +}; + +const getDotClasses = (color: string, isActive: boolean): string => { + const baseClasses = 'w-2.5 h-2.5 rounded-full flex-shrink-0 transition-all duration-300'; + + if (isActive) { + return `${baseClasses} shadow-lg ${ + color === 'purple' + ? 'bg-purple-500 shadow-purple-500/50' + : color === 'cyan' + ? 'bg-cyan-500 shadow-cyan-500/50' + : 'bg-amber-500 shadow-amber-500/50' + }`; + } + + return `${baseClasses} ${ + color === 'purple' + ? 'bg-purple-500/40' + : color === 'cyan' + ? 'bg-cyan-500/40' + : 'bg-amber-500/40' + }`; +}; + +export const DocsTOCC = ({ items }: DocsTOCCProps) => { + const [activeId, setActiveId] = useState(''); + const [scrollProgress, setScrollProgress] = useState(0); + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setActiveId(entry.target.id); + } + }); + }, + { rootMargin: '-20% 0px -35% 0px' } + ); + + items.forEach((item) => { + const element = document.getElementById(item.id); + if (element) observer.observe(element); + }); + + const handleScroll = () => { + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight; + const scrollTop = window.scrollY; + const progress = (scrollTop / (documentHeight - windowHeight)) * 100; + setScrollProgress(Math.min(progress, 100)); + }; + + window.addEventListener('scroll', handleScroll); + + return () => { + observer.disconnect(); + window.removeEventListener('scroll', handleScroll); + }; + }, [items]); + + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }; + + if (items.length === 0) { + return null; + } + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx b/apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx new file mode 100644 index 0000000..c2c6ad9 --- /dev/null +++ b/apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx @@ -0,0 +1,393 @@ +'use client'; + +/** + * Interactive API Widget - Variant C: Modern & Visual (Shopify-inspired) + * + * Design Philosophy: Floating, expandable card with colorful visual feedback + * + * Features: + * - Full-screen expandable mode toggle button + * - Large gradient-bordered card with shadow glow + * - Prominent "Test Now ⚑" button (larger, more visual) + * - Response in colorful gradient-bordered card + * - Success/error states with vibrant colored badges + * - More visual feedback and animations + * - Large emoji icons throughout + * - Colorful code syntax highlighting hints + * - Floating shadow effects + * + * Layout: + * - Top: Large colorful API key input card + * - Main: Expandable code editor with rainbow gradient border + * - Language tabs as colorful pills + * - Large prominent "Test Now" button with gradient + * - Response card with colored status indicators + * + * Visual Elements: + * - Purple/cyan/amber gradients everywhere + * - Large shadows with colored glows + * - Scale and hover animations + * - Success: Green gradient with glow + * - Error: Red gradient with glow + */ + +import { useState, useEffect } from 'react'; + +interface InteractiveAPIWidgetCProps { + endpoint: string; + method: 'GET' | 'POST' | 'PUT' | 'DELETE'; + description: string; + parameters?: Array<{ + name: string; + type: string; + required: boolean; + description: string; + defaultValue?: string; + }>; +} + +type Language = 'curl' | 'javascript' | 'python' | 'go'; + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; +const API_KEY_STORAGE = 'banatie_docs_api_key'; + +const getMethodColor = (method: string): string => { + switch (method) { + case 'GET': + return 'from-cyan-500 to-cyan-600'; + case 'POST': + return 'from-purple-500 to-purple-600'; + case 'PUT': + return 'from-amber-500 to-amber-600'; + case 'DELETE': + return 'from-red-500 to-red-600'; + default: + return 'from-purple-500 to-cyan-500'; + } +}; + +export const InteractiveAPIWidgetC = ({ + endpoint, + method, + description, + parameters = [], +}: InteractiveAPIWidgetCProps) => { + const [language, setLanguage] = useState('curl'); + const [apiKey, setApiKey] = useState(''); + const [isExecuting, setIsExecuting] = useState(false); + const [response, setResponse] = useState(null); + const [error, setError] = useState(null); + const [paramValues, setParamValues] = useState>({}); + const [isExpanded, setIsExpanded] = useState(false); + + useEffect(() => { + const stored = localStorage.getItem(API_KEY_STORAGE); + if (stored) setApiKey(stored); + + const defaults: Record = {}; + parameters.forEach((param) => { + if (param.defaultValue) { + defaults[param.name] = param.defaultValue; + } + }); + setParamValues(defaults); + }, [parameters]); + + const handleApiKeyChange = (value: string) => { + setApiKey(value); + if (value) { + localStorage.setItem(API_KEY_STORAGE, value); + } else { + localStorage.removeItem(API_KEY_STORAGE); + } + }; + + const generateCode = (): string => { + const url = `${API_BASE_URL}${endpoint}`; + + switch (language) { + case 'curl': + return `curl -X ${method} "${url}" \\ + -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ + -H "Content-Type: application/json" \\ + -d '{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9" + }'`; + + case 'javascript': + return `const response = await fetch('${url}', { + method: '${method}', + headers: { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + prompt: 'a futuristic city at sunset', + filename: 'city', + aspectRatio: '16:9' + }) +}); + +const data = await response.json();`; + + case 'python': + return `import requests + +url = '${url}' +headers = { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' +} +data = { + 'prompt': 'a futuristic city at sunset', + 'filename': 'city', + 'aspectRatio': '16:9' +} + +response = requests.${method.toLowerCase()}(url, headers=headers, json=data)`; + + case 'go': + return `package main + +import ( + "bytes" + "encoding/json" + "net/http" +) + +func main() { + url := "${url}" + data := map[string]interface{}{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9", + } + + jsonData, _ := json.Marshal(data) + req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) + req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, _ := client.Do(req) +}`; + + default: + return ''; + } + }; + + const executeRequest = async () => { + if (!apiKey) { + setError('Please enter your API key above ✨'); + return; + } + + setIsExecuting(true); + setError(null); + + try { + const body: Record = {}; + parameters.forEach((param) => { + if (paramValues[param.name]) { + body[param.name] = paramValues[param.name]; + } + }); + + const res = await fetch(`${API_BASE_URL}${endpoint}`, { + method, + headers: { + 'X-API-Key': apiKey, + 'Content-Type': 'application/json', + }, + body: method !== 'GET' ? JSON.stringify(body) : undefined, + }); + + const data = await res.json(); + setResponse(data); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to execute request πŸ˜”'); + } finally { + setIsExecuting(false); + } + }; + + const copyCode = () => { + navigator.clipboard.writeText(generateCode()); + }; + + return ( +
+ {/* API Key Card - Large and Colorful */} +
+
+ πŸ”‘ + +
+
+ handleApiKeyChange(e.target.value)} + placeholder="Enter your API key (saved locally)" + className="flex-1 px-4 py-3 text-sm bg-slate-900/80 border-2 border-purple-500/30 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500/50 transition-all" + /> +
+ {apiKey ? 'βœ“ Ready' : '⚠️ Required'} +
+
+
+ + {/* Main Widget Card - Large Gradient Border */} +
+ {/* Header with Expand Button */} +
+
+
+ {method} +
+ {endpoint} +
+ +
+ +
+ {/* Left: Code Editor */} +
+ {/* Language Tabs - Colorful Pills */} +
+ {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => { + const colors = ['purple', 'cyan', 'amber', 'purple']; + const color = colors[idx]; + return ( + + ); + })} +
+ + {/* Code Display - Gradient Border */} +
+
+ Code Example + +
+
+
+                  {generateCode()}
+                
+
+
+
+ + {/* Right: Response */} +
+

+ πŸ“¦ + Response +

+ +
+
+ {response && ( + + {response.success ? 'βœ“ Success' : 'βœ• Error'} + + )} +
+
+ {error ? ( +
+
+ ⚠️ +
+

Error

+

{error}

+
+
+
+ ) : response ? ( +
+                    {JSON.stringify(response, null, 2)}
+                  
+ ) : ( +
+
+

πŸš€

+

+ Click "Test Now" below to see the response +

+
+
+ )} +
+
+
+
+ + {/* Large Test Now Button */} +
+ +

{description}

+
+
+
+ ); +}; From 1d1a88d07357b9eb0bd59d19e6ef8da1c94f7588 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Tue, 14 Oct 2025 00:54:34 +0700 Subject: [PATCH 02/11] feat: final variant ready --- .../app/docs/final/api/text-to-image/page.tsx | 255 +++++++++++++ .../docs/final/guides/authentication/page.tsx | 336 +++++++++++++++++ apps/landing/src/app/docs/final/page.tsx | 225 +++++++++++ apps/landing/src/app/docs/page.tsx | 107 ++++++ .../components/docs/final/DocsLayoutFinal.tsx | 64 ++++ .../docs/final/DocsSidebarFinal.tsx | 181 +++++++++ .../components/docs/final/DocsTOCFinal.tsx | 102 +++++ .../docs/final/InteractiveAPIWidgetFinal.tsx | 348 ++++++++++++++++++ .../docs/shared/CodeBlockExpanded.tsx | 142 +++++++ .../src/components/docs/shared/Table.tsx | 93 +++++ .../src/components/docs/shared/TipBox.tsx | 90 +++++ .../src/components/shared/SubsectionNav.tsx | 179 +++++++++ 12 files changed, 2122 insertions(+) create mode 100644 apps/landing/src/app/docs/final/api/text-to-image/page.tsx create mode 100644 apps/landing/src/app/docs/final/guides/authentication/page.tsx create mode 100644 apps/landing/src/app/docs/final/page.tsx create mode 100644 apps/landing/src/components/docs/final/DocsLayoutFinal.tsx create mode 100644 apps/landing/src/components/docs/final/DocsSidebarFinal.tsx create mode 100644 apps/landing/src/components/docs/final/DocsTOCFinal.tsx create mode 100644 apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx create mode 100644 apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx create mode 100644 apps/landing/src/components/docs/shared/Table.tsx create mode 100644 apps/landing/src/components/docs/shared/TipBox.tsx create mode 100644 apps/landing/src/components/shared/SubsectionNav.tsx diff --git a/apps/landing/src/app/docs/final/api/text-to-image/page.tsx b/apps/landing/src/app/docs/final/api/text-to-image/page.tsx new file mode 100644 index 0000000..7c1ef9e --- /dev/null +++ b/apps/landing/src/app/docs/final/api/text-to-image/page.tsx @@ -0,0 +1,255 @@ +'use client'; + +/** + * API Reference: Text to Image - Final Variant + * + * Features: + * - SubsectionNav at top + * - InteractiveAPIWidgetFinal with expand + success styling + * - Enhanced tables for parameters and error codes + * - Compact TipBox for parameter descriptions + * - Simplified Next Steps + */ + +import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal'; +import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal'; +import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal'; +import { SubsectionNav } from '@/components/shared/SubsectionNav'; +import { TipBox } from '@/components/docs/shared/TipBox'; +import { Table } from '@/components/docs/shared/Table'; +import { InteractiveAPIWidgetFinal } from '@/components/docs/final/InteractiveAPIWidgetFinal'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'overview', text: 'Overview', level: 2 }, + { id: 'endpoint', text: 'Endpoint', level: 2 }, + { id: 'parameters', text: 'Parameters', level: 2 }, + { id: 'response', text: 'Response', level: 2 }, + { id: 'error-codes', text: 'Error Codes', level: 2 }, + { id: 'interactive', text: 'Try It Live', level: 2 }, + { id: 'next-steps', text: 'Next Steps', level: 2 }, +]; + +const navItems = [ + { label: 'Documentation', href: '/docs/final' }, + { label: 'Demo', href: '/demo' }, + { label: 'Examples', href: '/docs/final/examples' }, +]; + +const parameters = [ + { name: 'prompt', type: 'string', required: true, description: 'Text description of the image to generate' }, + { name: 'filename', type: 'string', required: false, description: 'Output filename (without extension)' }, + { name: 'aspectRatio', type: 'string', required: false, description: 'Image aspect ratio: "1:1", "16:9", "9:16", "4:3"' }, + { name: 'autoEnhance', type: 'boolean', required: false, description: 'Enable AI prompt enhancement for better results' }, +]; + +export default function TextToImageAPIPage() { + return ( + <> + {/* Subsection Navigation */} + + + } + toc={} + > + + + {/* Hero Section */} +
+

Text to Image

+

+ Generate high-quality images from text prompts using AI-powered models. +

+
+ + {/* Overview */} +
+

Overview

+

+ The Text to Image endpoint allows you to generate images from natural language descriptions. + Powered by Google Gemini 2.5 Flash and Imagen 4.0, it produces photorealistic images + optimized for your specified requirements. +

+ + Tip: Enable autoEnhance + to let AI improve your prompts for better image quality. + +
+ + {/* Endpoint */} +
+

Endpoint

+
+
+ + POST + + /api/text-to-image +
+

+ Base URL: https://api.banatie.com +

+
+
+ + {/* Parameters */} +
+

Parameters

+

+ All parameters should be sent in the request body as JSON. +

+ + [ + {param.name}, + {param.type}, + + {param.required ? 'Yes' : 'No'} + , + param.description, + ])} + /> + +
+ + Default Values: If not specified, filename is + auto-generated, aspectRatio defaults + to "1:1", and autoEnhance is false. + +
+ + + {/* Response */} +
+

Response

+

+ On success, the API returns a JSON object containing the generated image URL and metadata. +

+ + +
+ + {/* Error Codes */} +
+

Error Codes

+

+ The API uses standard HTTP status codes and returns descriptive error messages. +

+ +
400, + 'Bad Request', + 'Missing or invalid parameters in the request body', + ], + [ + 401, + 'Unauthorized', + 'Missing or invalid API key in X-API-Key header', + ], + [ + 429, + 'Rate Limit', + 'Too many requests. Check rate limit headers for retry timing', + ], + [ + 500, + 'Server Error', + 'Internal server error. Contact support if persists', + ], + ]} + /> + +
+ + Rate Limits: Project API keys are limited to 100 requests per hour. + Upgrade your plan for higher limits. + +
+ + + {/* Interactive Widget */} +
+

Try It Live

+

+ Test the API directly from this page. Enter your API key and customize the parameters below. +

+ + +
+ + {/* Next Steps */} +
+

Next Steps

+ + +
+ + + ); +} diff --git a/apps/landing/src/app/docs/final/guides/authentication/page.tsx b/apps/landing/src/app/docs/final/guides/authentication/page.tsx new file mode 100644 index 0000000..224aaf3 --- /dev/null +++ b/apps/landing/src/app/docs/final/guides/authentication/page.tsx @@ -0,0 +1,336 @@ +'use client'; + +/** + * Authentication Guide - Final Variant + * + * Features: + * - SubsectionNav at top + * - Prominent TipBox for security warnings + * - Compact TipBox for general tips + * - Enhanced tables for rate limits and key types + * - Simplified Next Steps + */ + +import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal'; +import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal'; +import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal'; +import { SubsectionNav } from '@/components/shared/SubsectionNav'; +import { TipBox } from '@/components/docs/shared/TipBox'; +import { Table } from '@/components/docs/shared/Table'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'overview', text: 'Overview', level: 2 }, + { id: 'api-keys', text: 'API Keys', level: 2 }, + { id: 'key-types', text: 'Key Types', level: 3 }, + { id: 'creating-keys', text: 'Creating Keys', level: 3 }, + { id: 'using-keys', text: 'Using API Keys', level: 2 }, + { id: 'rate-limits', text: 'Rate Limits', level: 2 }, + { id: 'security', text: 'Security Best Practices', level: 2 }, + { id: 'next-steps', text: 'Next Steps', level: 2 }, +]; + +const navItems = [ + { label: 'Documentation', href: '/docs/final' }, + { label: 'Demo', href: '/demo' }, + { label: 'Examples', href: '/docs/final/examples' }, +]; + +export default function AuthenticationGuidePage() { + return ( + <> + {/* Subsection Navigation */} + + + } + toc={} + > + + + {/* Hero Section */} +
+

Authentication

+

+ Learn how to authenticate with the Banatie API using API keys, manage rate limits, and + implement security best practices. +

+
+ + {/* Overview */} +
+

Overview

+

+ Banatie uses API keys to authenticate requests. All API endpoints require authentication + via the X-API-Key header. + API keys are tied to organizations and projects, providing fine-grained access control. +

+ + + Quick Start: New to API authentication? Check out our{' '} + + Getting Started guide + {' '} + for a step-by-step walkthrough. + +
+ + {/* API Keys */} +
+

API Keys

+ +
+

Key Types

+

+ Banatie supports two types of API keys, each with different permissions and use cases: +

+ +
Master Key, + 'Full admin access, can create/revoke keys', + Never expires, + 'Server-side admin operations, key management', + ], + [ + Project Key, + 'Image generation only', + 90 days, + 'Application integration, API requests', + ], + ]} + /> + +
+ + Master Key Security: Master keys have full + administrative access and never expire. Store them securely in encrypted vaults or + secret managers. Never expose master keys in client-side code, logs, or version control. + Use project keys for application integration whenever possible. + +
+ + +
+

Creating Keys

+

+ For first-time setup, use the bootstrap endpoint to create your initial master key: +

+ + + +
+

+ Once you have a master key, you can create project keys for your applications: +

+ + +
+
+ + + {/* Using API Keys */} +
+

Using API Keys

+

+ Include your API key in the X-API-Key header + with every request: +

+ + + +
+ + Environment Variables: Store API keys in environment variables, not + hardcoded in your application. Example:{' '} + BANATIE_API_KEY + +
+
+ + {/* Rate Limits */} +
+

Rate Limits

+

+ API keys are subject to rate limits to ensure fair usage and system stability. Limits + vary by key type and plan tier: +

+ +
Master Key, + Unlimited, + 'N/A', + 'N/A', + ], + [ + Project Key (Free), + 100 requests/hour, + '1 hour rolling', + Yes, + ], + [ + Project Key (Pro), + 1,000 requests/hour, + '1 hour rolling', + Yes, + ], + ]} + /> + +
+

+ When you exceed rate limits, the API returns a 429 Too Many Requests status. + Check the response headers for retry timing: +

+ + +
+ + + {/* Security Best Practices */} +
+

Security Best Practices

+ + + Critical Security Guidelines: +
    +
  • Never commit API keys to version control systems (Git, SVN, etc.)
  • +
  • Store keys in environment variables or secret management services
  • +
  • Use project keys in applications, reserve master keys for admin operations
  • +
  • Rotate keys regularly, especially after team member changes
  • +
  • Implement server-side API calls for production applications
  • +
  • Monitor API key usage in your dashboard for suspicious activity
  • +
+
+ +
+

Key Rotation Example

+ +
+
+ + {/* Next Steps */} +
+

Next Steps

+ + +
+ + + ); +} diff --git a/apps/landing/src/app/docs/final/page.tsx b/apps/landing/src/app/docs/final/page.tsx new file mode 100644 index 0000000..521d23b --- /dev/null +++ b/apps/landing/src/app/docs/final/page.tsx @@ -0,0 +1,225 @@ +'use client'; + +/** + * Getting Started Page - Final Variant + * + * Production-ready documentation landing page + * Features: + * - SubsectionNav at top + * - Both TipBox styles (compact + prominent) + * - Enhanced tables + * - Simplified Next Steps (2 cards only) + * - Clean, accessible design + */ + +import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal'; +import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal'; +import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal'; +import { SubsectionNav } from '@/components/shared/SubsectionNav'; +import { TipBox } from '@/components/docs/shared/TipBox'; +import { Table } from '@/components/docs/shared/Table'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; + +const tocItems = [ + { id: 'introduction', text: 'Introduction', level: 2 }, + { id: 'quick-start', text: 'Quick Start', level: 2 }, + { id: 'installation', text: 'Installation', level: 3 }, + { id: 'authentication', text: 'Authentication', level: 3 }, + { id: 'first-request', text: 'Your First Request', level: 2 }, + { id: 'next-steps', text: 'Next Steps', level: 2 }, +]; + +const navItems = [ + { label: 'Documentation', href: '/docs/final' }, + { label: 'Demo', href: '/demo' }, + { label: 'Examples', href: '/docs/final/examples' }, +]; + +export default function GettingStartedPageFinal() { + return ( + <> + {/* Subsection Navigation */} + + + } + toc={} + > + + + {/* Hero Section */} +
+

Getting Started

+

+ Welcome to the Banatie API documentation. Learn how to integrate AI-powered image + generation into your applications in minutes. +

+
+ + {/* Introduction */} +
+

Introduction

+

+ Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini + 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into + production-ready visuals. +

+

+ Whether you are building a content creation platform, e-commerce site, or creative tool, + Banatie provides the infrastructure you need to generate high-quality images at scale. +

+ + {/* Compact Tip Box */} + + New to API integration? Start with our{' '} + + code examples + {' '} + to see common use cases in action. + +
+ + {/* Quick Start */} +
+

Quick Start

+ +
+

Installation

+

+ Banatie is a REST API, so you do not need to install any libraries. However, we provide + SDKs for popular languages to make integration easier. +

+ + +
+ +
+

Authentication

+

+ All API requests require an API key. You can create an API key from your dashboard or + using the bootstrap endpoint for initial setup. +

+ + {/* Prominent Tip Box for Security Warning */} +
+ + Security Best Practice: Keep your API keys secure. + Never commit them to public repositories or expose them in client-side code. Use environment + variables and server-side implementations for production applications. + +
+ + +
+
+ + {/* First Request */} +
+

Your First Request

+

+ Let's generate your first image! This example uses curl, but you can use any HTTP client + or our SDKs. +

+ + + +
+

Expected Response:

+
+
+ + βœ“ 200 Success + +
+
+                {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
+    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "enhancedPrompt": "A breathtaking mountain landscape..."
+    }
+  }
+}`}
+              
+
+
+
+ + {/* 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/app/docs/page.tsx b/apps/landing/src/app/docs/page.tsx index 34fdbce..b229630 100644 --- a/apps/landing/src/app/docs/page.tsx +++ b/apps/landing/src/app/docs/page.tsx @@ -53,6 +53,113 @@ export default function DocsIndexPage() {

+ {/* Final Variant - Recommended */} + + + {/* Other Variants for Reference */} +
+

Other Variants (Reference)

+

+ Explore the original variants that inspired the final design +

+
+ {/* Variant Cards */}
{/* Variant A: Clean & Minimal */} diff --git a/apps/landing/src/components/docs/final/DocsLayoutFinal.tsx b/apps/landing/src/components/docs/final/DocsLayoutFinal.tsx new file mode 100644 index 0000000..db66cc7 --- /dev/null +++ b/apps/landing/src/components/docs/final/DocsLayoutFinal.tsx @@ -0,0 +1,64 @@ +'use client'; + +/** + * Documentation Layout - Final Variant + * + * Based on Variant A: Clean & Minimal with enhancements + * This is the production-ready version combining the best aspects + * + * Layout Structure: + * - Left Sidebar: Thin (256px) with minimal design + * - Content Area: Wide margins (max-w-3xl) for comfortable reading + * - Right TOC: Subtle and unobtrusive (224px) + * + * Responsive Behavior: + * - Mobile (<768px): Single column, sidebars become overlays + * - Tablet (768px-1024px): Content + TOC only + * - Desktop (>1024px): Full three-column layout + * + * Design Characteristics: + * - Generous whitespace + * - Subtle borders and shadows + * - Focus on content clarity + * - Minimal visual noise + * - Accessibility compliant (WCAG 2.1 AA) + */ + +import { ReactNode } from 'react'; + +interface DocsLayoutFinalProps { + sidebar: ReactNode; + children: ReactNode; + toc: ReactNode; +} + +export const DocsLayoutFinal = ({ sidebar, children, toc }: DocsLayoutFinalProps) => { + return ( +
+ {/* Animated gradient background (matching landing page) */} +
+
+
+
+ +
+ {/* Left Sidebar - Thin, minimal design */} + + + {/* Main Content Area - Wide margins for comfortable reading */} +
+
+ {children} +
+
+ + {/* Right TOC - Subtle and unobtrusive */} + +
+
+ ); +}; diff --git a/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx b/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx new file mode 100644 index 0000000..e7fe7c9 --- /dev/null +++ b/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx @@ -0,0 +1,181 @@ +'use client'; + +/** + * Documentation Sidebar - Final Variant + * + * Based on Variant A with FIXED active states + * + * Key Improvements: + * - Consistent active state styling for both parent and child items + * - Clean left border indicator (no background boxes) + * - Parent active: purple left border + white text + * - Child active: purple left border + white text (NO background) + * + * Features: + * - Thin sidebar with subtle hover states + * - Collapsible section groups + * - Minimal icons (chevron for expandable items) + * - Clean, uncluttered appearance + * + * Navigation Structure: + * - Getting Started + * - API Reference (collapsible) + * - Guides (collapsible) + * - Examples + */ + +import { useState } from 'react'; + +interface NavItem { + label: string; + href: string; + icon?: string; + children?: NavItem[]; +} + +interface DocsSidebarFinalProps { + currentPath: string; +} + +const navigationItems: NavItem[] = [ + { + label: 'Getting Started', + href: '/docs/final', + icon: 'πŸš€', + }, + { + label: 'API Reference', + href: '/docs/final/api', + icon: 'πŸ“š', + children: [ + { label: 'Text to Image', href: '/docs/final/api/text-to-image' }, + { label: 'Upload', href: '/docs/final/api/upload' }, + { label: 'Images', href: '/docs/final/api/images' }, + ], + }, + { + label: 'Guides', + href: '/docs/final/guides', + icon: 'πŸ“–', + children: [ + { label: 'Authentication', href: '/docs/final/guides/authentication' }, + { label: 'Error Handling', href: '/docs/final/guides/error-handling' }, + { label: 'Rate Limits', href: '/docs/final/guides/rate-limits' }, + ], + }, + { + label: 'Examples', + href: '/docs/final/examples', + icon: 'πŸ’‘', + }, +]; + +export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => { + const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); + + const toggleSection = (label: string) => { + setExpandedSections((prev) => + prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] + ); + }; + + const isActive = (href: string) => currentPath === href; + const isExpanded = (label: string) => expandedSections.includes(label); + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/final/DocsTOCFinal.tsx b/apps/landing/src/components/docs/final/DocsTOCFinal.tsx new file mode 100644 index 0000000..0a25277 --- /dev/null +++ b/apps/landing/src/components/docs/final/DocsTOCFinal.tsx @@ -0,0 +1,102 @@ +'use client'; + +/** + * Table of Contents - Final Variant + * + * Based on Variant A: Clean & Minimal (no changes needed) + * + * Features: + * - Small indicator dots for section levels + * - Smooth scroll to section + * - Active section highlighting (purple text) + * - Sticky positioning + * - Minimal visual weight + * + * Behavior: + * - Extracts H2 and H3 headings from content + * - Tracks scroll position to highlight active section + * - Click to smooth scroll to section + */ + +import { useEffect, useState } from 'react'; + +interface TocItem { + id: string; + text: string; + level: number; +} + +interface DocsTOCFinalProps { + items: TocItem[]; +} + +export const DocsTOCFinal = ({ items }: DocsTOCFinalProps) => { + const [activeId, setActiveId] = useState(''); + + useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setActiveId(entry.target.id); + } + }); + }, + { rootMargin: '-20% 0px -35% 0px' } + ); + + items.forEach((item) => { + const element = document.getElementById(item.id); + if (element) observer.observe(element); + }); + + return () => observer.disconnect(); + }, [items]); + + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }; + + if (items.length === 0) { + return null; + } + + return ( + + ); +}; diff --git a/apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx b/apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx new file mode 100644 index 0000000..8f45243 --- /dev/null +++ b/apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx @@ -0,0 +1,348 @@ +'use client'; + +/** + * Interactive API Widget - Final Variant + * + * Enhanced version of Variant A with: + * 1. Expand button for full-screen code view + * 2. Success response styling (green accent) + * 3. Error response styling (red accent) + * 4. Clickable image URLs in response + * 5. Status badges (200 Success, Error) + * + * Features: + * - Multi-language code tabs (curl, JavaScript, Python, Go) + * - API key input field (persists via localStorage) + * - "Try It" button to execute live requests + * - Response viewer with enhanced styling + * - Clean, focused design + */ + +import { useState, useEffect } from 'react'; +import { CodeBlockExpanded } from '@/components/docs/shared/CodeBlockExpanded'; + +interface InteractiveAPIWidgetFinalProps { + endpoint: string; + method: 'GET' | 'POST' | 'PUT' | 'DELETE'; + description: string; + parameters?: Array<{ + name: string; + type: string; + required: boolean; + description: string; + defaultValue?: string; + }>; +} + +type Language = 'curl' | 'javascript' | 'python' | 'go'; + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; +const API_KEY_STORAGE = 'banatie_docs_api_key'; + +export const InteractiveAPIWidgetFinal = ({ + endpoint, + method, + description, + parameters = [], +}: InteractiveAPIWidgetFinalProps) => { + const [language, setLanguage] = useState('curl'); + const [apiKey, setApiKey] = useState(''); + const [isExecuting, setIsExecuting] = useState(false); + const [response, setResponse] = useState(null); + const [error, setError] = useState(null); + const [isExpanded, setIsExpanded] = useState(false); + + // Parameter values + const [paramValues, setParamValues] = useState>({}); + + // Load API key from localStorage + useEffect(() => { + const stored = localStorage.getItem(API_KEY_STORAGE); + if (stored) setApiKey(stored); + + // Initialize parameter default values + const defaults: Record = {}; + parameters.forEach((param) => { + if (param.defaultValue) { + defaults[param.name] = param.defaultValue; + } + }); + setParamValues(defaults); + }, [parameters]); + + // Save API key to localStorage + const handleApiKeyChange = (value: string) => { + setApiKey(value); + if (value) { + localStorage.setItem(API_KEY_STORAGE, value); + } else { + localStorage.removeItem(API_KEY_STORAGE); + } + }; + + // Generate code examples + const generateCode = (): string => { + const url = `${API_BASE_URL}${endpoint}`; + + switch (language) { + case 'curl': + return `curl -X ${method} "${url}" \\ + -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ + -H "Content-Type: application/json" \\ + -d '{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9" + }'`; + + case 'javascript': + return `const response = await fetch('${url}', { + method: '${method}', + headers: { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + prompt: 'a futuristic city at sunset', + filename: 'city', + aspectRatio: '16:9' + }) +}); + +const data = await response.json(); +console.log(data);`; + + case 'python': + return `import requests + +url = '${url}' +headers = { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' +} +data = { + 'prompt': 'a futuristic city at sunset', + 'filename': 'city', + 'aspectRatio': '16:9' +} + +response = requests.${method.toLowerCase()}(url, headers=headers, json=data) +print(response.json())`; + + case 'go': + return `package main + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +func main() { + url := "${url}" + data := map[string]interface{}{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9", + } + + jsonData, _ := json.Marshal(data) + req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) + req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, _ := client.Do(req) + defer resp.Body.Close() +}`; + + default: + return ''; + } + }; + + // Execute API request + const executeRequest = async () => { + if (!apiKey) { + setError('Please enter your API key'); + return; + } + + setIsExecuting(true); + setError(null); + + try { + const body: Record = {}; + parameters.forEach((param) => { + if (paramValues[param.name]) { + body[param.name] = paramValues[param.name]; + } + }); + + const res = await fetch(`${API_BASE_URL}${endpoint}`, { + method, + headers: { + 'X-API-Key': apiKey, + 'Content-Type': 'application/json', + }, + body: method !== 'GET' ? JSON.stringify(body) : undefined, + }); + + const data = await res.json(); + setResponse(data); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to execute request'); + } finally { + setIsExecuting(false); + } + }; + + // Copy code to clipboard + const copyCode = () => { + navigator.clipboard.writeText(generateCode()); + }; + + // Render response with clickable URLs + const renderResponse = (data: any): string => { + return JSON.stringify(data, null, 2); + }; + + // Check if response is success + const isSuccess = response && response.success === true; + + return ( + <> +
+ {/* Header with API Key Input */} +
+
+
+

Try it out

+

{description}

+
+
+ handleApiKeyChange(e.target.value)} + placeholder="Enter your API key" + className="w-full px-3 py-2 text-xs bg-slate-800 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" + /> +
+
+
+ + {/* Language Tabs with Expand Button */} +
+
+ {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => ( + + ))} +
+
+ + +
+
+ + {/* Code Display */} +
+
+            {generateCode()}
+          
+
+ + {/* Try It Button */} +
+ +
+ + {/* Response Section - Enhanced with success/error styling */} + {(response || error) && ( +
+
+

Response

+ {error ? ( + // Error Response +
+
+ + βœ— Error + +
+

{error}

+
+ ) : isSuccess ? ( + // Success Response +
+
+ + βœ“ 200 Success + +
+
+                    {renderResponse(response)}
+                  
+
+ ) : ( + // Normal Response +
+                  {renderResponse(response)}
+                
+ )} +
+
+ )} +
+ + {/* Expanded Code Modal */} + setIsExpanded(false)} + code={generateCode()} + language={language} + filename={`example.${language === 'javascript' ? 'js' : language === 'python' ? 'py' : language}`} + /> + + ); +}; diff --git a/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx b/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx new file mode 100644 index 0000000..8f28869 --- /dev/null +++ b/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx @@ -0,0 +1,142 @@ +'use client'; + +/** + * Code Block Expanded Modal Component + * + * Full-screen code viewer for better readability + * Features: + * - Full-screen overlay with dark backdrop + * - Centered modal with max-width constraint + * - Close button (X) in top-right + * - Escape key support + * - Larger code text in expanded mode + * - Copy button still visible + * - Language badge + * + * Usage: + * setIsOpen(false)} + * code={codeString} + * language="javascript" + * filename="example.js" + * /> + */ + +import { useEffect } from 'react'; + +interface CodeBlockExpandedProps { + isOpen: boolean; + onClose: () => void; + code: string; + language: string; + filename?: string; +} + +export const CodeBlockExpanded = ({ + isOpen, + onClose, + code, + language, + filename, +}: CodeBlockExpandedProps) => { + // Handle escape key + useEffect(() => { + const handleEscape = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + onClose(); + } + }; + + if (isOpen) { + document.addEventListener('keydown', handleEscape); + // Prevent body scroll when modal is open + document.body.style.overflow = 'hidden'; + } + + return () => { + document.removeEventListener('keydown', handleEscape); + document.body.style.overflow = 'unset'; + }; + }, [isOpen, onClose]); + + // Copy to clipboard + const copyCode = () => { + navigator.clipboard.writeText(code); + }; + + if (!isOpen) return null; + + return ( +
+ {/* Modal Content */} +
e.stopPropagation()} + > + {/* Header */} +
+
+ {filename && ( + {filename} + )} + + {language} + +
+ +
+ {/* Copy Button */} + + + {/* Close Button */} + +
+
+ + {/* Code Content */} +
+
+            {code}
+          
+
+ + {/* Hint Text */} +
+

+ Press Esc to close +

+
+
+
+ ); +}; diff --git a/apps/landing/src/components/docs/shared/Table.tsx b/apps/landing/src/components/docs/shared/Table.tsx new file mode 100644 index 0000000..e50ade8 --- /dev/null +++ b/apps/landing/src/components/docs/shared/Table.tsx @@ -0,0 +1,93 @@ +'use client'; + +/** + * Enhanced Table Component + * + * Features: + * - Larger font: text-base for cells (more readable) + * - Better padding: py-4 px-6 (spacious) + * - Full-width with proper column distribution + * - Hover states for rows + * - Responsive: horizontal scroll on mobile + * - Optional sortable headers (UI only, no logic yet) + * + * Usage: + *
+ */ + +import { ReactNode } from 'react'; + +interface TableProps { + headers: string[]; + rows: (string | ReactNode)[][]; + sortable?: boolean; +} + +export const Table = ({ headers, rows, sortable = false }: TableProps) => { + return ( +
+
+ {/* Header */} + + + {headers.map((header, idx) => ( + + ))} + + + + {/* Body */} + + {rows.map((row, rowIdx) => ( + + {row.map((cell, cellIdx) => ( + + ))} + + ))} + +
+
+ {header} + {sortable && ( + + )} +
+
+ {cell} +
+ + ); +}; diff --git a/apps/landing/src/components/docs/shared/TipBox.tsx b/apps/landing/src/components/docs/shared/TipBox.tsx new file mode 100644 index 0000000..0ff884b --- /dev/null +++ b/apps/landing/src/components/docs/shared/TipBox.tsx @@ -0,0 +1,90 @@ +'use client'; + +/** + * TipBox Component - Dual Style System + * + * Provides two distinct styles for callouts/notes: + * + * 1. Compact Style (Variant A inspired): + * - Small emoji icon on left + * - Compact padding (p-4) + * - Smaller text (text-sm) + * - Subtle background with thin border + * - Best for minor notes and tips + * + * 2. Prominent Style (Adapted from Variant C): + * - NO icon + * - Larger padding (p-6) + * - Larger text (text-base) + * - Gradient border with soft glow + * - More visual weight + * - Best for important warnings and security notices + * + * Usage: + * + * This is a compact tip + * + * + * + * This is an important security warning + * + */ + +import { ReactNode } from 'react'; + +type TipType = 'info' | 'warning' | 'success'; +type TipVariant = 'compact' | 'prominent'; + +interface TipBoxProps { + children: ReactNode; + variant?: TipVariant; + type?: TipType; +} + +const icons: Record = { + info: 'πŸ’‘', + warning: '⚠️', + success: 'βœ“', +}; + +const compactStyles: Record = { + info: 'bg-purple-500/10 border-purple-500/20 text-purple-300', + warning: 'bg-amber-500/10 border-amber-500/20 text-amber-300', + success: 'bg-green-500/10 border-green-500/20 text-green-300', +}; + +const prominentStyles: Record = { + info: 'bg-gradient-to-br from-purple-500/5 via-cyan-500/5 to-purple-500/5 border-purple-500/30 text-gray-300 shadow-lg shadow-purple-500/10', + warning: 'bg-gradient-to-br from-amber-500/5 via-orange-500/5 to-amber-500/5 border-amber-500/30 text-gray-300 shadow-lg shadow-amber-500/10', + success: 'bg-gradient-to-br from-green-500/5 via-emerald-500/5 to-green-500/5 border-green-500/30 text-gray-300 shadow-lg shadow-green-500/10', +}; + +export const TipBox = ({ children, variant = 'compact', type = 'info' }: TipBoxProps) => { + const isCompact = variant === 'compact'; + const icon = icons[type]; + const styleClass = isCompact ? compactStyles[type] : prominentStyles[type]; + + if (isCompact) { + return ( +
+ {icon} +
{children}
+
+ ); + } + + // Prominent style + return ( +
+
{children}
+
+ ); +}; diff --git a/apps/landing/src/components/shared/SubsectionNav.tsx b/apps/landing/src/components/shared/SubsectionNav.tsx new file mode 100644 index 0000000..1ae7314 --- /dev/null +++ b/apps/landing/src/components/shared/SubsectionNav.tsx @@ -0,0 +1,179 @@ +'use client'; + +/** + * Subsection Navigation Component + * + * Reusable navigation bar for documentation and other subsections + * Features: + * - Dark nav bar with decorative wave line + * - Active state indicator (purple underline/highlight) + * - "Join Beta" CTA button on the right + * - Responsive (hamburger menu on mobile) + * - Can be reused across landing app sections + * + * Usage: + * + */ + +import { useState } from 'react'; + +interface NavItem { + label: string; + href: string; +} + +interface SubsectionNavProps { + items: NavItem[]; + currentPath: string; + ctaText?: string; + ctaHref?: string; + onCtaClick?: () => void; +} + +export const SubsectionNav = ({ + items, + currentPath, + ctaText = 'Join Beta', + ctaHref = '/signup', + onCtaClick, +}: SubsectionNavProps) => { + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + + const isActive = (href: string) => currentPath.startsWith(href); + + return ( + + ); +}; From 658f1420db40d1b4e4449cd0e2d56f4e7dea90b2 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Tue, 14 Oct 2025 01:07:50 +0700 Subject: [PATCH 03/11] feat: polish --- apps/landing/src/app/globals.css | 37 +++++ .../docs/final/DocsSidebarFinal.tsx | 2 +- .../docs/final/InteractiveAPIWidgetFinal.tsx | 127 ++++++++++++++++-- .../docs/shared/CodeBlockExpanded.tsx | 75 ++++++++--- .../src/components/shared/SubsectionNav.tsx | 28 +--- 5 files changed, 210 insertions(+), 59 deletions(-) diff --git a/apps/landing/src/app/globals.css b/apps/landing/src/app/globals.css index 762d09f..bafa22b 100644 --- a/apps/landing/src/app/globals.css +++ b/apps/landing/src/app/globals.css @@ -62,3 +62,40 @@ body { html { scroll-behavior: smooth; } + +/* Custom Scrollbars for Dark Theme */ +/* Firefox */ +* { + scrollbar-width: thin; + scrollbar-color: rgb(71, 85, 105) rgb(15, 23, 42); /* slate-600 on slate-950 */ +} + +/* Webkit browsers (Chrome, Safari, Edge) */ +*::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +*::-webkit-scrollbar-track { + background: rgb(15, 23, 42); /* slate-950 */ + border-radius: 4px; +} + +*::-webkit-scrollbar-thumb { + background: rgb(71, 85, 105); /* slate-600 */ + border-radius: 4px; + border: 2px solid rgb(15, 23, 42); /* slate-950 */ +} + +*::-webkit-scrollbar-thumb:hover { + background: rgb(100, 116, 139); /* slate-500 */ +} + +/* Code blocks - slightly brighter scrollbar for better visibility */ +pre::-webkit-scrollbar-thumb { + background: rgb(100, 116, 139); /* slate-500 */ +} + +pre::-webkit-scrollbar-thumb:hover { + background: rgb(148, 163, 184); /* slate-400 */ +} diff --git a/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx b/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx index e7fe7c9..7c4e60c 100644 --- a/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx +++ b/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx @@ -146,7 +146,7 @@ export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => { = {}; + // Initialize with proper defaults + const defaults: Record = { + prompt: 'a futuristic city at sunset', + filename: 'demo', + aspectRatio: '16:9', + }; + + // Override with parameter defaults if provided parameters.forEach((param) => { if (param.defaultValue) { defaults[param.name] = param.defaultValue; } }); + setParamValues(defaults); }, [parameters]); @@ -162,6 +169,80 @@ func main() { } }; + // Generate all language codes at once + const generateAllCodes = (): Record => { + const url = `${API_BASE_URL}${endpoint}`; + + return { + curl: `curl -X ${method} "${url}" \\ + -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ + -H "Content-Type: application/json" \\ + -d '{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9" + }'`, + + javascript: `const response = await fetch('${url}', { + method: '${method}', + headers: { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + prompt: 'a futuristic city at sunset', + filename: 'city', + aspectRatio: '16:9' + }) +}); + +const data = await response.json(); +console.log(data);`, + + python: `import requests + +url = '${url}' +headers = { + 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', + 'Content-Type': 'application/json' +} +data = { + 'prompt': 'a futuristic city at sunset', + 'filename': 'city', + 'aspectRatio': '16:9' +} + +response = requests.${method.toLowerCase()}(url, headers=headers, json=data) +print(response.json())`, + + go: `package main + +import ( + "bytes" + "encoding/json" + "net/http" +) + +func main() { + url := "${url}" + data := map[string]interface{}{ + "prompt": "a futuristic city at sunset", + "filename": "city", + "aspectRatio": "16:9", + } + + jsonData, _ := json.Marshal(data) + req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) + req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, _ := client.Do(req) + defer resp.Body.Close() +}`, + }; + }; + // Execute API request const executeRequest = async () => { if (!apiKey) { @@ -171,13 +252,21 @@ func main() { setIsExecuting(true); setError(null); + setResponse(null); try { - const body: Record = {}; - parameters.forEach((param) => { - if (paramValues[param.name]) { - body[param.name] = paramValues[param.name]; - } + // Build proper request body + const body = { + prompt: paramValues.prompt || 'a futuristic city at sunset', + filename: paramValues.filename || 'demo', + aspectRatio: paramValues.aspectRatio || '16:9', + }; + + console.log('πŸ”΅ API Request:', { + url: `${API_BASE_URL}${endpoint}`, + method, + headers: { 'X-API-Key': apiKey.substring(0, 10) + '...' }, + body, }); const res = await fetch(`${API_BASE_URL}${endpoint}`, { @@ -189,10 +278,27 @@ func main() { body: method !== 'GET' ? JSON.stringify(body) : undefined, }); + console.log('🟒 Response Status:', res.status, res.statusText); + + // Handle non-OK responses + if (!res.ok) { + let errorMessage = `HTTP ${res.status}: ${res.statusText}`; + try { + const errorData = await res.json(); + errorMessage = errorData.message || errorData.error || errorMessage; + } catch { + // Response is not JSON + } + throw new Error(errorMessage); + } + const data = await res.json(); + console.log('βœ… Response Data:', data); setResponse(data); } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to execute request'); + console.error('❌ API Error:', err); + const errorMsg = err instanceof Error ? err.message : 'Failed to execute request'; + setError(`Request failed: ${errorMsg}`); } finally { setIsExecuting(false); } @@ -339,9 +445,8 @@ func main() { setIsExpanded(false)} - code={generateCode()} - language={language} - filename={`example.${language === 'javascript' ? 'js' : language === 'python' ? 'py' : language}`} + codes={generateAllCodes()} + initialLanguage={language} /> ); diff --git a/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx b/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx index 8f28869..e57a428 100644 --- a/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx +++ b/apps/landing/src/components/docs/shared/CodeBlockExpanded.tsx @@ -7,39 +7,52 @@ * Features: * - Full-screen overlay with dark backdrop * - Centered modal with max-width constraint + * - Language tabs for switching between languages * - Close button (X) in top-right * - Escape key support * - Larger code text in expanded mode - * - Copy button still visible + * - Copy button with feedback * - Language badge * * Usage: * setIsOpen(false)} - * code={codeString} - * language="javascript" + * codes={{ curl: '...', javascript: '...', python: '...', go: '...' }} + * initialLanguage="curl" * filename="example.js" * /> */ -import { useEffect } from 'react'; +import { useState, useEffect } from 'react'; + +type Language = 'curl' | 'javascript' | 'python' | 'go'; interface CodeBlockExpandedProps { isOpen: boolean; onClose: () => void; - code: string; - language: string; + codes: Record; + initialLanguage: Language; filename?: string; } export const CodeBlockExpanded = ({ isOpen, onClose, - code, - language, + codes, + initialLanguage, filename, }: CodeBlockExpandedProps) => { + const [currentLanguage, setCurrentLanguage] = useState(initialLanguage); + const [copied, setCopied] = useState(false); + + // Update language when modal opens + useEffect(() => { + if (isOpen) { + setCurrentLanguage(initialLanguage); + } + }, [isOpen, initialLanguage]); + // Handle escape key useEffect(() => { const handleEscape = (e: KeyboardEvent) => { @@ -62,7 +75,9 @@ export const CodeBlockExpanded = ({ // Copy to clipboard const copyCode = () => { - navigator.clipboard.writeText(code); + navigator.clipboard.writeText(codes[currentLanguage]); + setCopied(true); + setTimeout(() => setCopied(false), 2000); }; if (!isOpen) return null; @@ -77,27 +92,43 @@ export const CodeBlockExpanded = ({ > {/* Modal Content */}
e.stopPropagation()} > {/* Header */}
+ {/* Left: Language Tabs */}
- {filename && ( - {filename} - )} - - {language} - + Language: +
+ {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => ( + + ))} +
+ {/* Right: Actions */}
{/* Copy Button */} {/* Close Button */} @@ -123,10 +154,10 @@ export const CodeBlockExpanded = ({
- {/* Code Content */} -
-
-            {code}
+        {/* Code Content - Larger text, better spacing */}
+        
+
+            {codes[currentLanguage]}
           
diff --git a/apps/landing/src/components/shared/SubsectionNav.tsx b/apps/landing/src/components/shared/SubsectionNav.tsx index 1ae7314..edb1485 100644 --- a/apps/landing/src/components/shared/SubsectionNav.tsx +++ b/apps/landing/src/components/shared/SubsectionNav.tsx @@ -50,7 +50,7 @@ export const SubsectionNav = ({
-
+ ); } diff --git a/apps/landing/src/app/docs/final/page.tsx b/apps/landing/src/app/docs/final/page.tsx deleted file mode 100644 index 521d23b..0000000 --- a/apps/landing/src/app/docs/final/page.tsx +++ /dev/null @@ -1,225 +0,0 @@ -'use client'; - -/** - * Getting Started Page - Final Variant - * - * Production-ready documentation landing page - * Features: - * - SubsectionNav at top - * - Both TipBox styles (compact + prominent) - * - Enhanced tables - * - Simplified Next Steps (2 cards only) - * - Clean, accessible design - */ - -import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal'; -import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal'; -import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal'; -import { SubsectionNav } from '@/components/shared/SubsectionNav'; -import { TipBox } from '@/components/docs/shared/TipBox'; -import { Table } from '@/components/docs/shared/Table'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'introduction', text: 'Introduction', level: 2 }, - { id: 'quick-start', text: 'Quick Start', level: 2 }, - { id: 'installation', text: 'Installation', level: 3 }, - { id: 'authentication', text: 'Authentication', level: 3 }, - { id: 'first-request', text: 'Your First Request', level: 2 }, - { id: 'next-steps', text: 'Next Steps', level: 2 }, -]; - -const navItems = [ - { label: 'Documentation', href: '/docs/final' }, - { label: 'Demo', href: '/demo' }, - { label: 'Examples', href: '/docs/final/examples' }, -]; - -export default function GettingStartedPageFinal() { - return ( - <> - {/* Subsection Navigation */} - - - } - toc={} - > - - - {/* Hero Section */} -
-

Getting Started

-

- Welcome to the Banatie API documentation. Learn how to integrate AI-powered image - generation into your applications in minutes. -

-
- - {/* Introduction */} -
-

Introduction

-

- Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini - 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into - production-ready visuals. -

-

- Whether you are building a content creation platform, e-commerce site, or creative tool, - Banatie provides the infrastructure you need to generate high-quality images at scale. -

- - {/* Compact Tip Box */} - - New to API integration? Start with our{' '} - - code examples - {' '} - to see common use cases in action. - -
- - {/* Quick Start */} -
-

Quick Start

- -
-

Installation

-

- Banatie is a REST API, so you do not need to install any libraries. However, we provide - SDKs for popular languages to make integration easier. -

- - -
- -
-

Authentication

-

- All API requests require an API key. You can create an API key from your dashboard or - using the bootstrap endpoint for initial setup. -

- - {/* Prominent Tip Box for Security Warning */} -
- - Security Best Practice: Keep your API keys secure. - Never commit them to public repositories or expose them in client-side code. Use environment - variables and server-side implementations for production applications. - -
- - -
-
- - {/* First Request */} -
-

Your First Request

-

- Let's generate your first image! This example uses curl, but you can use any HTTP client - or our SDKs. -

- - - -
-

Expected Response:

-
-
- - βœ“ 200 Success - -
-
-                {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
-    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "enhancedPrompt": "A breathtaking mountain landscape..."
-    }
-  }
-}`}
-              
-
-
-
- - {/* 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/app/docs/final/guides/authentication/page.tsx b/apps/landing/src/app/docs/guides/authentication/page.tsx similarity index 95% rename from apps/landing/src/app/docs/final/guides/authentication/page.tsx rename to apps/landing/src/app/docs/guides/authentication/page.tsx index 224aaf3..68c685f 100644 --- a/apps/landing/src/app/docs/final/guides/authentication/page.tsx +++ b/apps/landing/src/app/docs/guides/authentication/page.tsx @@ -11,9 +11,9 @@ * - Simplified Next Steps */ -import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal'; -import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal'; -import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal'; +import { DocsLayout } from '@/components/docs/docs/DocsLayout'; +import { DocsSidebar } from '@/components/docs/docs/DocsSidebar'; +import { DocsTOC } from '@/components/docs/docs/DocsTOC'; import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; @@ -32,9 +32,9 @@ const tocItems = [ ]; const navItems = [ - { label: 'Documentation', href: '/docs/final' }, + { label: 'Documentation', href: '/docs' }, { label: 'Demo', href: '/demo' }, - { label: 'Examples', href: '/docs/final/examples' }, + { label: 'Examples', href: '/docs/examples' }, ]; export default function AuthenticationGuidePage() { @@ -43,19 +43,19 @@ export default function AuthenticationGuidePage() { {/* Subsection Navigation */} - } - toc={} + } + toc={} > @@ -330,7 +330,7 @@ curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\ - + ); } diff --git a/apps/landing/src/app/docs/page.tsx b/apps/landing/src/app/docs/page.tsx index b229630..a60b022 100644 --- a/apps/landing/src/app/docs/page.tsx +++ b/apps/landing/src/app/docs/page.tsx @@ -1,376 +1,224 @@ 'use client'; /** - * Documentation Variants Comparison Page + * Getting Started Page - Production Documentation * - * Landing page that introduces users to the three documentation design variants. - * Helps users choose the variant that best suits their preferences. - * - * Three Variants: - * - Variant A: Clean & Minimal (Vercel-inspired) - * - Variant B: Dense & Information-Rich (Next.js docs-inspired) - * - Variant C: Modern & Visual (Shopify-inspired) - * - * Design: - * - Hero section explaining the concept - * - Three large gradient-bordered cards - * - Visual preview descriptions - * - Clear CTAs to each variant + * Main entry point for documentation + * Features: + * - SubsectionNav at top + * - Both TipBox styles (compact + prominent) + * - Enhanced tables + * - Simplified Next Steps (2 cards only) + * - Clean, accessible design */ -export default function DocsIndexPage() { +import { DocsLayout } from '@/components/docs/docs/DocsLayout'; +import { DocsSidebar } from '@/components/docs/docs/DocsSidebar'; +import { DocsTOC } from '@/components/docs/docs/DocsTOC'; +import { SubsectionNav } from '@/components/shared/SubsectionNav'; +import { TipBox } from '@/components/docs/shared/TipBox'; +import { CodeBlock } from '@/components/docs/shared/CodeBlock'; +import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; + +const tocItems = [ + { id: 'introduction', text: 'Introduction', level: 2 }, + { id: 'quick-start', text: 'Quick Start', level: 2 }, + { id: 'installation', text: 'Installation', level: 3 }, + { id: 'authentication', text: 'Authentication', level: 3 }, + { id: 'first-request', text: 'Your First Request', level: 2 }, + { id: 'next-steps', text: 'Next Steps', level: 2 }, +]; + +const navItems = [ + { label: 'Documentation', href: '/docs' }, + { label: 'Demo', href: '/demo' }, + { label: 'Examples', href: '/docs/examples' }, +]; + +export default function GettingStartedPage() { return ( -
- {/* Header with back to home */} -
-
- - - - - Back to Home - -
Choose Your Documentation Style
-
-
+ <> + {/* Subsection Navigation */} + + + } + toc={} + > + -
{/* Hero Section */} -
-
- πŸ“š - DOCUMENTATION -
-

- Choose Your Documentation Style -

-

- We've created three distinct documentation designs. Pick the style that works best for - youβ€”same content, different presentation. -

-
- - {/* Final Variant - Recommended */} - - {/* Other Variants for Reference */} -
-

Other Variants (Reference)

-

- Explore the original variants that inspired the final design +

Getting Started

+

+ Welcome to the Banatie API documentation. Learn how to integrate AI-powered image + generation into your applications in minutes.

- {/* Variant Cards */} -
- {/* Variant A: Clean & Minimal */} - -
✨
-

- Variant A -

-

Clean & Minimal

-

- Vercel-inspired spacious layout with generous whitespace, focused reading experience, - and subtle visual hierarchy. + {/* Introduction */} +

+

Introduction

+

+ Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini + 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into + production-ready visuals. +

+

+ Whether you are building a content creation platform, e-commerce site, or creative tool, + Banatie provides the infrastructure you need to generate high-quality images at scale. +

+ + {/* Compact Tip Box */} + + New to API integration? Start with our{' '} +
+ code examples + {' '} + to see common use cases in action. + +
+ + {/* Quick Start */} +
+

Quick Start

+ +
+

Installation

+

+ Banatie is a REST API, so you do not need to install any libraries. However, we provide + SDKs for popular languages to make integration easier.

-
-
- - - - Wide margins, comfortable reading -
-
- - - - Subtle borders and minimal design -
-
- - - - Focus on content clarity -
-
+ - Explore Variant A - - - -
- +# Using pip (Python) +pip install banatie - {/* Variant B: Dense & Information-Rich */} - -
πŸ“Š
-

- Variant B -

-

Dense & Information-Rich

-

- Next.js docs-inspired compact layout with section numbers, nested navigation, and - maximum information density per screen. +# Using Go +go get github.com/banatie/sdk-go`} + language="bash" + filename="Installation" + /> +

+ +
+

Authentication

+

+ All API requests require an API key. You can create an API key from your dashboard or + using the bootstrap endpoint for initial setup.

-
-
- - - - Compact spacing, more content visible -
-
- - - - Section numbers (1., 2.1, etc.) -
-
- - - - Hierarchical nested tree navigation -
+ {/* Prominent Tip Box for Security Warning */} +
+ + Security Best Practice: Keep your API keys secure. + Never commit them to public repositories or expose them in client-side code. Use environment + variables and server-side implementations for production applications. +
-
- Explore Variant B - - - -
-
+ -
🎨
-

- Variant C -

-

Modern & Visual

-

- Shopify-inspired colorful card-based design with large emoji icons, gradient borders, - and playful engaging visual style. -

+# Save the returned key securely +export BANATIE_API_KEY="bnt_your_key_here"`} + language="bash" + filename="Get API Key" + /> +
+ -
-
- - - - Colorful gradient borders everywhere + {/* First Request */} +
+

Your First Request

+

+ Let's generate your first image! This example uses curl, but you can use any HTTP client + or our SDKs. +

+ + + +
+

Expected Response:

+
+
+ + βœ“ 200 Success +
-
- - - - Large emoji icons and visual elements -
-
- - - - Fun, engaging, playful design -
-
- -
- Explore Variant C - - - -
- -
- - {/* Feature Comparison */} -
-

- All Variants Include -

-
-
-
πŸ“š
-

Same Content

-

- Identical API documentation, just styled differently -

-
-
-
⚑
-

Interactive Widgets

-

- Live API testing with your own keys -

-
-
-
πŸ”
-

Navigation & Search

-

- Sidebar, TOC, and breadcrumb navigation -

+
+                {`{
+  "success": true,
+  "data": {
+    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
+    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
+    "width": 1920,
+    "height": 1080,
+    "promptEnhancement": {
+      "enhancedPrompt": "A breathtaking mountain landscape..."
+    }
+  }
+}`}
+              
-
+
- {/* Footer CTA */} -
-

- Not sure which to choose? Try all three and see which feels right! + {/* Next Steps - Simplified to 2 Cards */} +

+

Next Steps

+

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

-

- Each variant links to the same API contentβ€”pick your preferred reading experience. -

-
-
-
+ + + + + ); } diff --git a/apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx b/apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx deleted file mode 100644 index 61e796c..0000000 --- a/apps/landing/src/app/docs/variant-a/api/text-to-image/page.tsx +++ /dev/null @@ -1,299 +0,0 @@ -'use client'; - -/** - * API Reference: Text to Image - Variant A: Clean & Minimal - * - * This page demonstrates the interactive API reference design with live code execution. - * Features placeholder content and a fully functional API widget. - */ - -import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA'; -import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA'; -import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { InteractiveAPIWidgetA } from '@/components/docs/variant-a/InteractiveAPIWidgetA'; - -const tocItems = [ - { id: 'overview', text: 'Overview', level: 2 }, - { id: 'endpoint', text: 'Endpoint', level: 2 }, - { id: 'request', text: 'Request', level: 2 }, - { id: 'headers', text: 'Headers', level: 3 }, - { id: 'body', text: 'Body Parameters', level: 3 }, - { id: 'response', text: 'Response', level: 2 }, - { id: 'examples', text: 'Examples', level: 2 }, - { id: 'errors', text: 'Error Codes', level: 2 }, -]; - -export default function TextToImageAPIPageA() { - return ( - } - toc={} - > - - - {/* Hero Section */} -
-
- POST -
-

Text to Image

-

- Generate high-quality images from text prompts using AI-powered models. -

-
- - {/* Overview */} -
-

Overview

-

- The Text to Image endpoint generates images from text descriptions. It supports various - aspect ratios, automatic prompt enhancement, and optional reference images for style - matching. -

-
-

- Tip: Enable autoEnhance for better results. The AI will optimize your - prompt for higher quality outputs while preserving your intent. -

-
-
- - {/* Endpoint */} -
-

Endpoint

-
- POST - https://api.banatie.com/api/text-to-image -
-
- - {/* Request */} -
-

Request

- -
-

Headers

-
- - - - - - - - - - - - - - - - - - - - -
HeaderValueRequired
X-API-KeyYour project API key - Yes -
Content-Typeapplication/json - Yes -
-
-
- -
-

Body Parameters

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterTypeDescriptionRequired
promptstringText description of the image to generate - Yes -
filenamestringName for the generated image file - Yes -
aspectRatiostring - Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9 - - No -
autoEnhancebooleanEnable automatic prompt enhancement (default: true) - No -
enhancementOptionsobjectTemplate and enhancement settings - No -
-
-
-
- - {/* Interactive API Widget */} - - - {/* Response */} -
-

Response

-

- Returns a JSON object with the generated image URL and metadata. -

- -
-
-            {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
-    "filepath": "org/project/generated/2025-01/city.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "originalPrompt": "a futuristic city at sunset",
-      "enhancedPrompt": "A breathtaking futuristic cityscape...",
-      "template": "photorealistic"
-    },
-    "generatedAt": "2025-01-15T10:30:00Z"
-  }
-}`}
-          
-
-
- - {/* Examples */} -
-

Examples

- -
-
-

Basic Image Generation

-

Generate a simple image with default settings

-
-
-                {`{
-  "prompt": "a serene mountain landscape",
-  "filename": "mountain"
-}`}
-              
-
-
- -
-

Custom Aspect Ratio

-

Generate a widescreen image

-
-
-                {`{
-  "prompt": "cinematic space battle scene",
-  "filename": "space_battle",
-  "aspectRatio": "21:9"
-}`}
-              
-
-
-
-
- - {/* Error Codes */} -
-

Error Codes

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
CodeDescription
400Invalid request parameters
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
-
-
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx b/apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx deleted file mode 100644 index 535e8bb..0000000 --- a/apps/landing/src/app/docs/variant-a/guides/authentication/page.tsx +++ /dev/null @@ -1,300 +0,0 @@ -'use client'; - -/** - * Guide: Authentication - Variant A: Clean & Minimal - * - * This page demonstrates a guide/tutorial style page with step-by-step instructions. - * Features placeholder content focused on authentication concepts. - */ - -import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA'; -import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA'; -import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'overview', text: 'Overview', level: 2 }, - { id: 'api-keys', text: 'API Keys', level: 2 }, - { id: 'key-types', text: 'Key Types', level: 3 }, - { id: 'creating-keys', text: 'Creating Keys', level: 3 }, - { id: 'using-keys', text: 'Using API Keys', level: 2 }, - { id: 'security', text: 'Security Best Practices', level: 2 }, - { id: 'rate-limits', text: 'Rate Limits', level: 2 }, -]; - -export default function AuthenticationGuidePageA() { - return ( - } - toc={} - > - - - {/* Hero Section */} -
-
- GUIDE -
-

Authentication

-

- Learn how to authenticate your requests and manage API keys securely. -

-
- - {/* Overview */} -
-

Overview

-

- Banatie uses API keys to authenticate requests. Each request must include a valid API key - in the X-API-Key header. API keys are tied to your organization and project, providing - secure, isolated access to resources. -

-
-

- Security First: Never expose your API keys in client-side code, public - repositories, or logs. Treat them like passwords. -

-
-
- - {/* API Keys */} -
-

API Keys

- -
-

Key Types

-

- Banatie provides two types of API keys, each with different permissions and use cases: -

- -
-
-
-
- πŸ”‘ -
-
-

Master Keys

-

- Full administrative access to your organization. Can create and revoke other - keys, access all projects, and manage settings. -

-
    -
  • β€’ Never expire
  • -
  • β€’ Full API access
  • -
  • β€’ One per organization (initially)
  • -
  • β€’ Should be kept extremely secure
  • -
-
-
-
- -
-
-
- 🎫 -
-
-

Project Keys

-

- Scoped to a specific project. Used for image generation and resource access - within that project only. -

-
    -
  • β€’ Expire after 90 days
  • -
  • β€’ Project-specific access
  • -
  • β€’ Rate limited
  • -
  • β€’ Safe for production use
  • -
-
-
-
-
-
- -
-

Creating Keys

- -
-

Bootstrap Your First Key

-

- When setting up Banatie for the first time, create your initial master key using the - bootstrap endpoint: -

- -
-

- Important: This endpoint can only be used once. Save the returned - key immediately - it will never be shown again. -

-
-
- -
-

Create Project Keys

-

- Use your master key to create project-specific keys: -

- -
-
-
- - {/* Using Keys */} -
-

Using API Keys

-

- Include your API key in every request using the X-API-Key header: -

- - -
- - {/* Security */} -
-

Security Best Practices

- -
-
-
πŸ”’
-
-

Never Commit Keys

-

- Use environment variables or secret management tools. Never commit keys to version - control. -

-
-
- -
-
πŸ”„
-
-

Rotate Keys Regularly

-

- Project keys expire after 90 days. Plan for rotation and implement graceful - handling. -

-
-
- -
-
🚫
-
-

Server-Side Only

-

- Never use API keys in client-side code. Always make requests from your backend. -

-
-
- -
-
πŸ‘οΈ
-
-

Monitor Usage

-

- Track API key usage patterns. Unusual activity may indicate a compromised key. -

-
-
-
-
- - {/* Rate Limits */} -
-

Rate Limits

-

- To ensure fair usage and system stability, all API keys are subject to rate limits: -

- -
- - - - - - - - - - - - - - - - - - - - -
Key TypeLimitWindow
Master Key500 requestsper hour
Project Key100 requestsper hour
-
- -
-

- Need Higher Limits? Contact our sales team to discuss enterprise plans - with custom rate limits. -

-
-
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-a/page.tsx b/apps/landing/src/app/docs/variant-a/page.tsx deleted file mode 100644 index 972c2e6..0000000 --- a/apps/landing/src/app/docs/variant-a/page.tsx +++ /dev/null @@ -1,208 +0,0 @@ -'use client'; - -/** - * Getting Started Page - Variant A: Clean & Minimal - * - * This is the main landing page for the documentation. - * Features placeholder content to demonstrate the layout and design. - */ - -import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA'; -import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA'; -import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'introduction', text: 'Introduction', level: 2 }, - { id: 'quick-start', text: 'Quick Start', level: 2 }, - { id: 'installation', text: 'Installation', level: 3 }, - { id: 'authentication', text: 'Authentication', level: 3 }, - { id: 'first-request', text: 'Your First Request', level: 2 }, - { id: 'next-steps', text: 'Next Steps', level: 2 }, -]; - -export default function GettingStartedPageA() { - return ( - } - toc={} - > - - - {/* Hero Section */} -
-

Getting Started

-

- Welcome to the Banatie API documentation. Learn how to integrate AI-powered image - generation into your applications in minutes. -

-
- - {/* Introduction */} -
-

Introduction

-

- Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini - 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into - production-ready visuals. -

-

- Whether you're building a content creation platform, e-commerce site, or creative tool, - Banatie provides the infrastructure you need to generate high-quality images at scale. -

-
- - {/* Quick Start */} -
-

Quick Start

- -
-

Installation

-

- Banatie is a REST API, so you don't need to install any libraries. However, we provide - SDKs for popular languages to make integration easier. -

- - -
- -
-

Authentication

-

- All API requests require an API key. You can create an API key from your dashboard or - using the bootstrap endpoint for initial setup. -

- -
-

- Note: Keep your API keys secure. Never commit them to public - repositories or expose them in client-side code. -

-
- - -
-
- - {/* First Request */} -
-

Your First Request

-

- Let's generate your first image! This example uses curl, but you can use any HTTP client - or our SDKs. -

- - - -
-

Response:

-
-            {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
-    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "enhancedPrompt": "A breathtaking mountain landscape..."
-    }
-  }
-}`}
-          
-
-
- - {/* Next Steps */} -
-

Next Steps

- - -
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx b/apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx deleted file mode 100644 index 3c830bd..0000000 --- a/apps/landing/src/app/docs/variant-b/api/text-to-image/page.tsx +++ /dev/null @@ -1,304 +0,0 @@ -'use client'; - -/** - * API Reference: Text to Image - Variant B: Dense & Information-Rich - * - * Design Philosophy: Compact, information-dense layout with section numbers - * - * Key Differences from Variant A: - * - Section numbers in all headings (1., 1.1, 1.2, etc.) - * - More compact spacing (mb-6 vs mb-12, p-3 vs p-4) - * - Smaller text sizes throughout - * - Denser tables and narrower content - */ - -import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB'; -import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB'; -import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { InteractiveAPIWidgetB } from '@/components/docs/variant-b/InteractiveAPIWidgetB'; - -const tocItems = [ - { id: 'overview', text: '1. Overview', level: 2 }, - { id: 'endpoint', text: '2. Endpoint', level: 2 }, - { id: 'request', text: '3. Request', level: 2 }, - { id: 'headers', text: '3.1 Headers', level: 3 }, - { id: 'body', text: '3.2 Body Parameters', level: 3 }, - { id: 'response', text: '4. Response', level: 2 }, - { id: 'examples', text: '5. Examples', level: 2 }, - { id: 'errors', text: '6. Error Codes', level: 2 }, -]; - -export default function TextToImageAPIPageB() { - return ( - } - toc={} - > - - - {/* Hero Section - More compact */} -
-
- POST -
-

Text to Image

-

- Generate high-quality images from text prompts using AI-powered models. -

-
- - {/* Overview */} -
-

1. Overview

-

- The Text to Image endpoint generates images from text descriptions. It supports various - aspect ratios, automatic prompt enhancement, and optional reference images for style - matching. -

-
-

- Tip: Enable autoEnhance for better results. The AI will optimize your - prompt for higher quality outputs while preserving your intent. -

-
-
- - {/* Endpoint */} -
-

2. Endpoint

-
- POST - https://api.banatie.com/api/text-to-image -
-
- - {/* Request */} -
-

3. Request

- -
-

3.1 Headers

-
- - - - - - - - - - - - - - - - - - - - -
HeaderValueRequired
X-API-KeyYour project API key - Yes -
Content-Typeapplication/json - Yes -
-
-
- -
-

3.2 Body Parameters

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterTypeDescriptionRequired
promptstringText description of the image to generate - Yes -
filenamestringName for the generated image file - Yes -
aspectRatiostring - Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9 - - No -
autoEnhancebooleanEnable automatic prompt enhancement (default: true) - No -
enhancementOptionsobjectTemplate and enhancement settings - No -
-
-
-
- - {/* Interactive API Widget */} - - - {/* Response */} -
-

4. Response

-

- Returns a JSON object with the generated image URL and metadata. -

- -
-
-            {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
-    "filepath": "org/project/generated/2025-01/city.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "originalPrompt": "a futuristic city at sunset",
-      "enhancedPrompt": "A breathtaking futuristic cityscape...",
-      "template": "photorealistic"
-    },
-    "generatedAt": "2025-01-15T10:30:00Z"
-  }
-}`}
-          
-
-
- - {/* Examples */} -
-

5. Examples

- -
-
-

5.1 Basic Image Generation

-

Generate a simple image with default settings

-
-
-                {`{
-  "prompt": "a serene mountain landscape",
-  "filename": "mountain"
-}`}
-              
-
-
- -
-

5.2 Custom Aspect Ratio

-

Generate a widescreen image

-
-
-                {`{
-  "prompt": "cinematic space battle scene",
-  "filename": "space_battle",
-  "aspectRatio": "21:9"
-}`}
-              
-
-
-
-
- - {/* Error Codes */} -
-

6. Error Codes

-
- - - - - - - - - - - - - - - - - - - - - - - - - -
CodeDescription
400Invalid request parameters
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
-
-
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx b/apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx deleted file mode 100644 index a4b8ffb..0000000 --- a/apps/landing/src/app/docs/variant-b/guides/authentication/page.tsx +++ /dev/null @@ -1,305 +0,0 @@ -'use client'; - -/** - * Guide: Authentication - Variant B: Dense & Information-Rich - * - * Design Philosophy: Compact, information-dense layout with section numbers - * - * Key Differences from Variant A: - * - Section numbers in all headings (1., 2., 2.1, etc.) - * - More compact spacing (mb-6 vs mb-12, p-3 vs p-4) - * - Smaller text sizes throughout (text-xs, text-sm) - * - Denser layout with narrower content area - */ - -import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB'; -import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB'; -import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'overview', text: '1. Overview', level: 2 }, - { id: 'api-keys', text: '2. API Keys', level: 2 }, - { id: 'key-types', text: '2.1 Key Types', level: 3 }, - { id: 'creating-keys', text: '2.2 Creating Keys', level: 3 }, - { id: 'using-keys', text: '3. Using API Keys', level: 2 }, - { id: 'security', text: '4. Security Best Practices', level: 2 }, - { id: 'rate-limits', text: '5. Rate Limits', level: 2 }, -]; - -export default function AuthenticationGuidePageB() { - return ( - } - toc={} - > - - - {/* Hero Section - More compact */} -
-
- GUIDE -
-

Authentication

-

- Learn how to authenticate your requests and manage API keys securely. -

-
- - {/* Overview */} -
-

1. Overview

-

- Banatie uses API keys to authenticate requests. Each request must include a valid API key - in the X-API-Key header. API keys are tied to your organization and project, providing - secure, isolated access to resources. -

-
-

- Security First: Never expose your API keys in client-side code, public - repositories, or logs. Treat them like passwords. -

-
-
- - {/* API Keys */} -
-

2. API Keys

- -
-

2.1 Key Types

-

- Banatie provides two types of API keys, each with different permissions and use cases: -

- -
-
-
-
- πŸ”‘ -
-
-

Master Keys

-

- Full administrative access to your organization. Can create and revoke other - keys, access all projects, and manage settings. -

-
    -
  • β€’ Never expire
  • -
  • β€’ Full API access
  • -
  • β€’ One per organization (initially)
  • -
  • β€’ Should be kept extremely secure
  • -
-
-
-
- -
-
-
- 🎫 -
-
-

Project Keys

-

- Scoped to a specific project. Used for image generation and resource access - within that project only. -

-
    -
  • β€’ Expire after 90 days
  • -
  • β€’ Project-specific access
  • -
  • β€’ Rate limited
  • -
  • β€’ Safe for production use
  • -
-
-
-
-
-
- -
-

2.2 Creating Keys

- -
-

2.2.1 Bootstrap Your First Key

-

- When setting up Banatie for the first time, create your initial master key using the - bootstrap endpoint: -

- -
-

- Important: This endpoint can only be used once. Save the returned - key immediately - it will never be shown again. -

-
-
- -
-

2.2.2 Create Project Keys

-

- Use your master key to create project-specific keys: -

- -
-
-
- - {/* Using Keys */} -
-

3. Using API Keys

-

- Include your API key in every request using the X-API-Key header: -

- - -
- - {/* Security */} -
-

4. Security Best Practices

- -
-
-
πŸ”’
-
-

Never Commit Keys

-

- Use environment variables or secret management tools. Never commit keys to version - control. -

-
-
- -
-
πŸ”„
-
-

Rotate Keys Regularly

-

- Project keys expire after 90 days. Plan for rotation and implement graceful - handling. -

-
-
- -
-
🚫
-
-

Server-Side Only

-

- Never use API keys in client-side code. Always make requests from your backend. -

-
-
- -
-
πŸ‘οΈ
-
-

Monitor Usage

-

- Track API key usage patterns. Unusual activity may indicate a compromised key. -

-
-
-
-
- - {/* Rate Limits */} -
-

5. Rate Limits

-

- To ensure fair usage and system stability, all API keys are subject to rate limits: -

- -
- - - - - - - - - - - - - - - - - - - - -
Key TypeLimitWindow
Master Key500 requestsper hour
Project Key100 requestsper hour
-
- -
-

- Need Higher Limits? Contact our sales team to discuss enterprise plans - with custom rate limits. -

-
-
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-b/page.tsx b/apps/landing/src/app/docs/variant-b/page.tsx deleted file mode 100644 index c8320e6..0000000 --- a/apps/landing/src/app/docs/variant-b/page.tsx +++ /dev/null @@ -1,211 +0,0 @@ -'use client'; - -/** - * Getting Started Page - Variant B: Dense & Information-Rich - * - * Same content as Variant A but with Variant B styling: - * - Compact spacing (py-10 vs py-12, p-4 vs p-6) - * - Narrower max-width (max-w-4xl) - * - Section numbers in headings where appropriate - * - Denser tables and lists - */ - -import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB'; -import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB'; -import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'introduction', text: '1. Introduction', level: 2 }, - { id: 'quick-start', text: '2. Quick Start', level: 2 }, - { id: 'installation', text: '2.1 Installation', level: 3 }, - { id: 'authentication', text: '2.2 Authentication', level: 3 }, - { id: 'first-request', text: '3. Your First Request', level: 2 }, - { id: 'next-steps', text: '4. Next Steps', level: 2 }, -]; - -export default function GettingStartedPageB() { - return ( - } - toc={} - > - - - {/* Hero Section - More compact */} -
-

Getting Started

-

- Welcome to the Banatie API documentation. Learn how to integrate AI-powered image - generation into your applications in minutes. -

-
- - {/* Introduction */} -
-

1. Introduction

-

- Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini - 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into - production-ready visuals. -

-

- Whether you're building a content creation platform, e-commerce site, or creative tool, - Banatie provides the infrastructure you need to generate high-quality images at scale. -

-
- - {/* Quick Start */} -
-

2. Quick Start

- -
-

2.1 Installation

-

- Banatie is a REST API, so you don't need to install any libraries. However, we provide - SDKs for popular languages to make integration easier. -

- - -
- -
-

2.2 Authentication

-

- All API requests require an API key. You can create an API key from your dashboard or - using the bootstrap endpoint for initial setup. -

- -
-

- Note: Keep your API keys secure. Never commit them to public - repositories or expose them in client-side code. -

-
- - -
-
- - {/* First Request */} -
-

3. Your First Request

-

- Let's generate your first image! This example uses curl, but you can use any HTTP client - or our SDKs. -

- - - -
-

Response:

-
-            {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
-    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "enhancedPrompt": "A breathtaking mountain landscape..."
-    }
-  }
-}`}
-          
-
-
- - {/* Next Steps */} -
-

4. Next Steps

- - -
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx b/apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx deleted file mode 100644 index 83665b8..0000000 --- a/apps/landing/src/app/docs/variant-c/api/text-to-image/page.tsx +++ /dev/null @@ -1,369 +0,0 @@ -'use client'; - -/** - * API Reference: Text to Image - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Colorful, card-based, engaging visual design - * - * Key Characteristics: - * - NO section numbers (more visual/playful) - * - Large emoji icons (text-3xl) - * - Gradient borders everywhere - * - Colorful method badge (large, gradient) - * - Visual cards for parameter tables - * - Generous spacing (mb-12, p-6) - */ - -import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC'; -import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC'; -import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { InteractiveAPIWidgetC } from '@/components/docs/variant-c/InteractiveAPIWidgetC'; - -const tocItems = [ - { id: 'overview', text: 'Overview', level: 2 }, - { id: 'endpoint', text: 'Endpoint', level: 2 }, - { id: 'request', text: 'Request', level: 2 }, - { id: 'headers', text: 'Headers', level: 3 }, - { id: 'body', text: 'Body Parameters', level: 3 }, - { id: 'response', text: 'Response', level: 2 }, - { id: 'examples', text: 'Examples', level: 2 }, - { id: 'errors', text: 'Error Codes', level: 2 }, -]; - -export default function TextToImageAPIPageC() { - return ( - } - toc={} - > - - - {/* Hero Section - Large and Colorful */} -
-
- POST -
-

- Text to Image -

-

- Generate high-quality images from text prompts using AI-powered models. -

-
- - {/* Overview */} -
-
- πŸ“– -

Overview

-
-
-

- The Text to Image endpoint generates images from text descriptions. It supports various - aspect ratios, automatic prompt enhancement, and optional reference images for style - matching. -

-
-
- πŸ’‘ -
-

Pro Tip

-

- Enable autoEnhance for better results. The AI will optimize your prompt for higher - quality outputs while preserving your intent. -

-
-
-
-
-
- - {/* Endpoint */} -
-
- πŸ”— -

Endpoint

-
-
-
- - POST - - https://api.banatie.com/api/text-to-image -
-
-
- - {/* Request */} -
-
- πŸ“€ -

Request

-
- -
-
- 🏷️ -

Headers

-
-
- - - - - - - - - - - - - - - - - - - - -
HeaderValueRequired
X-API-KeyYour project API key - - Required - -
Content-Typeapplication/json - - Required - -
-
-
- -
-
- βš™οΈ -

Body Parameters

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterTypeDescriptionRequired
promptstringText description of the image to generate - - Required - -
filenamestringName for the generated image file - - Required - -
aspectRatiostring - Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9 - - - Optional - -
autoEnhancebooleanEnable automatic prompt enhancement (default: true) - - Optional - -
enhancementOptionsobjectTemplate and enhancement settings - - Optional - -
-
-
-
- - {/* Interactive API Widget */} - - - {/* Response */} -
-
- πŸ“¦ -

Response

-
-

- Returns a JSON object with the generated image URL and metadata. -

- -
-
- - βœ“ 200 Success - -
-
-            {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
-    "filepath": "org/project/generated/2025-01/city.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "originalPrompt": "a futuristic city at sunset",
-      "enhancedPrompt": "A breathtaking futuristic cityscape...",
-      "template": "photorealistic"
-    },
-    "generatedAt": "2025-01-15T10:30:00Z"
-  }
-}`}
-          
-
-
- - {/* Examples */} -
-
- πŸ’‘ -

Examples

-
- -
-
-
- 🎨 -

Basic Image Generation

-
-

Generate a simple image with default settings

-
-
-                {`{
-  "prompt": "a serene mountain landscape",
-  "filename": "mountain"
-}`}
-              
-
-
- -
-
- 🎬 -

Custom Aspect Ratio

-
-

Generate a widescreen image

-
-
-                {`{
-  "prompt": "cinematic space battle scene",
-  "filename": "space_battle",
-  "aspectRatio": "21:9"
-}`}
-              
-
-
-
-
- - {/* Error Codes */} -
-
- ⚠️ -

Error Codes

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
CodeDescription
400Invalid request parameters
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
-
-
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx b/apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx deleted file mode 100644 index 1e9b3ef..0000000 --- a/apps/landing/src/app/docs/variant-c/guides/authentication/page.tsx +++ /dev/null @@ -1,370 +0,0 @@ -'use client'; - -/** - * Guide: Authentication - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Colorful, card-based, playful visual design - * - * Key Characteristics: - * - NO section numbers (more visual/playful) - * - Security best practices as large visual cards - * - Emoji icons prominent (text-3xl) - * - Gradient borders everywhere - * - Generous spacing and padding - */ - -import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC'; -import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC'; -import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'overview', text: 'Overview', level: 2 }, - { id: 'api-keys', text: 'API Keys', level: 2 }, - { id: 'key-types', text: 'Key Types', level: 3 }, - { id: 'creating-keys', text: 'Creating Keys', level: 3 }, - { id: 'using-keys', text: 'Using API Keys', level: 2 }, - { id: 'security', text: 'Security Best Practices', level: 2 }, - { id: 'rate-limits', text: 'Rate Limits', level: 2 }, -]; - -export default function AuthenticationGuidePageC() { - return ( - } - toc={} - > - - - {/* Hero Section - Large and Colorful */} -
-
- πŸ“š - GUIDE -
-

- Authentication -

-

- Learn how to authenticate your requests and manage API keys securely. -

-
- - {/* Overview */} -
-
- πŸ” -

Overview

-
-
-

- Banatie uses API keys to authenticate requests. Each request must include a valid API key - in the X-API-Key header. API keys are tied to your organization and project, providing - secure, isolated access to resources. -

-
-
- πŸ›‘οΈ -
-

Security First

-

- Never expose your API keys in client-side code, public repositories, or logs. Treat - them like passwords. -

-
-
-
-
-
- - {/* API Keys */} -
-
- πŸ”‘ -

API Keys

-
- -
-
- 🏷️ -

Key Types

-
-

- Banatie provides two types of API keys, each with different permissions and use cases: -

- -
-
-
-
- πŸ”‘ -
-
-

Master Keys

-

- Full administrative access to your organization. Can create and revoke other - keys, access all projects, and manage settings. -

-
    -
  • - βœ“ Never expire -
  • -
  • - βœ“ Full API access -
  • -
  • - βœ“ One per organization (initially) -
  • -
  • - βœ“ Should be kept extremely secure -
  • -
-
-
-
- -
-
-
- 🎫 -
-
-

Project Keys

-

- Scoped to a specific project. Used for image generation and resource access - within that project only. -

-
    -
  • - βœ“ Expire after 90 days -
  • -
  • - βœ“ Project-specific access -
  • -
  • - βœ“ Rate limited -
  • -
  • - βœ“ Safe for production use -
  • -
-
-
-
-
-
- -
-
- ⚑ -

Creating Keys

-
- -
-
- πŸš€ -

Bootstrap Your First Key

-
-

- When setting up Banatie for the first time, create your initial master key using the - bootstrap endpoint: -

- -
-
- ⚠️ -
-

Important

-

- This endpoint can only be used once. Save the returned key immediately - it will - never be shown again. -

-
-
-
-
- -
-
- 🎨 -

Create Project Keys

-
-

- Use your master key to create project-specific keys: -

- -
-
-
- - {/* Using Keys */} -
-
- πŸ’» -

Using API Keys

-
-

- Include your API key in every request using the X-API-Key header: -

- - -
- - {/* Security */} -
-
- πŸ›‘οΈ -

Security Best Practices

-
- -
-
-
πŸ”’
-

Never Commit Keys

-

- Use environment variables or secret management tools. Never commit keys to version - control. -

-
- -
-
πŸ”„
-

Rotate Keys Regularly

-

- Project keys expire after 90 days. Plan for rotation and implement graceful handling. -

-
- -
-
🚫
-

Server-Side Only

-

- Never use API keys in client-side code. Always make requests from your backend. -

-
- -
-
πŸ‘οΈ
-

Monitor Usage

-

- Track API key usage patterns. Unusual activity may indicate a compromised key. -

-
-
-
- - {/* Rate Limits */} -
-
- ⏱️ -

Rate Limits

-
-

- To ensure fair usage and system stability, all API keys are subject to rate limits: -

- -
- - - - - - - - - - - - - - - - - - - - -
Key TypeLimitWindow
Master Key - - 500 requests - - per hour
Project Key - - 100 requests - - per hour
-
- -
-
- πŸ’¬ -
-

Need Higher Limits?

-

- Contact our sales team to discuss enterprise plans with custom rate limits. -

-
-
-
-
-
- ); -} diff --git a/apps/landing/src/app/docs/variant-c/page.tsx b/apps/landing/src/app/docs/variant-c/page.tsx deleted file mode 100644 index b80157e..0000000 --- a/apps/landing/src/app/docs/variant-c/page.tsx +++ /dev/null @@ -1,268 +0,0 @@ -'use client'; - -/** - * Getting Started Page - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Colorful, card-based, playful visual design - * - * Key Characteristics: - * - NO section numbers (more visual/playful) - * - Large emoji icons throughout (text-3xl) - * - Gradient borders on all callout boxes - * - More colorful design (purple/cyan/amber accents) - * - Generous spacing (mb-12, p-6) - * - Larger padding and gaps throughout - * - Card-based sections with shadows - * - Floating visual effects - */ - -import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC'; -import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC'; -import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; -import { CodeBlock } from '@/components/docs/shared/CodeBlock'; - -const tocItems = [ - { id: 'introduction', text: 'Introduction', level: 2 }, - { id: 'quick-start', text: 'Quick Start', level: 2 }, - { id: 'installation', text: 'Installation', level: 3 }, - { id: 'authentication', text: 'Authentication', level: 3 }, - { id: 'first-request', text: 'Your First Request', level: 2 }, - { id: 'next-steps', text: 'Next Steps', level: 2 }, -]; - -export default function GettingStartedPageC() { - return ( - } - toc={} - > - - - {/* Hero Section - Large and Colorful */} -
-
- πŸš€ - START HERE -
-

- Getting Started -

-

- Welcome to the Banatie API documentation. Learn how to integrate AI-powered image - generation into your applications in minutes. -

-
- - {/* Introduction */} -
-
- πŸ‘‹ -

Introduction

-
-
-

- Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini - 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into - production-ready visuals. -

-

- Whether you're building a content creation platform, e-commerce site, or creative tool, - Banatie provides the infrastructure you need to generate high-quality images at scale. -

-
-
- - {/* Quick Start */} -
-
- ⚑ -

Quick Start

-
- -
-
- πŸ“¦ -

Installation

-
-

- Banatie is a REST API, so you don't need to install any libraries. However, we provide - SDKs for popular languages to make integration easier. -

- - -
- -
-
- πŸ”‘ -

Authentication

-
-

- All API requests require an API key. You can create an API key from your dashboard or - using the bootstrap endpoint for initial setup. -

- -
-
- πŸ’‘ -
-

Security Tip

-

- Keep your API keys secure. Never commit them to public repositories or expose them - in client-side code. -

-
-
-
- - -
-
- - {/* First Request */} -
-
- 🎨 -

Your First Request

-
-

- Let's generate your first image! This example uses curl, but you can use any HTTP client - or our SDKs. -

- - - -
-
- ✨ -

Expected Response:

-
-
-            {`{
-  "success": true,
-  "data": {
-    "url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
-    "filepath": "org/project/generated/2025-01/mountain_sunset.png",
-    "width": 1920,
-    "height": 1080,
-    "promptEnhancement": {
-      "enhancedPrompt": "A breathtaking mountain landscape..."
-    }
-  }
-}`}
-          
-
-
- - {/* Next Steps */} -
-
- 🎯 -

Next Steps

-
- - -
- - {/* Fun CTA Card */} -
-
πŸŽ‰
-

Ready to Build Something Amazing?

-

- Start creating stunning AI-generated images for your applications today! -

- - ⚑ - Explore the API - -
-
- ); -} diff --git a/apps/landing/src/components/docs/final/DocsLayoutFinal.tsx b/apps/landing/src/components/docs/docs/DocsLayout.tsx similarity index 92% rename from apps/landing/src/components/docs/final/DocsLayoutFinal.tsx rename to apps/landing/src/components/docs/docs/DocsLayout.tsx index db66cc7..10bde15 100644 --- a/apps/landing/src/components/docs/final/DocsLayoutFinal.tsx +++ b/apps/landing/src/components/docs/docs/DocsLayout.tsx @@ -1,7 +1,7 @@ 'use client'; /** - * Documentation Layout - Final Variant + * Documentation Layout - Production Version * * Based on Variant A: Clean & Minimal with enhancements * This is the production-ready version combining the best aspects @@ -26,13 +26,13 @@ import { ReactNode } from 'react'; -interface DocsLayoutFinalProps { +interface DocsLayoutProps { sidebar: ReactNode; children: ReactNode; toc: ReactNode; } -export const DocsLayoutFinal = ({ sidebar, children, toc }: DocsLayoutFinalProps) => { +export const DocsLayout = ({ sidebar, children, toc }: DocsLayoutProps) => { return (
{/* Animated gradient background (matching landing page) */} diff --git a/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx b/apps/landing/src/components/docs/docs/DocsSidebar.tsx similarity index 84% rename from apps/landing/src/components/docs/final/DocsSidebarFinal.tsx rename to apps/landing/src/components/docs/docs/DocsSidebar.tsx index 7c4e60c..b5e6d6a 100644 --- a/apps/landing/src/components/docs/final/DocsSidebarFinal.tsx +++ b/apps/landing/src/components/docs/docs/DocsSidebar.tsx @@ -1,7 +1,7 @@ 'use client'; /** - * Documentation Sidebar - Final Variant + * Documentation Sidebar - Production Version * * Based on Variant A with FIXED active states * @@ -33,44 +33,44 @@ interface NavItem { children?: NavItem[]; } -interface DocsSidebarFinalProps { +interface DocsSidebarProps { currentPath: string; } const navigationItems: NavItem[] = [ { label: 'Getting Started', - href: '/docs/final', + href: '/docs', icon: 'πŸš€', }, { label: 'API Reference', - href: '/docs/final/api', + href: '/docs/api', icon: 'πŸ“š', children: [ - { label: 'Text to Image', href: '/docs/final/api/text-to-image' }, - { label: 'Upload', href: '/docs/final/api/upload' }, - { label: 'Images', href: '/docs/final/api/images' }, + { label: 'Text to Image', href: '/docs/api/text-to-image' }, + { label: 'Upload', href: '/docs/api/upload' }, + { label: 'Images', href: '/docs/api/images' }, ], }, { label: 'Guides', - href: '/docs/final/guides', + href: '/docs/guides', icon: 'πŸ“–', children: [ - { label: 'Authentication', href: '/docs/final/guides/authentication' }, - { label: 'Error Handling', href: '/docs/final/guides/error-handling' }, - { label: 'Rate Limits', href: '/docs/final/guides/rate-limits' }, + { label: 'Authentication', href: '/docs/guides/authentication' }, + { label: 'Error Handling', href: '/docs/guides/error-handling' }, + { label: 'Rate Limits', href: '/docs/guides/rate-limits' }, ], }, { label: 'Examples', - href: '/docs/final/examples', + href: '/docs/examples', icon: 'πŸ’‘', }, ]; -export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => { +export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => { const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); const toggleSection = (label: string) => { @@ -87,7 +87,7 @@ export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => { {/* Logo/Title */}

Documentation

-

Final: Production

+

API Reference

{/* Navigation Items */} @@ -170,8 +170,8 @@ export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => {
diff --git a/apps/landing/src/components/docs/final/DocsTOCFinal.tsx b/apps/landing/src/components/docs/docs/DocsTOC.tsx similarity index 95% rename from apps/landing/src/components/docs/final/DocsTOCFinal.tsx rename to apps/landing/src/components/docs/docs/DocsTOC.tsx index 0a25277..5b0ca3d 100644 --- a/apps/landing/src/components/docs/final/DocsTOCFinal.tsx +++ b/apps/landing/src/components/docs/docs/DocsTOC.tsx @@ -1,7 +1,7 @@ 'use client'; /** - * Table of Contents - Final Variant + * Table of Contents - Production Version * * Based on Variant A: Clean & Minimal (no changes needed) * @@ -26,11 +26,11 @@ interface TocItem { level: number; } -interface DocsTOCFinalProps { +interface DocsTOCProps { items: TocItem[]; } -export const DocsTOCFinal = ({ items }: DocsTOCFinalProps) => { +export const DocsTOC = ({ items }: DocsTOCProps) => { const [activeId, setActiveId] = useState(''); useEffect(() => { diff --git a/apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx b/apps/landing/src/components/docs/docs/InteractiveAPIWidget.tsx similarity index 98% rename from apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx rename to apps/landing/src/components/docs/docs/InteractiveAPIWidget.tsx index a146cb6..8b91a4d 100644 --- a/apps/landing/src/components/docs/final/InteractiveAPIWidgetFinal.tsx +++ b/apps/landing/src/components/docs/docs/InteractiveAPIWidget.tsx @@ -1,9 +1,9 @@ 'use client'; /** - * Interactive API Widget - Final Variant (Redesigned) + * Interactive API Widget - Production Version * - * Minimized layout inspired by Variant C with Final variant design system: + * Minimized layout with clean design system: * - No inline API key input (uses DocsApiKeyInput component) * - Clean header with method badge, endpoint, and expand button * - Full-width code snippet area @@ -13,7 +13,7 @@ import { useState, useEffect } from 'react'; -interface InteractiveAPIWidgetFinalProps { +interface InteractiveAPIWidgetProps { endpoint: string; method: 'GET' | 'POST' | 'PUT' | 'DELETE'; description: string; @@ -46,12 +46,12 @@ const getMethodBadgeStyle = (method: string): string => { } }; -export const InteractiveAPIWidgetFinal = ({ +export const InteractiveAPIWidget = ({ endpoint, method, description, parameters = [], -}: InteractiveAPIWidgetFinalProps) => { +}: InteractiveAPIWidgetProps) => { const [language, setLanguage] = useState('curl'); const [apiKey, setApiKey] = useState(''); const [isExecuting, setIsExecuting] = useState(false); diff --git a/apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx b/apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx deleted file mode 100644 index 66f33e5..0000000 --- a/apps/landing/src/components/docs/variant-a/DocsLayoutA.tsx +++ /dev/null @@ -1,62 +0,0 @@ -'use client'; - -/** - * Documentation Layout - Variant A: Clean & Minimal - * - * Design Philosophy: Vercel-inspired spacious, focused reading experience - * - * Layout Structure: - * - Left Sidebar: Thin (256px) with minimal design - * - Content Area: Wide margins (max-w-3xl) for comfortable reading - * - Right TOC: Subtle and unobtrusive (224px) - * - * Responsive Behavior: - * - Mobile (<768px): Single column, sidebars become overlays - * - Tablet (768px-1024px): Content + TOC only - * - Desktop (>1024px): Full three-column layout - * - * Design Characteristics: - * - Generous whitespace - * - Subtle borders and shadows - * - Focus on content clarity - * - Minimal visual noise - */ - -import { ReactNode } from 'react'; - -interface DocsLayoutAProps { - sidebar: ReactNode; - children: ReactNode; - toc: ReactNode; -} - -export const DocsLayoutA = ({ sidebar, children, toc }: DocsLayoutAProps) => { - return ( -
- {/* Animated gradient background (matching landing page) */} -
-
-
-
- -
- {/* Left Sidebar - Thin, minimal design */} - - - {/* Main Content Area - Wide margins for comfortable reading */} -
-
- {children} -
-
- - {/* Right TOC - Subtle and unobtrusive */} - -
-
- ); -}; diff --git a/apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx b/apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx deleted file mode 100644 index 34bb8d4..0000000 --- a/apps/landing/src/components/docs/variant-a/DocsSidebarA.tsx +++ /dev/null @@ -1,178 +0,0 @@ -'use client'; - -/** - * Documentation Sidebar - Variant A: Clean & Minimal - * - * Design Philosophy: Vercel-inspired minimal navigation - * - * Features: - * - Thin sidebar with subtle hover states - * - Collapsible section groups - * - Active state: Purple left border + text - * - Minimal icons (chevron for expandable items) - * - Clean, uncluttered appearance - * - * Navigation Structure: - * - Getting Started - * - API Reference (collapsible) - * - Text to Image - * - Upload - * - Images - * - Guides (collapsible) - * - Authentication - * - Error Handling - * - Rate Limits - * - Examples - */ - -import { useState } from 'react'; - -interface NavItem { - label: string; - href: string; - icon?: string; - children?: NavItem[]; -} - -interface DocsSidebarAProps { - currentPath: string; -} - -const navigationItems: NavItem[] = [ - { - label: 'Getting Started', - href: '/docs/variant-a', - icon: 'πŸš€', - }, - { - label: 'API Reference', - href: '/docs/variant-a/api', - icon: 'πŸ“š', - children: [ - { label: 'Text to Image', href: '/docs/variant-a/api/text-to-image' }, - { label: 'Upload', href: '/docs/variant-a/api/upload' }, - { label: 'Images', href: '/docs/variant-a/api/images' }, - ], - }, - { - label: 'Guides', - href: '/docs/variant-a/guides', - icon: 'πŸ“–', - children: [ - { label: 'Authentication', href: '/docs/variant-a/guides/authentication' }, - { label: 'Error Handling', href: '/docs/variant-a/guides/error-handling' }, - { label: 'Rate Limits', href: '/docs/variant-a/guides/rate-limits' }, - ], - }, - { - label: 'Examples', - href: '/docs/variant-a/examples', - icon: 'πŸ’‘', - }, -]; - -export const DocsSidebarA = ({ currentPath }: DocsSidebarAProps) => { - const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); - - const toggleSection = (label: string) => { - setExpandedSections((prev) => - prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] - ); - }; - - const isActive = (href: string) => currentPath === href; - const isExpanded = (label: string) => expandedSections.includes(label); - - return ( - - ); -}; diff --git a/apps/landing/src/components/docs/variant-a/DocsTOCA.tsx b/apps/landing/src/components/docs/variant-a/DocsTOCA.tsx deleted file mode 100644 index 330edf9..0000000 --- a/apps/landing/src/components/docs/variant-a/DocsTOCA.tsx +++ /dev/null @@ -1,102 +0,0 @@ -'use client'; - -/** - * Table of Contents - Variant A: Clean & Minimal - * - * Design Philosophy: Subtle, unobtrusive TOC - * - * Features: - * - Small indicator dots for section levels - * - Smooth scroll to section - * - Active section highlighting (purple text) - * - Sticky positioning - * - Minimal visual weight - * - * Behavior: - * - Extracts H2 and H3 headings from content - * - Tracks scroll position to highlight active section - * - Click to smooth scroll to section - */ - -import { useEffect, useState } from 'react'; - -interface TocItem { - id: string; - text: string; - level: number; -} - -interface DocsTOCAProps { - items: TocItem[]; -} - -export const DocsTOCA = ({ items }: DocsTOCAProps) => { - const [activeId, setActiveId] = useState(''); - - useEffect(() => { - const observer = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - setActiveId(entry.target.id); - } - }); - }, - { rootMargin: '-20% 0px -35% 0px' } - ); - - items.forEach((item) => { - const element = document.getElementById(item.id); - if (element) observer.observe(element); - }); - - return () => observer.disconnect(); - }, [items]); - - const scrollToSection = (id: string) => { - const element = document.getElementById(id); - if (element) { - element.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } - }; - - if (items.length === 0) { - return null; - } - - return ( - - ); -}; diff --git a/apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx b/apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx deleted file mode 100644 index a1d443a..0000000 --- a/apps/landing/src/components/docs/variant-a/InteractiveAPIWidgetA.tsx +++ /dev/null @@ -1,293 +0,0 @@ -'use client'; - -/** - * Interactive API Widget - Variant A: Clean & Minimal - * - * Design Philosophy: Inline playground with tabbed interface - * - * Features: - * - Multi-language code tabs (curl, JavaScript, Python, Go) - * - API key input field (persists via localStorage) - * - "Try It" button to execute live requests - * - Response viewer with syntax highlighting - * - Request/Response tabs - * - Error state handling - * - Clean, focused design - * - * Layout: - * - Top: Language tabs + Copy button - * - Middle: Code preview OR Request params - * - Bottom: Try It button - * - Response: Expandable section below - */ - -import { useState, useEffect } from 'react'; - -interface InteractiveAPIWidgetAProps { - endpoint: string; - method: 'GET' | 'POST' | 'PUT' | 'DELETE'; - description: string; - parameters?: Array<{ - name: string; - type: string; - required: boolean; - description: string; - defaultValue?: string; - }>; -} - -type Language = 'curl' | 'javascript' | 'python' | 'go'; -type ViewMode = 'code' | 'response'; - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; -const API_KEY_STORAGE = 'banatie_docs_api_key'; - -export const InteractiveAPIWidgetA = ({ - endpoint, - method, - description, - parameters = [], -}: InteractiveAPIWidgetAProps) => { - const [language, setLanguage] = useState('curl'); - const [apiKey, setApiKey] = useState(''); - const [isExecuting, setIsExecuting] = useState(false); - const [viewMode, setViewMode] = useState('code'); - const [response, setResponse] = useState(null); - const [error, setError] = useState(null); - - // Parameter values - const [paramValues, setParamValues] = useState>({}); - - // Load API key from localStorage - useEffect(() => { - const stored = localStorage.getItem(API_KEY_STORAGE); - if (stored) setApiKey(stored); - - // Initialize parameter default values - const defaults: Record = {}; - parameters.forEach((param) => { - if (param.defaultValue) { - defaults[param.name] = param.defaultValue; - } - }); - setParamValues(defaults); - }, [parameters]); - - // Save API key to localStorage - const handleApiKeyChange = (value: string) => { - setApiKey(value); - if (value) { - localStorage.setItem(API_KEY_STORAGE, value); - } else { - localStorage.removeItem(API_KEY_STORAGE); - } - }; - - // Generate code examples - const generateCode = (): string => { - const url = `${API_BASE_URL}${endpoint}`; - - switch (language) { - case 'curl': - return `curl -X ${method} "${url}" \\ - -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "prompt": "a futuristic city at sunset", - "filename": "city", - "aspectRatio": "16:9" - }'`; - - case 'javascript': - return `const response = await fetch('${url}', { - method: '${method}', - headers: { - 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - prompt: 'a futuristic city at sunset', - filename: 'city', - aspectRatio: '16:9' - }) -}); - -const data = await response.json(); -console.log(data);`; - - case 'python': - return `import requests - -url = '${url}' -headers = { - 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', - 'Content-Type': 'application/json' -} -data = { - 'prompt': 'a futuristic city at sunset', - 'filename': 'city', - 'aspectRatio': '16:9' -} - -response = requests.${method.toLowerCase()}(url, headers=headers, json=data) -print(response.json())`; - - case 'go': - return `package main - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" -) - -func main() { - url := "${url}" - data := map[string]interface{}{ - "prompt": "a futuristic city at sunset", - "filename": "city", - "aspectRatio": "16:9", - } - - jsonData, _ := json.Marshal(data) - req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) - req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - resp, _ := client.Do(req) - defer resp.Body.Close() -}`; - - default: - return ''; - } - }; - - // Execute API request - const executeRequest = async () => { - if (!apiKey) { - setError('Please enter your API key'); - return; - } - - setIsExecuting(true); - setError(null); - setViewMode('response'); - - try { - const body: Record = {}; - parameters.forEach((param) => { - if (paramValues[param.name]) { - body[param.name] = paramValues[param.name]; - } - }); - - const res = await fetch(`${API_BASE_URL}${endpoint}`, { - method, - headers: { - 'X-API-Key': apiKey, - 'Content-Type': 'application/json', - }, - body: method !== 'GET' ? JSON.stringify(body) : undefined, - }); - - const data = await res.json(); - setResponse(data); - } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to execute request'); - } finally { - setIsExecuting(false); - } - }; - - // Copy code to clipboard - const copyCode = () => { - navigator.clipboard.writeText(generateCode()); - }; - - return ( -
- {/* Header with API Key Input */} -
-
-
-

Try it out

-

{description}

-
-
- handleApiKeyChange(e.target.value)} - placeholder="Enter your API key" - className="w-full px-3 py-2 text-xs bg-slate-800 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" - /> -
-
-
- - {/* Language Tabs */} -
-
- {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => ( - - ))} -
- -
- - {/* Code Display */} -
-
-          {generateCode()}
-        
-
- - {/* Try It Button */} -
- -
- - {/* Response Section */} - {(response || error) && ( -
-
-

Response

- {error ? ( -
- {error} -
- ) : ( -
-                {JSON.stringify(response, null, 2)}
-              
- )} -
-
- )} -
- ); -}; diff --git a/apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx b/apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx deleted file mode 100644 index c019a9e..0000000 --- a/apps/landing/src/components/docs/variant-b/DocsLayoutB.tsx +++ /dev/null @@ -1,62 +0,0 @@ -'use client'; - -/** - * Documentation Layout - Variant B: Dense & Information-Rich - * - * Design Philosophy: Next.js-inspired dense, hierarchical layout - * - * Layout Structure: - * - Left Sidebar: Wider (280px) with nested tree structure - * - Content Area: Narrower margins to show more content - * - Right TOC: Prominent with progress indicator (240px) - * - * Responsive Behavior: - * - Mobile (<768px): Bottom sheet navigation - * - Tablet (768px-1024px): Collapsible sidebar + TOC - * - Desktop (>1024px): Full three-column layout - * - * Design Characteristics: - * - Compact spacing - * - More content per screen - * - Nested navigation tree - * - Section numbers throughout - */ - -import { ReactNode } from 'react'; - -interface DocsLayoutBProps { - sidebar: ReactNode; - children: ReactNode; - toc: ReactNode; -} - -export const DocsLayoutB = ({ sidebar, children, toc }: DocsLayoutBProps) => { - return ( -
- {/* Animated gradient background (matching landing page) */} -
-
-
-
- -
- {/* Left Sidebar - Wider with nested structure */} - - - {/* Main Content Area - Narrower margins for more content */} -
-
- {children} -
-
- - {/* Right TOC - Prominent with progress */} - -
-
- ); -}; diff --git a/apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx b/apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx deleted file mode 100644 index 8f55dcf..0000000 --- a/apps/landing/src/components/docs/variant-b/DocsSidebarB.tsx +++ /dev/null @@ -1,205 +0,0 @@ -'use client'; - -/** - * Documentation Sidebar - Variant B: Dense & Information-Rich - * - * Design Philosophy: Next.js-inspired nested tree structure - * - * Features: - * - Wider sidebar with deep nesting - * - Section numbers for all items - * - Compact spacing (more items visible) - * - Indent levels for hierarchy - * - Active state: Purple background + bold - * - Expand/collapse all button - * - * Navigation Structure with numbers: - * 1. Getting Started - * 2. API Reference - * 2.1 Text to Image - * 2.2 Upload - * 2.3 Images - * 3. Guides - * 3.1 Authentication - * 3.2 Error Handling - * 3.3 Rate Limits - * 4. Examples - */ - -import { useState } from 'react'; - -interface NavItem { - label: string; - href: string; - number?: string; - children?: NavItem[]; -} - -interface DocsSidebarBProps { - currentPath: string; -} - -const navigationItems: NavItem[] = [ - { - label: 'Getting Started', - href: '/docs/variant-b', - number: '1', - }, - { - label: 'API Reference', - href: '/docs/variant-b/api', - number: '2', - children: [ - { label: 'Text to Image', href: '/docs/variant-b/api/text-to-image', number: '2.1' }, - { label: 'Upload', href: '/docs/variant-b/api/upload', number: '2.2' }, - { label: 'Images', href: '/docs/variant-b/api/images', number: '2.3' }, - ], - }, - { - label: 'Guides', - href: '/docs/variant-b/guides', - number: '3', - children: [ - { label: 'Authentication', href: '/docs/variant-b/guides/authentication', number: '3.1' }, - { label: 'Error Handling', href: '/docs/variant-b/guides/error-handling', number: '3.2' }, - { label: 'Rate Limits', href: '/docs/variant-b/guides/rate-limits', number: '3.3' }, - ], - }, - { - label: 'Examples', - href: '/docs/variant-b/examples', - number: '4', - }, -]; - -export const DocsSidebarB = ({ currentPath }: DocsSidebarBProps) => { - const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); - - const toggleSection = (label: string) => { - setExpandedSections((prev) => - prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] - ); - }; - - const isActive = (href: string) => currentPath === href; - const isExpanded = (label: string) => expandedSections.includes(label); - - return ( - - ); -}; diff --git a/apps/landing/src/components/docs/variant-b/DocsTOCB.tsx b/apps/landing/src/components/docs/variant-b/DocsTOCB.tsx deleted file mode 100644 index 4d6c274..0000000 --- a/apps/landing/src/components/docs/variant-b/DocsTOCB.tsx +++ /dev/null @@ -1,141 +0,0 @@ -'use client'; - -/** - * Table of Contents - Variant B: Dense & Information-Rich - * - * Design Philosophy: Prominent TOC with progress indicator - * - * Features: - * - Section numbers matching content - * - Progress bar showing read percentage - * - Larger, more prominent design - * - Active section with purple highlight - * - Sticky positioning with scroll progress - * - * Behavior: - * - Extracts H2 and H3 headings with numbers - * - Shows reading progress percentage - * - Click to smooth scroll to section - * - Visual progress bar - */ - -import { useEffect, useState } from 'react'; - -interface TocItem { - id: string; - text: string; - level: number; -} - -interface DocsTOCBProps { - items: TocItem[]; -} - -export const DocsTOCB = ({ items }: DocsTOCBProps) => { - const [activeId, setActiveId] = useState(''); - const [scrollProgress, setScrollProgress] = useState(0); - - useEffect(() => { - const observer = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - setActiveId(entry.target.id); - } - }); - }, - { rootMargin: '-20% 0px -35% 0px' } - ); - - items.forEach((item) => { - const element = document.getElementById(item.id); - if (element) observer.observe(element); - }); - - // Track scroll progress - const handleScroll = () => { - const windowHeight = window.innerHeight; - const documentHeight = document.documentElement.scrollHeight; - const scrollTop = window.scrollY; - const progress = (scrollTop / (documentHeight - windowHeight)) * 100; - setScrollProgress(Math.min(progress, 100)); - }; - - window.addEventListener('scroll', handleScroll); - - return () => { - observer.disconnect(); - window.removeEventListener('scroll', handleScroll); - }; - }, [items]); - - const scrollToSection = (id: string) => { - const element = document.getElementById(id); - if (element) { - element.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } - }; - - if (items.length === 0) { - return null; - } - - return ( - - ); -}; diff --git a/apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx b/apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx deleted file mode 100644 index 21c543d..0000000 --- a/apps/landing/src/components/docs/variant-b/InteractiveAPIWidgetB.tsx +++ /dev/null @@ -1,291 +0,0 @@ -'use client'; - -/** - * Interactive API Widget - Variant B: Dense & Information-Rich - * - * Design Philosophy: Side-by-side code editor with persistent API key bar - * - * Features: - * - Persistent API key bar at the top of page (sticky) - * - Side-by-side code and response layout - * - Multi-language tabs (curl, JavaScript, Python, Go) - * - Live request execution - * - Compact, information-dense design - * - Parameter form on the left - * - Response on the right - * - * Layout: - * - Top: Sticky API key bar (global for page) - * - Left: Code + Parameters - * - Right: Response viewer - * - Bottom: Try It button - */ - -import { useState, useEffect } from 'react'; - -interface InteractiveAPIWidgetBProps { - endpoint: string; - method: 'GET' | 'POST' | 'PUT' | 'DELETE'; - description: string; - parameters?: Array<{ - name: string; - type: string; - required: boolean; - description: string; - defaultValue?: string; - }>; -} - -type Language = 'curl' | 'javascript' | 'python' | 'go'; - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; -const API_KEY_STORAGE = 'banatie_docs_api_key'; - -export const InteractiveAPIWidgetB = ({ - endpoint, - method, - description, - parameters = [], -}: InteractiveAPIWidgetBProps) => { - const [language, setLanguage] = useState('curl'); - const [apiKey, setApiKey] = useState(''); - const [isExecuting, setIsExecuting] = useState(false); - const [response, setResponse] = useState(null); - const [error, setError] = useState(null); - const [paramValues, setParamValues] = useState>({}); - - // Load API key from localStorage - useEffect(() => { - const stored = localStorage.getItem(API_KEY_STORAGE); - if (stored) setApiKey(stored); - - // Initialize parameter default values - const defaults: Record = {}; - parameters.forEach((param) => { - if (param.defaultValue) { - defaults[param.name] = param.defaultValue; - } - }); - setParamValues(defaults); - }, [parameters]); - - // Save API key to localStorage - const handleApiKeyChange = (value: string) => { - setApiKey(value); - if (value) { - localStorage.setItem(API_KEY_STORAGE, value); - } else { - localStorage.removeItem(API_KEY_STORAGE); - } - }; - - // Generate code examples - const generateCode = (): string => { - const url = `${API_BASE_URL}${endpoint}`; - - switch (language) { - case 'curl': - return `curl -X ${method} "${url}" \\ - -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "prompt": "a futuristic city at sunset", - "filename": "city", - "aspectRatio": "16:9" - }'`; - - case 'javascript': - return `const response = await fetch('${url}', { - method: '${method}', - headers: { - 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - prompt: 'a futuristic city at sunset', - filename: 'city', - aspectRatio: '16:9' - }) -}); - -const data = await response.json();`; - - case 'python': - return `import requests - -url = '${url}' -headers = { - 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', - 'Content-Type': 'application/json' -} -data = { - 'prompt': 'a futuristic city at sunset', - 'filename': 'city', - 'aspectRatio': '16:9' -} - -response = requests.${method.toLowerCase()}(url, headers=headers, json=data)`; - - case 'go': - return `package main - -import ( - "bytes" - "encoding/json" - "net/http" -) - -func main() { - url := "${url}" - data := map[string]interface{}{ - "prompt": "a futuristic city at sunset", - "filename": "city", - "aspectRatio": "16:9", - } - - jsonData, _ := json.Marshal(data) - req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) - req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - resp, _ := client.Do(req) -}`; - - default: - return ''; - } - }; - - // Execute API request - const executeRequest = async () => { - if (!apiKey) { - setError('Please enter your API key in the bar above'); - return; - } - - setIsExecuting(true); - setError(null); - - try { - const body: Record = {}; - parameters.forEach((param) => { - if (paramValues[param.name]) { - body[param.name] = paramValues[param.name]; - } - }); - - const res = await fetch(`${API_BASE_URL}${endpoint}`, { - method, - headers: { - 'X-API-Key': apiKey, - 'Content-Type': 'application/json', - }, - body: method !== 'GET' ? JSON.stringify(body) : undefined, - }); - - const data = await res.json(); - setResponse(data); - } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to execute request'); - } finally { - setIsExecuting(false); - } - }; - - // Copy code to clipboard - const copyCode = () => { - navigator.clipboard.writeText(generateCode()); - }; - - return ( -
- {/* API Key Bar - Persistent at top */} -
-
- - handleApiKeyChange(e.target.value)} - placeholder="Enter your API key (persists across examples)" - className="flex-1 px-3 py-1.5 text-xs bg-slate-800 border border-slate-700 rounded text-white placeholder-gray-600 focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-transparent" - /> - - {apiKey ? 'βœ“ Set' : 'Not set'} - -
-
- - {/* Main Widget - Two Column Layout */} -
- {/* Left Column: Code */} -
- {/* Language Tabs */} -
-
- {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => ( - - ))} -
- -
- - {/* Code Display */} -
-
-              {generateCode()}
-            
-
-
- - {/* Right Column: Response */} -
-
-

Response

-
- -
- {error ? ( -
- {error} -
- ) : response ? ( -
-                {JSON.stringify(response, null, 2)}
-              
- ) : ( -

- Click "Execute Request" to see the response -

- )} -
-
-
- - {/* Try It Button - Full Width */} - - -

{description}

-
- ); -}; diff --git a/apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx b/apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx deleted file mode 100644 index 435ee90..0000000 --- a/apps/landing/src/components/docs/variant-c/DocsLayoutC.tsx +++ /dev/null @@ -1,74 +0,0 @@ -'use client'; - -/** - * Documentation Layout - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Colorful, card-based, engaging visual layout - * - * Layout Structure: - * - Left Sidebar: Wide (320px) with large card-style navigation - * - Content Area: Generous padding (p-12) with wide max-width (max-w-5xl) - * - Right TOC: Floating card with gradient borders (280px) - * - * Design Characteristics: - * - Colorful gradient borders everywhere (purple/cyan) - * - Card-based design with shadows - * - Large, generous spacing (p-6, gap-6, mb-12) - * - Playful and engaging visual style - * - NO section numbers (more visual/intuitive) - * - Large emoji icons throughout - * - Floating shadow effects - * - * Responsive Behavior: - * - Mobile (<768px): Single column, cards stack - * - Tablet (768px-1024px): Content + floating TOC - * - Desktop (>1024px): Full three-column card layout - * - * Color Palette: - * - Purple gradients: from-purple-500/30 to-purple-600/20 - * - Cyan gradients: from-cyan-500/30 to-cyan-600/20 - * - Amber accents: amber-500, amber-600 - * - Background: slate-950, slate-900 - * - Borders: purple-500/40, cyan-500/40, slate-700 - * - Shadows: shadow-lg shadow-purple-500/20 - */ - -import { ReactNode } from 'react'; - -interface DocsLayoutCProps { - sidebar: ReactNode; - children: ReactNode; - toc: ReactNode; -} - -export const DocsLayoutC = ({ sidebar, children, toc }: DocsLayoutCProps) => { - return ( -
- {/* Animated gradient background - More colorful */} -
-
-
-
-
- -
- {/* Left Sidebar - Wide with card-style navigation */} - - - {/* Main Content Area - Wide with generous padding */} -
-
- {children} -
-
- - {/* Right TOC - Floating card with gradient border */} - -
-
- ); -}; diff --git a/apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx b/apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx deleted file mode 100644 index 7b96844..0000000 --- a/apps/landing/src/components/docs/variant-c/DocsSidebarC.tsx +++ /dev/null @@ -1,238 +0,0 @@ -'use client'; - -/** - * Documentation Sidebar - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Card-based navigation with large colorful visual elements - * - * Features: - * - Navigation items as large gradient-bordered cards - * - Large emoji icons (text-2xl) for visual hierarchy - * - Alternating purple/cyan gradient accents - * - Generous spacing (gap-4, p-4 per item) - * - Touch-friendly minimum heights (min-h-12) - * - NO section numbers (more playful/intuitive) - * - Hover effects with shadow and scale - * - Active state with prominent gradient background - * - * Navigation Structure (NO numbers): - * - πŸš€ Getting Started - * - πŸ“š API Reference - * - 🎨 Text to Image - * - πŸ“€ Upload - * - πŸ–ΌοΈ Images - * - πŸ” Guides - * - πŸ”‘ Authentication - * - ⚠️ Error Handling - * - ⏱️ Rate Limits - * - πŸ’‘ Examples - * - * Color Palette: - * - Purple: from-purple-500/30 to-purple-600/20 - * - Cyan: from-cyan-500/30 to-cyan-600/20 - * - Active: bg-gradient-to-br from-purple-500/30 to-cyan-500/30 - * - Hover: shadow-lg shadow-purple-500/20, scale-102 - */ - -import { useState } from 'react'; - -interface NavItem { - label: string; - href: string; - icon: string; - color: 'purple' | 'cyan' | 'amber'; - children?: NavItem[]; -} - -interface DocsSidebarCProps { - currentPath: string; -} - -const navigationItems: NavItem[] = [ - { - label: 'Getting Started', - href: '/docs/variant-c', - icon: 'πŸš€', - color: 'purple', - }, - { - label: 'API Reference', - href: '/docs/variant-c/api', - icon: 'πŸ“š', - color: 'cyan', - children: [ - { label: 'Text to Image', href: '/docs/variant-c/api/text-to-image', icon: '🎨', color: 'purple' }, - { label: 'Upload', href: '/docs/variant-c/api/upload', icon: 'πŸ“€', color: 'cyan' }, - { label: 'Images', href: '/docs/variant-c/api/images', icon: 'πŸ–ΌοΈ', color: 'purple' }, - ], - }, - { - label: 'Guides', - href: '/docs/variant-c/guides', - icon: 'πŸ”', - color: 'purple', - children: [ - { label: 'Authentication', href: '/docs/variant-c/guides/authentication', icon: 'πŸ”‘', color: 'cyan' }, - { label: 'Error Handling', href: '/docs/variant-c/guides/error-handling', icon: '⚠️', color: 'purple' }, - { label: 'Rate Limits', href: '/docs/variant-c/guides/rate-limits', icon: '⏱️', color: 'cyan' }, - ], - }, - { - label: 'Examples', - href: '/docs/variant-c/examples', - icon: 'πŸ’‘', - color: 'amber', - }, -]; - -const getGradientClasses = (color: 'purple' | 'cyan' | 'amber', active: boolean) => { - if (active) { - return 'bg-gradient-to-br from-purple-500/30 to-cyan-500/30 border-purple-500/60 shadow-lg shadow-purple-500/30'; - } - - const baseClasses = 'border-2 hover:shadow-lg transition-all duration-300 hover:scale-[1.02]'; - - switch (color) { - case 'purple': - return `${baseClasses} border-purple-500/30 hover:border-purple-500/50 hover:shadow-purple-500/20 hover:bg-purple-500/10`; - case 'cyan': - return `${baseClasses} border-cyan-500/30 hover:border-cyan-500/50 hover:shadow-cyan-500/20 hover:bg-cyan-500/10`; - case 'amber': - return `${baseClasses} border-amber-500/30 hover:border-amber-500/50 hover:shadow-amber-500/20 hover:bg-amber-500/10`; - default: - return baseClasses; - } -}; - -export const DocsSidebarC = ({ currentPath }: DocsSidebarCProps) => { - const [expandedSections, setExpandedSections] = useState(['API Reference', 'Guides']); - - const toggleSection = (label: string) => { - setExpandedSections((prev) => - prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label] - ); - }; - - const isActive = (href: string) => currentPath === href; - const isExpanded = (label: string) => expandedSections.includes(label); - - return ( - - ); -}; diff --git a/apps/landing/src/components/docs/variant-c/DocsTOCC.tsx b/apps/landing/src/components/docs/variant-c/DocsTOCC.tsx deleted file mode 100644 index d23f756..0000000 --- a/apps/landing/src/components/docs/variant-c/DocsTOCC.tsx +++ /dev/null @@ -1,212 +0,0 @@ -'use client'; - -/** - * Table of Contents - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Floating card with colorful visual indicators - * - * Features: - * - Wrapped in large gradient-bordered card - * - Colorful dot indicators (alternating purple/cyan/amber) - * - Large text sizes (text-base for items) - * - Generous spacing (p-6, gap-4) - * - Floating shadow effect with colored glow - * - NO section numbers (more visual/playful) - * - Active state with gradient background - * - Smooth hover animations with scale - * - Fun, engaging design with emoji header - * - * Visual Elements: - * - Large colored dots instead of numbers - * - Gradient progress bar with rainbow colors - * - Active item with gradient highlight - * - Hover effects with shadow and scale - * - * Behavior: - * - Extracts H2 and H3 headings (no numbers) - * - Shows reading progress with colorful bar - * - Click to smooth scroll to section - * - Visual feedback with animations - */ - -import { useEffect, useState } from 'react'; - -interface TocItem { - id: string; - text: string; - level: number; -} - -interface DocsTOCCProps { - items: TocItem[]; -} - -const getColorForIndex = (index: number): string => { - const colors = ['purple', 'cyan', 'amber']; - return colors[index % colors.length]; -}; - -const getDotClasses = (color: string, isActive: boolean): string => { - const baseClasses = 'w-2.5 h-2.5 rounded-full flex-shrink-0 transition-all duration-300'; - - if (isActive) { - return `${baseClasses} shadow-lg ${ - color === 'purple' - ? 'bg-purple-500 shadow-purple-500/50' - : color === 'cyan' - ? 'bg-cyan-500 shadow-cyan-500/50' - : 'bg-amber-500 shadow-amber-500/50' - }`; - } - - return `${baseClasses} ${ - color === 'purple' - ? 'bg-purple-500/40' - : color === 'cyan' - ? 'bg-cyan-500/40' - : 'bg-amber-500/40' - }`; -}; - -export const DocsTOCC = ({ items }: DocsTOCCProps) => { - const [activeId, setActiveId] = useState(''); - const [scrollProgress, setScrollProgress] = useState(0); - - useEffect(() => { - const observer = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - setActiveId(entry.target.id); - } - }); - }, - { rootMargin: '-20% 0px -35% 0px' } - ); - - items.forEach((item) => { - const element = document.getElementById(item.id); - if (element) observer.observe(element); - }); - - const handleScroll = () => { - const windowHeight = window.innerHeight; - const documentHeight = document.documentElement.scrollHeight; - const scrollTop = window.scrollY; - const progress = (scrollTop / (documentHeight - windowHeight)) * 100; - setScrollProgress(Math.min(progress, 100)); - }; - - window.addEventListener('scroll', handleScroll); - - return () => { - observer.disconnect(); - window.removeEventListener('scroll', handleScroll); - }; - }, [items]); - - const scrollToSection = (id: string) => { - const element = document.getElementById(id); - if (element) { - element.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } - }; - - if (items.length === 0) { - return null; - } - - return ( - - ); -}; diff --git a/apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx b/apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx deleted file mode 100644 index c2c6ad9..0000000 --- a/apps/landing/src/components/docs/variant-c/InteractiveAPIWidgetC.tsx +++ /dev/null @@ -1,393 +0,0 @@ -'use client'; - -/** - * Interactive API Widget - Variant C: Modern & Visual (Shopify-inspired) - * - * Design Philosophy: Floating, expandable card with colorful visual feedback - * - * Features: - * - Full-screen expandable mode toggle button - * - Large gradient-bordered card with shadow glow - * - Prominent "Test Now ⚑" button (larger, more visual) - * - Response in colorful gradient-bordered card - * - Success/error states with vibrant colored badges - * - More visual feedback and animations - * - Large emoji icons throughout - * - Colorful code syntax highlighting hints - * - Floating shadow effects - * - * Layout: - * - Top: Large colorful API key input card - * - Main: Expandable code editor with rainbow gradient border - * - Language tabs as colorful pills - * - Large prominent "Test Now" button with gradient - * - Response card with colored status indicators - * - * Visual Elements: - * - Purple/cyan/amber gradients everywhere - * - Large shadows with colored glows - * - Scale and hover animations - * - Success: Green gradient with glow - * - Error: Red gradient with glow - */ - -import { useState, useEffect } from 'react'; - -interface InteractiveAPIWidgetCProps { - endpoint: string; - method: 'GET' | 'POST' | 'PUT' | 'DELETE'; - description: string; - parameters?: Array<{ - name: string; - type: string; - required: boolean; - description: string; - defaultValue?: string; - }>; -} - -type Language = 'curl' | 'javascript' | 'python' | 'go'; - -const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; -const API_KEY_STORAGE = 'banatie_docs_api_key'; - -const getMethodColor = (method: string): string => { - switch (method) { - case 'GET': - return 'from-cyan-500 to-cyan-600'; - case 'POST': - return 'from-purple-500 to-purple-600'; - case 'PUT': - return 'from-amber-500 to-amber-600'; - case 'DELETE': - return 'from-red-500 to-red-600'; - default: - return 'from-purple-500 to-cyan-500'; - } -}; - -export const InteractiveAPIWidgetC = ({ - endpoint, - method, - description, - parameters = [], -}: InteractiveAPIWidgetCProps) => { - const [language, setLanguage] = useState('curl'); - const [apiKey, setApiKey] = useState(''); - const [isExecuting, setIsExecuting] = useState(false); - const [response, setResponse] = useState(null); - const [error, setError] = useState(null); - const [paramValues, setParamValues] = useState>({}); - const [isExpanded, setIsExpanded] = useState(false); - - useEffect(() => { - const stored = localStorage.getItem(API_KEY_STORAGE); - if (stored) setApiKey(stored); - - const defaults: Record = {}; - parameters.forEach((param) => { - if (param.defaultValue) { - defaults[param.name] = param.defaultValue; - } - }); - setParamValues(defaults); - }, [parameters]); - - const handleApiKeyChange = (value: string) => { - setApiKey(value); - if (value) { - localStorage.setItem(API_KEY_STORAGE, value); - } else { - localStorage.removeItem(API_KEY_STORAGE); - } - }; - - const generateCode = (): string => { - const url = `${API_BASE_URL}${endpoint}`; - - switch (language) { - case 'curl': - return `curl -X ${method} "${url}" \\ - -H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\ - -H "Content-Type: application/json" \\ - -d '{ - "prompt": "a futuristic city at sunset", - "filename": "city", - "aspectRatio": "16:9" - }'`; - - case 'javascript': - return `const response = await fetch('${url}', { - method: '${method}', - headers: { - 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - prompt: 'a futuristic city at sunset', - filename: 'city', - aspectRatio: '16:9' - }) -}); - -const data = await response.json();`; - - case 'python': - return `import requests - -url = '${url}' -headers = { - 'X-API-Key': '${apiKey || 'YOUR_API_KEY'}', - 'Content-Type': 'application/json' -} -data = { - 'prompt': 'a futuristic city at sunset', - 'filename': 'city', - 'aspectRatio': '16:9' -} - -response = requests.${method.toLowerCase()}(url, headers=headers, json=data)`; - - case 'go': - return `package main - -import ( - "bytes" - "encoding/json" - "net/http" -) - -func main() { - url := "${url}" - data := map[string]interface{}{ - "prompt": "a futuristic city at sunset", - "filename": "city", - "aspectRatio": "16:9", - } - - jsonData, _ := json.Marshal(data) - req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData)) - req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}") - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - resp, _ := client.Do(req) -}`; - - default: - return ''; - } - }; - - const executeRequest = async () => { - if (!apiKey) { - setError('Please enter your API key above ✨'); - return; - } - - setIsExecuting(true); - setError(null); - - try { - const body: Record = {}; - parameters.forEach((param) => { - if (paramValues[param.name]) { - body[param.name] = paramValues[param.name]; - } - }); - - const res = await fetch(`${API_BASE_URL}${endpoint}`, { - method, - headers: { - 'X-API-Key': apiKey, - 'Content-Type': 'application/json', - }, - body: method !== 'GET' ? JSON.stringify(body) : undefined, - }); - - const data = await res.json(); - setResponse(data); - } catch (err) { - setError(err instanceof Error ? err.message : 'Failed to execute request πŸ˜”'); - } finally { - setIsExecuting(false); - } - }; - - const copyCode = () => { - navigator.clipboard.writeText(generateCode()); - }; - - return ( -
- {/* API Key Card - Large and Colorful */} -
-
- πŸ”‘ - -
-
- handleApiKeyChange(e.target.value)} - placeholder="Enter your API key (saved locally)" - className="flex-1 px-4 py-3 text-sm bg-slate-900/80 border-2 border-purple-500/30 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500/50 transition-all" - /> -
- {apiKey ? 'βœ“ Ready' : '⚠️ Required'} -
-
-
- - {/* Main Widget Card - Large Gradient Border */} -
- {/* Header with Expand Button */} -
-
-
- {method} -
- {endpoint} -
- -
- -
- {/* Left: Code Editor */} -
- {/* Language Tabs - Colorful Pills */} -
- {(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => { - const colors = ['purple', 'cyan', 'amber', 'purple']; - const color = colors[idx]; - return ( - - ); - })} -
- - {/* Code Display - Gradient Border */} -
-
- Code Example - -
-
-
-                  {generateCode()}
-                
-
-
-
- - {/* Right: Response */} -
-

- πŸ“¦ - Response -

- -
-
- {response && ( - - {response.success ? 'βœ“ Success' : 'βœ• Error'} - - )} -
-
- {error ? ( -
-
- ⚠️ -
-

Error

-

{error}

-
-
-
- ) : response ? ( -
-                    {JSON.stringify(response, null, 2)}
-                  
- ) : ( -
-
-

πŸš€

-

- Click "Test Now" below to see the response -

-
-
- )} -
-
-
-
- - {/* Large Test Now Button */} -
- -

{description}

-
-
-
- ); -}; From 94c8aafe5bd6cedbf01c636ec664a97bb0bd3dc8 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Fri, 17 Oct 2025 23:33:57 +0700 Subject: [PATCH 07/11] chore: sort components folders --- apps/landing/package.json | 3 ++- apps/landing/src/app/docs/api/text-to-image/page.tsx | 8 ++++---- apps/landing/src/app/docs/guides/authentication/page.tsx | 6 +++--- apps/landing/src/app/docs/page.tsx | 6 +++--- .../docs/{docs => blocks}/InteractiveAPIWidget.tsx | 0 .../src/components/docs/{docs => layout}/DocsLayout.tsx | 0 .../src/components/docs/{docs => layout}/DocsSidebar.tsx | 0 .../src/components/docs/{docs => layout}/DocsTOC.tsx | 0 8 files changed, 12 insertions(+), 11 deletions(-) rename apps/landing/src/components/docs/{docs => blocks}/InteractiveAPIWidget.tsx (100%) rename apps/landing/src/components/docs/{docs => layout}/DocsLayout.tsx (100%) rename apps/landing/src/components/docs/{docs => layout}/DocsSidebar.tsx (100%) rename apps/landing/src/components/docs/{docs => layout}/DocsTOC.tsx (100%) diff --git a/apps/landing/package.json b/apps/landing/package.json index 3188c77..0f92f17 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -6,7 +6,8 @@ "dev": "next dev -p 3010", "build": "next build", "start": "next start", - "deploy": "cp -r out/* /var/www/banatie.app/" + "deploy": "cp -r out/* /var/www/banatie.app/", + "typecheck": "tsc --noEmit" }, "dependencies": { "react": "19.1.0", 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 b62fb1b..0e2ab7b 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 @@ -11,15 +11,15 @@ * - Simplified Next Steps */ -import { DocsLayout } from '@/components/docs/docs/DocsLayout'; -import { DocsSidebar } from '@/components/docs/docs/DocsSidebar'; -import { DocsTOC } from '@/components/docs/docs/DocsTOC'; +import { DocsLayout } from '@/components/docs/layout/DocsLayout'; +import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; +import { DocsTOC } from '@/components/docs/layout/DocsTOC'; import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; -import { InteractiveAPIWidget } from '@/components/docs/docs/InteractiveAPIWidget'; import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; +import { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget'; const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, diff --git a/apps/landing/src/app/docs/guides/authentication/page.tsx b/apps/landing/src/app/docs/guides/authentication/page.tsx index 68c685f..648cfa9 100644 --- a/apps/landing/src/app/docs/guides/authentication/page.tsx +++ b/apps/landing/src/app/docs/guides/authentication/page.tsx @@ -11,9 +11,9 @@ * - Simplified Next Steps */ -import { DocsLayout } from '@/components/docs/docs/DocsLayout'; -import { DocsSidebar } from '@/components/docs/docs/DocsSidebar'; -import { DocsTOC } from '@/components/docs/docs/DocsTOC'; +import { DocsLayout } from '@/components/docs/layout/DocsLayout'; +import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; +import { DocsTOC } from '@/components/docs/layout/DocsTOC'; import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; diff --git a/apps/landing/src/app/docs/page.tsx b/apps/landing/src/app/docs/page.tsx index a60b022..f9aa7df 100644 --- a/apps/landing/src/app/docs/page.tsx +++ b/apps/landing/src/app/docs/page.tsx @@ -12,9 +12,9 @@ * - Clean, accessible design */ -import { DocsLayout } from '@/components/docs/docs/DocsLayout'; -import { DocsSidebar } from '@/components/docs/docs/DocsSidebar'; -import { DocsTOC } from '@/components/docs/docs/DocsTOC'; +import { DocsLayout } from '@/components/docs/layout/DocsLayout'; +import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; +import { DocsTOC } from '@/components/docs/layout/DocsTOC'; import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; diff --git a/apps/landing/src/components/docs/docs/InteractiveAPIWidget.tsx b/apps/landing/src/components/docs/blocks/InteractiveAPIWidget.tsx similarity index 100% rename from apps/landing/src/components/docs/docs/InteractiveAPIWidget.tsx rename to apps/landing/src/components/docs/blocks/InteractiveAPIWidget.tsx diff --git a/apps/landing/src/components/docs/docs/DocsLayout.tsx b/apps/landing/src/components/docs/layout/DocsLayout.tsx similarity index 100% rename from apps/landing/src/components/docs/docs/DocsLayout.tsx rename to apps/landing/src/components/docs/layout/DocsLayout.tsx diff --git a/apps/landing/src/components/docs/docs/DocsSidebar.tsx b/apps/landing/src/components/docs/layout/DocsSidebar.tsx similarity index 100% rename from apps/landing/src/components/docs/docs/DocsSidebar.tsx rename to apps/landing/src/components/docs/layout/DocsSidebar.tsx diff --git a/apps/landing/src/components/docs/docs/DocsTOC.tsx b/apps/landing/src/components/docs/layout/DocsTOC.tsx similarity index 100% rename from apps/landing/src/components/docs/docs/DocsTOC.tsx rename to apps/landing/src/components/docs/layout/DocsTOC.tsx From 813e0b186cc15161baaa2562412effd39c0139e1 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Sat, 18 Oct 2025 01:14:41 +0700 Subject: [PATCH 08/11] feat: extract components --- .../src/app/docs/api/text-to-image/page.tsx | 125 ++++---- .../app/docs/guides/authentication/page.tsx | 109 +++---- apps/landing/src/app/docs/page.tsx | 104 ++++--- .../components/docs/blocks/EndpointCard.tsx | 202 +++++++++++++ .../src/components/docs/blocks/Hero.tsx | 185 ++++++++++++ .../src/components/docs/blocks/InlineCode.tsx | 156 ++++++++++ .../src/components/docs/blocks/LinkCard.tsx | 281 ++++++++++++++++++ .../components/docs/blocks/LinkCardGrid.tsx | 216 ++++++++++++++ .../components/docs/blocks/MethodBadge.tsx | 181 +++++++++++ .../components/docs/blocks/ResponseBlock.tsx | 244 +++++++++++++++ .../components/docs/blocks/SectionHeader.tsx | 199 +++++++++++++ .../components/docs/blocks/StatusBadge.tsx | 176 +++++++++++ .../src/components/docs/blocks/index.ts | 176 +++++++++++ 13 files changed, 2187 insertions(+), 167 deletions(-) create mode 100644 apps/landing/src/components/docs/blocks/EndpointCard.tsx create mode 100644 apps/landing/src/components/docs/blocks/Hero.tsx create mode 100644 apps/landing/src/components/docs/blocks/InlineCode.tsx create mode 100644 apps/landing/src/components/docs/blocks/LinkCard.tsx create mode 100644 apps/landing/src/components/docs/blocks/LinkCardGrid.tsx create mode 100644 apps/landing/src/components/docs/blocks/MethodBadge.tsx create mode 100644 apps/landing/src/components/docs/blocks/ResponseBlock.tsx create mode 100644 apps/landing/src/components/docs/blocks/SectionHeader.tsx create mode 100644 apps/landing/src/components/docs/blocks/StatusBadge.tsx create mode 100644 apps/landing/src/components/docs/blocks/index.ts 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 0e2ab7b..6c4d3c7 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 @@ -1,14 +1,10 @@ 'use client'; /** - * API Reference: Text to Image - Final Variant + * API Reference: Text to Image * - * Features: - * - SubsectionNav at top - * - InteractiveAPIWidgetFinal with expand + success styling - * - Enhanced tables for parameters and error codes - * - Compact TipBox for parameter descriptions - * - Simplified Next Steps + * Refactored to use block components from @/components/docs/blocks + * Demonstrates API documentation patterns with semantic components */ import { DocsLayout } from '@/components/docs/layout/DocsLayout'; @@ -20,6 +16,14 @@ import { Table } from '@/components/docs/shared/Table'; import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget'; +import { + Hero, + SectionHeader, + InlineCode, + EndpointCard, + LinkCard, + LinkCardGrid, +} from '@/components/docs/blocks'; const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, @@ -67,46 +71,44 @@ export default function TextToImageAPIPage() { /> {/* Hero Section */} -
-

Text to Image

-

- Generate high-quality images from text prompts using AI-powered models. -

-
+ {/* Overview */}
-

Overview

+ + Overview +

The Text to Image endpoint allows you to generate images from natural language descriptions. Powered by Google Gemini 2.5 Flash and Imagen 4.0, it produces photorealistic images optimized for your specified requirements.

- Tip: Enable autoEnhance + Tip: Enable autoEnhance to let AI improve your prompts for better image quality.
{/* Endpoint */}
-

Endpoint

-
-
- - POST - - /api/text-to-image -
-

- Base URL: https://api.banatie.com -

-
+ + Endpoint + +
{/* Parameters */}
-

Parameters

+ + Parameters +

All parameters should be sent in the request body as JSON.

@@ -114,7 +116,7 @@ export default function TextToImageAPIPage() { [ - {param.name}, + {param.name}, {param.type}, {param.required ? 'Yes' : 'No'} @@ -125,16 +127,18 @@ export default function TextToImageAPIPage() {
- Default Values: If not specified, filename is - auto-generated, aspectRatio defaults - to "1:1", and autoEnhance is false. + Default Values: If not specified, filename is + auto-generated, aspectRatio defaults + to "1:1", and autoEnhance is false.
{/* Response */}
-

Response

+ + Response +

On success, the API returns a JSON object containing the generated image URL and metadata.

@@ -164,7 +168,9 @@ export default function TextToImageAPIPage() { {/* Error Codes */}
-

Error Codes

+ + Error Codes +

The API uses standard HTTP status codes and returns descriptive error messages.

@@ -173,22 +179,22 @@ export default function TextToImageAPIPage() { headers={['Status Code', 'Error Type', 'Description']} rows={[ [ - 400, + 400, 'Bad Request', 'Missing or invalid parameters in the request body', ], [ - 401, + 401, 'Unauthorized', 'Missing or invalid API key in X-API-Key header', ], [ - 429, + 429, 'Rate Limit', 'Too many requests. Check rate limit headers for retry timing', ], [ - 500, + 500, 'Server Error', 'Internal server error. Contact support if persists', ], @@ -205,7 +211,9 @@ export default function TextToImageAPIPage() { {/* Interactive Widget */}
-

Try It Live

+ + Try It Live +

Test the API directly from this page. Enter your API key and customize the parameters below.

@@ -220,33 +228,24 @@ export default function TextToImageAPIPage() { {/* Next Steps */}
-

Next Steps

+ + Next Steps + - + title="Error Handling" + description="Best practices for handling errors and retries in production." + accent="secondary" + /> +
diff --git a/apps/landing/src/app/docs/guides/authentication/page.tsx b/apps/landing/src/app/docs/guides/authentication/page.tsx index 648cfa9..6b3d159 100644 --- a/apps/landing/src/app/docs/guides/authentication/page.tsx +++ b/apps/landing/src/app/docs/guides/authentication/page.tsx @@ -19,6 +19,13 @@ import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; +import { + Hero, + SectionHeader, + InlineCode, + LinkCard, + LinkCardGrid, +} from '@/components/docs/blocks'; const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, @@ -61,26 +68,25 @@ export default function AuthenticationGuidePage() { /> {/* Hero Section */} -
-

Authentication

-

- Learn how to authenticate with the Banatie API using API keys, manage rate limits, and - implement security best practices. -

-
+ {/* Overview */}
-

Overview

+ + Overview +

Banatie uses API keys to authenticate requests. All API endpoints require authentication - via the X-API-Key header. + via the X-API-Key header. API keys are tied to organizations and projects, providing fine-grained access control.

Quick Start: New to API authentication? Check out our{' '} - + Getting Started guide {' '} for a step-by-step walkthrough. @@ -89,10 +95,14 @@ export default function AuthenticationGuidePage() { {/* API Keys */}
-

API Keys

+ + API Keys +
-

Key Types

+ + Key Types +

Banatie supports two types of API keys, each with different permissions and use cases:

@@ -101,13 +111,13 @@ export default function AuthenticationGuidePage() { headers={['Key Type', 'Permissions', 'Expiration', 'Use Case']} rows={[ [ - Master Key, + Master Key, 'Full admin access, can create/revoke keys', Never expires, 'Server-side admin operations, key management', ], [ - Project Key, + Project Key, 'Image generation only', 90 days, 'Application integration, API requests', @@ -126,7 +136,9 @@ export default function AuthenticationGuidePage() {
-

Creating Keys

+ + Creating Keys +

For first-time setup, use the bootstrap endpoint to create your initial master key:

@@ -181,9 +193,11 @@ curl -X POST https://api.banatie.com/api/admin/keys \\ {/* Using API Keys */}
-

Using API Keys

+ + Using API Keys +

- Include your API key in the X-API-Key header + Include your API key in the X-API-Key header with every request:

@@ -204,14 +218,16 @@ curl -X POST https://api.banatie.com/api/text-to-image \\ Environment Variables: Store API keys in environment variables, not hardcoded in your application. Example:{' '} - BANATIE_API_KEY + BANATIE_API_KEY
{/* Rate Limits */}
-

Rate Limits

+ + Rate Limits +

API keys are subject to rate limits to ensure fair usage and system stability. Limits vary by key type and plan tier: @@ -221,19 +237,19 @@ curl -X POST https://api.banatie.com/api/text-to-image \\ headers={['Key Type', 'Rate Limit', 'Reset Window', 'Upgrade Available']} rows={[ [ - Master Key, + Master Key, Unlimited, 'N/A', 'N/A', ], [ - Project Key (Free), + Project Key (Free), 100 requests/hour, '1 hour rolling', Yes, ], [ - Project Key (Pro), + Project Key (Pro), 1,000 requests/hour, '1 hour rolling', Yes, @@ -243,7 +259,7 @@ curl -X POST https://api.banatie.com/api/text-to-image \\

- When you exceed rate limits, the API returns a 429 Too Many Requests status. + When you exceed rate limits, the API returns a 429 Too Many Requests status. Check the response headers for retry timing:

@@ -266,7 +282,9 @@ X-RateLimit-Reset: 1704153600 {/* Security Best Practices */}
-

Security Best Practices

+ + Security Best Practices + Critical Security Guidelines: @@ -302,33 +320,24 @@ curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\ {/* Next Steps */}
-

Next Steps

+ + Next Steps + - + + + +
diff --git a/apps/landing/src/app/docs/page.tsx b/apps/landing/src/app/docs/page.tsx index f9aa7df..8a05d26 100644 --- a/apps/landing/src/app/docs/page.tsx +++ b/apps/landing/src/app/docs/page.tsx @@ -3,13 +3,8 @@ /** * Getting Started Page - Production Documentation * - * Main entry point for documentation - * Features: - * - SubsectionNav at top - * - Both TipBox styles (compact + prominent) - * - Enhanced tables - * - Simplified Next Steps (2 cards only) - * - Clean, accessible design + * Refactored to use block components from @/components/docs/blocks + * Demonstrates composition of reusable semantic components */ import { DocsLayout } from '@/components/docs/layout/DocsLayout'; @@ -19,6 +14,13 @@ import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; +import { + Hero, + SectionHeader, + ResponseBlock, + LinkCard, + LinkCardGrid, +} from '@/components/docs/blocks'; const tocItems = [ { id: 'introduction', text: 'Introduction', level: 2 }, @@ -53,17 +55,16 @@ export default function GettingStartedPage() { {/* Hero Section */} -
-

Getting Started

-

- Welcome to the Banatie API documentation. Learn how to integrate AI-powered image - generation into your applications in minutes. -

-
+ {/* Introduction */}
-

Introduction

+ + Introduction +

Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini 2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into @@ -86,10 +87,14 @@ export default function GettingStartedPage() { {/* Quick Start */}

-

Quick Start

+ + Quick Start +
-

Installation

+ + Installation +

Banatie is a REST API, so you do not need to install any libraries. However, we provide SDKs for popular languages to make integration easier. @@ -110,7 +115,9 @@ go get github.com/banatie/sdk-go`}

-

Authentication

+ + Authentication +

All API requests require an API key. You can create an API key from your dashboard or using the bootstrap endpoint for initial setup. @@ -139,7 +146,9 @@ export BANATIE_API_KEY="bnt_your_key_here"`} {/* First Request */}

-

Your First Request

+ + Your First Request +

Let's generate your first image! This example uses curl, but you can use any HTTP client or our SDKs. @@ -161,14 +170,11 @@ export BANATIE_API_KEY="bnt_your_key_here"`}

Expected Response:

-
-
- - βœ“ 200 Success - -
-
-                {`{
+            
-              
-
+}`} + />
{/* Next Steps - Simplified to 2 Cards */}
-

Next Steps

+ + Next Steps +

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

- + title="Authentication Guide" + description="Learn about API keys, rate limits, and security best practices." + accent="secondary" + /> +
diff --git a/apps/landing/src/components/docs/blocks/EndpointCard.tsx b/apps/landing/src/components/docs/blocks/EndpointCard.tsx new file mode 100644 index 0000000..d616f3d --- /dev/null +++ b/apps/landing/src/components/docs/blocks/EndpointCard.tsx @@ -0,0 +1,202 @@ +'use client'; + +/** + * EndpointCard Component + * + * A structured display block for API endpoint information including HTTP method, + * path, and base URL. Creates consistent, scannable API reference documentation. + * + * ## Design Principles + * + * 1. **Information Grouping**: Related endpoint data in one visual container + * - Method badge + endpoint path on same line for scannability + * - Base URL separated below for clarity without clutter + * - Container styling creates clear boundaries + * + * 2. **Visual Hierarchy**: Emphasis guides attention naturally + * - HTTP method badge draws eye first (color + position) + * - Endpoint path is prominent (white text, slightly larger) + * - Base URL is secondary (smaller, muted gray) + * + * 3. **Technical Precision**: Monospace fonts for code accuracy + * - Endpoint path uses code styling + * - Prevents ambiguity in technical content + * - Familiar to developers + * + * ## Layout Strategy + * + * Horizontal Flow: + * ``` + * [METHOD BADGE] /api/endpoint-path + * Base URL: https://api.example.com + * ``` + * + * This layout: + * - Puts most important info (method + path) on top line + * - Creates natural left-to-right reading flow + * - Groups related information visually + * - Works well at various screen sizes + * + * ## Container Styling + * + * Background & Border: + * - bg-slate-900/50: Semi-transparent dark background + * - Separates from page background + * - Maintains dark theme consistency + * - Subtle enough not to dominate + * + * - border-slate-700: Defined edges + * - Creates clear container boundaries + * - Adds structure without heaviness + * - Professional, technical appearance + * + * - rounded-xl: Soft corners (12px radius) + * - Modern, friendly appearance + * - Matches other card elements + * - Balances technical precision with approachability + * + * Padding: + * - p-4 (16px): Comfortable breathing room + * - Prevents cramped appearance + * - Makes content easy to read + * - Balances whitespace and content + * + * ## Typography System + * + * Endpoint Path: + * - text-sm: Slightly smaller than body but clearly readable + * - text-white: Maximum contrast for primary content + * - font-mono implicitly via : Technical accuracy + * + * Base URL: + * - text-xs: Clearly secondary information + * - text-gray-400: Muted to not compete with endpoint + * - Includes "Base URL:" label for context + * + * ## Spacing & Layout + * + * Flex Layout Benefits: + * - items-center: Vertically centers badge with text + * - gap-3 (12px): Comfortable space between badge and path + * - mb-2 (8px): Separates primary info from base URL + * + * ## Usage Examples + * + * ```tsx + * // Standard REST endpoint + * + * + * // Different HTTP methods + * + * + * + * + * // Custom base URL + * + * ``` + * + * ## Content Guidelines + * + * HTTP Method: + * - Always uppercase (GET, POST, PUT, DELETE, PATCH) + * - Choose semantically correct method + * - Follows REST conventions + * + * Endpoint Path: + * - Start with forward slash (/) + * - Use lowercase with hyphens (kebab-case) + * - Include path parameters with colon prefix (:id, :keyId) + * - Be specific and descriptive + * - Example: `/api/projects/:projectId/keys` + * + * Base URL: + * - Include protocol (https://) + * - Use production URL as default + * - No trailing slash + * - Example: `https://api.banatie.com` + * + * ## Accessibility + * + * - Semantic HTML structure + * - Proper contrast ratios for all text + * - MethodBadge includes aria-label + * - Logical reading order (method β†’ path β†’ base) + * - Keyboard accessible (no interactive elements, but focusable context) + * + * ## Visual Language + * + * The EndpointCard establishes: + * - Professional, technical aesthetic + * - Consistent API documentation pattern + * - Clear, unambiguous endpoint identification + * - Easy copy-paste of endpoint information + * - Quick visual scanning in multi-endpoint docs + * + * @component + * @example + * + */ + +import { MethodBadge, HttpMethod } from './MethodBadge'; + +/** + * Props for the EndpointCard component + */ +export interface EndpointCardProps { + /** HTTP method for the endpoint */ + method: HttpMethod; + /** API endpoint path (e.g., "/api/users") */ + endpoint: string; + /** Base URL for the API (default: "https://api.banatie.com") */ + baseUrl?: string; + /** Optional CSS class name for additional styling */ + className?: string; +} + +export const EndpointCard = ({ + method, + endpoint, + baseUrl = 'https://api.banatie.com', + className = '', +}: EndpointCardProps) => { + return ( +
+ {/* Method + Endpoint Row */} +
+ + {endpoint} +
+ + {/* Base URL */} +

+ Base URL: {baseUrl} +

+
+ ); +}; diff --git a/apps/landing/src/components/docs/blocks/Hero.tsx b/apps/landing/src/components/docs/blocks/Hero.tsx new file mode 100644 index 0000000..647eeaf --- /dev/null +++ b/apps/landing/src/components/docs/blocks/Hero.tsx @@ -0,0 +1,185 @@ +'use client'; + +/** + * Hero Component + * + * The primary heading section at the top of documentation pages. + * Establishes visual hierarchy and sets expectations for page content. + * + * ## Design Principles + * + * 1. **Information Hierarchy**: Clear progression from title to description + * - Large, bold title commands attention immediately + * - Subtitle provides context without competing with title + * - Consistent spacing creates rhythm and flow + * + * 2. **Typography Scale**: Responsive sizing for all devices + * - Mobile-first approach with thoughtful breakpoints + * - Maintains readability across screen sizes + * - Proper line-height for comfortable reading + * + * 3. **Visual Weight**: Balanced presence without overwhelming + * - White title for maximum contrast and impact + * - Gray subtitle for supporting, not competing + * - Generous margins create breathing room + * + * ## Size Variants + * + * @param {'default'} default - Standard documentation pages + * - Title: text-4xl (36px) β†’ md:text-5xl (48px) + * - Use cases: API references, guides, tutorials + * - Psychology: Professional, focused, informative + * - Spacing: mb-12 (48px) after hero + * + * @param {'large'} large - Major landing pages, section introductions + * - Title: text-5xl (48px) β†’ md:text-6xl (60px) + * - Use cases: Documentation home, major category pages + * - Psychology: Welcoming, important, primary entry point + * - Spacing: mb-16 (64px) after hero + * + * ## Typographic Hierarchy + * + * Title Characteristics: + * - **Weight**: font-bold (700) - Commands attention + * - **Color**: text-white - Maximum contrast, immediately readable + * - **Spacing**: mb-4 (16px) - Connects title to subtitle + * + * Subtitle Characteristics: + * - **Size**: text-xl (20px) - Large enough to be comfortable, small enough to defer + * - **Weight**: Regular (400) - Contrast with bold title + * - **Color**: text-gray-400 - Supporting role, doesn't compete + * - **Line height**: leading-relaxed (1.625) - Comfortable multi-line reading + * + * ## Responsive Behavior + * + * Mobile (<768px): + * - Smaller text sizes to fit narrow screens + * - Maintains readability with appropriate line lengths + * - Single column layout + * + * Desktop (β‰₯768px): + * - Larger text leverages available space + * - Enhanced visual impact + * - Better use of vertical rhythm + * + * ## Visual Language + * + * The hero serves multiple purposes in documentation: + * 1. **Orientation**: Tells users where they are + * 2. **Context**: Explains what this page covers + * 3. **Hierarchy**: Establishes importance through size + * 4. **Consistency**: Familiarpattern across all docs pages + * + * Color Psychology: + * - **White title**: Authority, clarity, primary information + * - **Gray subtitle**: Support, context, secondary information + * - Creates natural reading flow: bold β†’ light, primary β†’ secondary + * + * ## Accessibility + * + * - Uses semantic HTML (

for title) + * - Proper heading hierarchy (h1 is first heading on page) + * - Sufficient color contrast (white on dark background) + * - Readable font sizes (minimum 20px for subtitle) + * - Appropriate line-height for comfortable reading + * + * ## Usage Examples + * + * ```tsx + * // Standard API reference page + * + * + * // Documentation home page + * + * + * // Guide page + * + * ``` + * + * ## Content Guidelines + * + * Title: + * - Keep short and specific (1-5 words ideal) + * - Use sentence case (capitalize first word only) + * - Avoid punctuation unless necessary + * - Match page's primary purpose + * + * Subtitle: + * - One to two sentences maximum + * - Explain what user will learn or accomplish + * - Use active voice and present tense + * - End with period for complete thoughts + * + * @component + * @example + * + */ + +import { ReactNode } from 'react'; + +/** + * Size variant determining the visual scale of the hero + */ +export type HeroSize = 'default' | 'large'; + +/** + * Props for the Hero component + */ +export interface HeroProps { + /** The main page title (renders as h1) */ + title: string; + /** Supporting description or context */ + subtitle: string | ReactNode; + /** Size variant (default: 'default') */ + size?: HeroSize; + /** Optional CSS class name for additional styling */ + className?: string; +} + +/** + * Title size system mapping size variant to responsive text classes + */ +const titleSizes: Record = { + default: 'text-4xl md:text-5xl', + large: 'text-5xl md:text-6xl', +}; + +/** + * Spacing system for bottom margin + */ +const spacingSizes: Record = { + default: 'mb-12', + large: 'mb-16', +}; + +export const Hero = ({ + title, + subtitle, + size = 'default', + className = '', +}: HeroProps) => { + return ( +
+

+ {title} +

+

+ {subtitle} +

+
+ ); +}; diff --git a/apps/landing/src/components/docs/blocks/InlineCode.tsx b/apps/landing/src/components/docs/blocks/InlineCode.tsx new file mode 100644 index 0000000..758c174 --- /dev/null +++ b/apps/landing/src/components/docs/blocks/InlineCode.tsx @@ -0,0 +1,156 @@ +'use client'; + +/** + * InlineCode Component + * + * A consistent inline code element for technical content within documentation text. + * Provides semantic color variants to emphasize context and meaning. + * + * ## Design Principles + * + * 1. **Readability First**: High contrast with surrounding text + * - Dark background distinguishes code from prose + * - Slightly larger padding creates breathing room + * - Rounded corners soften appearance for inline usage + * + * 2. **Semantic Coloring**: Color conveys meaning beyond monospace + * - Different contexts require different visual emphasis + * - Colors match broader design system for consistency + * - Never rely on color alone (always has monospace + background) + * + * 3. **Typography**: Monospace font signals technical content + * - Built-in font-mono class ensures code appearance + * - Small size (text-sm) fits inline with body text + * - Maintains readability without disrupting flow + * + * ## Color Semantic Values + * + * @param {'primary'} primary - Default technical content, variable names, general code + * - Visual: Purple accent (matches brand primary) + * - Psychology: Neutral technical content, primary focus + * - Use cases: `apiKey`, `userId`, general inline code snippets + * - When to use: Default choice for any code reference + * + * @param {'success'} success - Positive examples, correct values, successful states + * - Visual: Green accent + * - Psychology: Correct, recommended, successful outcome + * - Use cases: `status: 200`, `"success": true`, correct API responses + * - When to use: Showing what TO do, expected good outcomes + * + * @param {'error'} error - Error values, incorrect usage, warnings + * - Visual: Red accent + * - Psychology: Wrong, dangerous, avoid + * - Use cases: `status: 500`, error codes, anti-patterns + * - When to use: Showing what NOT to do, error states + * + * @param {'neutral'} neutral - Informational, documentation, placeholders + * - Visual: Slate/Gray (matches text color scheme) + * - Psychology: Reference, documentation, less emphasis + * - Use cases: HTTP headers like `X-API-Key`, endpoints, technical terms + * - When to use: Supporting information, less critical code references + * + * ## Visual Language + * + * Background Strategy: + * - Dark bg (slate-800) creates clear separation from surrounding text + * - Works on both light and dark documentation themes + * - Sufficient contrast meets WCAG AA standards + * + * Padding Strategy: + * - Horizontal: px-1.5 (6px) - enough space but not disruptive + * - Vertical: py-0.5 (2px) - maintains inline text flow + * - Border radius: rounded (4px) - soft enough for inline, defined enough for blocks + * + * Font Strategy: + * - text-sm: Slightly smaller than body text but still readable + * - font-mono: Clear distinction from prose, signals code + * - font-normal: Not bold, integrates naturally with surrounding text + * + * ## Usage Examples + * + * ```tsx + * // Default technical content + * Set your API_KEY environment variable. + * + * // With semantic colors + * The response includes status: 200. + * Avoid using hardcoded credentials. + * Include the X-API-Key header. + * + * // Parameter documentation + * The autoEnhance parameter defaults to false. + * + * // Error messages + * If you receive 401 Unauthorized, check your API key. + * ``` + * + * ## Composition Guidelines + * + * DO: + * - Use for short code snippets (1-4 words) + * - Use for technical terms, variable names, values + * - Use semantic colors to reinforce meaning + * - Place naturally within sentences + * + * DON'T: + * - Use for multi-line code (use CodeBlock instead) + * - Use for long strings (creates readability issues) + * - Overuse color variants (primary is default for a reason) + * - Use as a design element (it's for code content only) + * + * @component + * @example + * apiKey + */ + +import { ReactNode } from 'react'; + +/** + * Semantic color variants for inline code + */ +export type InlineCodeColor = 'primary' | 'success' | 'error' | 'neutral'; + +/** + * Props for the InlineCode component + */ +export interface InlineCodeProps { + /** The code content to display */ + children: ReactNode; + /** Semantic color variant (default: 'primary') */ + color?: InlineCodeColor; + /** Optional CSS class name for additional styling */ + className?: string; +} + +/** + * Color system mapping semantic meanings to text colors + * All use same dark background for consistency + */ +const colorStyles: Record = { + primary: 'text-purple-400', + success: 'text-green-400', + error: 'text-red-400', + neutral: 'text-gray-400', +}; + +export const InlineCode = ({ + children, + color = 'primary', + className = '', +}: InlineCodeProps) => { + return ( + + {children} + + ); +}; diff --git a/apps/landing/src/components/docs/blocks/LinkCard.tsx b/apps/landing/src/components/docs/blocks/LinkCard.tsx new file mode 100644 index 0000000..33f28d5 --- /dev/null +++ b/apps/landing/src/components/docs/blocks/LinkCard.tsx @@ -0,0 +1,281 @@ +'use client'; + +/** + * LinkCard Component + * + * An interactive navigation card for guiding users to related documentation pages. + * Uses color accents and hover effects to create an engaging, explorable experience. + * + * ## Design Principles + * + * 1. **Visual Affordance**: Design signals interactivity + * - Gradient backgrounds hint at clickability + * - Hover states provide immediate feedback + * - Cursor changes to pointer on hover + * - Border transitions guide attention + * + * 2. **Semantic Color System**: Accent colors convey meaning + * - Primary (Purple): Main content, API references + * - Secondary (Cyan): Supporting content, guides + * - Success (Green): Getting started, tutorials + * - Warning (Amber): Important notices, deprecations + * + * 3. **Information Hierarchy**: Title dominates, description supports + * - Large, bold title draws attention + * - Smaller, muted description provides context + * - Title color changes on hover for feedback + * - Clean vertical rhythm (title β†’ description) + * + * ## Accent Color Semantics + * + * @param {'primary'} primary - Main navigational elements, API documentation + * - Visual: Purple gradient and border + * - Psychology: Primary brand, core content, important + * - Use cases: "API Reference", "Core Concepts", main docs + * - Gradient: from-purple-500/10 + * - Hover: border-purple-500/40, text-purple-400 + * + * @param {'secondary'} secondary - Supporting content, guides, tutorials + * - Visual: Cyan gradient and border + * - Psychology: Complementary, helpful, educational + * - Use cases: "Guides", "Tutorials", "Best Practices" + * - Gradient: from-cyan-500/10 + * - Hover: border-cyan-500/40, text-cyan-400 + * + * @param {'success'} success - Getting started, quick wins, positive actions + * - Visual: Green gradient and border + * - Psychology: Achievement, beginning, growth + * - Use cases: "Getting Started", "Quick Start", "First Steps" + * - Gradient: from-green-500/10 + * - Hover: border-green-500/40, text-green-400 + * + * @param {'warning'} warning - Important notices, cautions, deprecations + * - Visual: Amber gradient and border + * - Psychology: Attention, caution, important + * - Use cases: "Migration Guide", "Breaking Changes", "Deprecations" + * - Gradient: from-amber-500/10 + * - Hover: border-amber-500/40, text-amber-400 + * + * ## Interactive States + * + * Default State: + * - Subtle gradient background (from-{color}-500/10) + * - Muted border (border-slate-700/50) + * - White title, gray description + * - Inviting but not demanding attention + * + * Hover State: + * - Border brightens to accent color (/40 opacity) + * - Title transitions to accent color + * - Smooth transition (transition-colors) + * - Clear feedback that element is clickable + * + * ## Layout Structure + * + * Padding System: + * - p-5 (20px): Generous padding for comfortable clicking + * - Creates substantial hit area for accessibility + * - Provides breathing room for content + * + * Border & Radius: + * - rounded-xl (12px): Modern, friendly appearance + * - border: Defined structure + * - Matches other card components in system + * + * ## Typography System + * + * Title (h3): + * - text-lg (18px): Large enough to be primary visual element + * - font-semibold (600): Strong but not overbearing + * - text-white: Maximum contrast and readability + * - mb-2 (8px): Separates from description + * - Transitions to accent color on hover + * + * Description (p): + * - text-sm (14px): Clearly secondary to title + * - text-gray-400: Muted, supporting role + * - Provides context without competing with title + * + * ## Accessibility Features + * + * - Semantic HTML ( tag for links) + * - Proper heading hierarchy (h3 for card titles) + * - Keyboard accessible (focusable link) + * - Sufficient color contrast in all states + * - Large click target (full card clickable) + * - Clear focus states (browser default + hover) + * - Descriptive link text (title + description) + * + * ## Usage Examples + * + * ```tsx + * // Primary content link + * + * + * // Getting started + * + * + * // Supporting guide + * + * + * // Important notice + * + * ``` + * + * ## Content Guidelines + * + * Title: + * - 2-5 words ideal + * - Action-oriented or noun-based + * - Clear and specific + * - Sentence case + * - Examples: "API Reference", "Quick Start", "Authentication Guide" + * + * Description: + * - One sentence (10-20 words) + * - Explain what user will find/learn + * - Start with verb (Explore, Learn, Discover) + * - End with period + * - Be specific about content + * + * Accent Color: + * - Choose based on content type and importance + * - Maintain consistency across similar pages + * - Use primary for most API/core documentation + * - Reserve warning for truly important notices + * + * ## Visual Language + * + * The LinkCard system creates: + * - Intuitive navigation patterns + * - Clear content categorization through color + * - Engaging, explorable documentation + * - Professional yet friendly appearance + * - Consistent user experience across all docs + * + * @component + * @example + * + */ + +/** + * Accent color determining the card's visual theme + */ +export type LinkCardAccent = 'primary' | 'secondary' | 'success' | 'warning'; + +/** + * Props for the LinkCard component + */ +export interface LinkCardProps { + /** Navigation URL */ + href: string; + /** Card title (renders as h3) */ + title: string; + /** Supporting description */ + description: string; + /** Visual accent color */ + accent: LinkCardAccent; + /** Optional icon or emoji to display */ + icon?: string; + /** Optional CSS class name for additional styling */ + className?: string; +} + +/** + * Accent styles mapping color to gradient and hover colors + */ +const accentStyles: Record = { + primary: { + gradient: 'from-purple-500/10', + hoverBorder: 'hover:border-purple-500/40', + hoverText: 'group-hover:text-purple-400', + }, + secondary: { + gradient: 'from-cyan-500/10', + hoverBorder: 'hover:border-cyan-500/40', + hoverText: 'group-hover:text-cyan-400', + }, + success: { + gradient: 'from-green-500/10', + hoverBorder: 'hover:border-green-500/40', + hoverText: 'group-hover:text-green-400', + }, + warning: { + gradient: 'from-amber-500/10', + hoverBorder: 'hover:border-amber-500/40', + hoverText: 'group-hover:text-amber-400', + }, +}; + +export const LinkCard = ({ + href, + title, + description, + accent, + icon, + className = '', +}: LinkCardProps) => { + const styles = accentStyles[accent]; + + return ( + + {icon && ( +
{icon}
+ )} +

+ {title} +

+

+ {description} +

+
+ ); +}; diff --git a/apps/landing/src/components/docs/blocks/LinkCardGrid.tsx b/apps/landing/src/components/docs/blocks/LinkCardGrid.tsx new file mode 100644 index 0000000..b55232c --- /dev/null +++ b/apps/landing/src/components/docs/blocks/LinkCardGrid.tsx @@ -0,0 +1,216 @@ +'use client'; + +/** + * LinkCardGrid Component + * + * A responsive grid layout container for organizing multiple LinkCard components. + * Provides consistent spacing and responsive behavior for navigation card collections. + * + * ## Design Principles + * + * 1. **Responsive Layout**: Adapts gracefully to all screen sizes + * - Mobile: Single column for comfortable tap targets + * - Tablet/Desktop: Multi-column for efficient space usage + * - Fluid transitions between breakpoints + * + * 2. **Grid System**: CSS Grid provides flexible, robust layout + * - Equal-width columns maintain balance + * - Auto-fit for flexible number of cards + * - Consistent gaps create visual rhythm + * + * 3. **Composition Pattern**: Wrapper abstracts layout complexity + * - Parent handles grid logic + * - Children (LinkCards) focus on content + * - Separation of concerns improves maintainability + * + * ## Column Configuration + * + * @param {2} columns=2 - Two-column layout (default) + * - Visual: Balanced, side-by-side comparison + * - Use cases: "Next Steps", paired content, binary choices + * - Responsive: md:grid-cols-2 (2 cols β‰₯768px, 1 col <768px) + * - Psychology: Compare and choose pattern + * - Example: "API Reference" vs "Authentication Guide" + * + * @param {3} columns=3 - Three-column layout + * - Visual: Information-rich, multiple options + * - Use cases: Resource hubs, category pages, multiple paths + * - Responsive: md:grid-cols-3 (3 cols β‰₯768px, 1 col <768px) + * - Psychology: Multiple choice, exploration + * - Example: "Getting Started", "API Docs", "Examples" + * + * @param {4} columns=4 - Four-column layout + * - Visual: Dense, comprehensive navigation + * - Use cases: Resource libraries, extensive catalogs + * - Responsive: md:grid-cols-2 lg:grid-cols-4 (2 cols tablet, 4 cols desktop) + * - Psychology: Broad exploration, many options + * - Example: Multiple API endpoints, extensive guides + * + * ## Responsive Breakpoints + * + * Mobile (<768px): + * - All grids collapse to single column + * - Prevents cramped cards on small screens + * - Optimizes for thumb-friendly tap targets + * - Maintains readability and usability + * + * Tablet (β‰₯768px, <1024px): + * - 2-column: Displays as 2 columns + * - 3-column: Displays as 3 columns + * - 4-column: Displays as 2 columns (intermediate step) + * - Balances space usage and readability + * + * Desktop (β‰₯1024px): + * - All grids display at full column count + * - Efficient use of available width + * - Supports quick visual scanning + * + * ## Spacing System + * + * Gap: + * - gap-4 (16px): Comfortable separation between cards + * - Creates visual grouping without crowding + * - Maintains clean grid appearance + * - Consistent with other spacing in design system + * + * Why gap-4? + * - Larger than text line-height (prevents cramping) + * - Small enough to show relationship between cards + * - Works well with card padding (p-5) + * - Scales gracefully at all screen sizes + * + * ## Grid Behavior + * + * CSS Grid Properties: + * - `grid`: Establishes grid container + * - `grid-cols-1`: Mobile baseline (single column) + * - `md:grid-cols-{n}`: Tablet/desktop columns + * - `gap-4`: Gutter between grid items + * + * ## Accessibility Considerations + * + * - Maintains logical reading order (top-to-bottom, left-to-right) + * - Grid doesn't interfere with keyboard navigation + * - Responsive design ensures usability on all devices + * - No JavaScript required (pure CSS grid) + * - Works with screen readers (semantic HTML preserved) + * + * ## Usage Examples + * + * ```tsx + * // Two-column "Next Steps" section + * + * + * + * + * + * // Three-column resource hub + * + * + * + * + * + * + * // Four-column comprehensive navigation + * + * + * + * + * + * + * ``` + * + * ## Composition Guidelines + * + * DO: + * - Use consistent accent colors within a grid (e.g., all primary, or primary + secondary) + * - Keep card count balanced (even numbers work best for 2/4 columns) + * - Provide descriptive, parallel content in cards + * - Order cards by importance or logical flow + * + * DON'T: + * - Mix too many accent colors (creates visual chaos) + * - Use unbalanced card counts in 2-column (odd numbers leave gaps) + * - Nest grids inside grids (causes layout issues) + * - Put non-LinkCard components inside (breaks grid consistency) + * + * ## Visual Language + * + * The LinkCardGrid creates: + * - Organized, scannable navigation patterns + * - Professional documentation architecture + * - Clear visual hierarchy through layout + * - Responsive, mobile-friendly experience + * - Consistent spacing and alignment + * + * ## Performance + * + * - Pure CSS (no JavaScript overhead) + * - Minimal DOM elements (single wrapper div) + * - Hardware-accelerated grid layout + * - No re-renders or layout thrashing + * + * @component + * @example + * + * {children} + * + */ + +import { ReactNode } from 'react'; + +/** + * Column configuration for the grid + */ +export type GridColumns = 2 | 3 | 4; + +/** + * Props for the LinkCardGrid component + */ +export interface LinkCardGridProps { + /** Number of columns at tablet/desktop breakpoints */ + columns?: GridColumns; + /** LinkCard components to display in the grid */ + children: ReactNode; + /** Optional CSS class name for additional styling */ + className?: string; +} + +/** + * Responsive grid class mappings for different column counts + */ +const columnStyles: Record = { + 2: 'md:grid-cols-2', + 3: 'md:grid-cols-3', + 4: 'md:grid-cols-2 lg:grid-cols-4', // 2 cols on tablet, 4 on desktop +}; + +export const LinkCardGrid = ({ + columns = 2, + children, + className = '', +}: LinkCardGridProps) => { + return ( +
+ {children} +
+ ); +}; diff --git a/apps/landing/src/components/docs/blocks/MethodBadge.tsx b/apps/landing/src/components/docs/blocks/MethodBadge.tsx new file mode 100644 index 0000000..b54a492 --- /dev/null +++ b/apps/landing/src/components/docs/blocks/MethodBadge.tsx @@ -0,0 +1,181 @@ +'use client'; + +/** + * MethodBadge Component + * + * A specialized badge for HTTP method display in API documentation. + * Uses industry-standard color conventions to communicate REST operation types. + * + * ## Design Principles + * + * 1. **REST Semantic Mapping**: Colors align with HTTP method semantics + * - Follows industry conventions (GitHub, Stripe, Swagger UI) + * - Immediate visual recognition for developers + * - Consistent with HTTP specification meanings + * + * 2. **Visual Distinction**: Each method has unique, memorable color + * - High contrast for readability against dark backgrounds + * - Distinct enough to differentiate at a glance + * - Professional appearance suitable for technical documentation + * + * 3. **Typography**: Bold, uppercase display reinforces technical nature + * - font-bold for emphasis and readability + * - Uppercase matches HTTP specification format + * - Monospace-friendly sizing + * + * ## HTTP Method Semantics + * + * @param {'GET'} GET - Read/Retrieve operations (Safe, Idempotent) + * - Visual: Cyan/Blue - represents data flow inward (reading) + * - Psychology: Information retrieval, safe operation + * - Use cases: Fetch resources, list endpoints, query data + * - HTTP: Safe method, no side effects, cacheable + * + * @param {'POST'} POST - Create operations (Not safe, Not idempotent) + * - Visual: Green - represents creation, addition, growth + * - Psychology: Positive action, new resource creation + * - Use cases: Create resource, submit form, trigger action + * - HTTP: Creates new resource, may have side effects + * + * @param {'PUT'} PUT - Update/Replace operations (Not safe, Idempotent) + * - Visual: Amber/Orange - represents modification, change + * - Psychology: Caution, transformation, state change + * - Use cases: Update entire resource, replace content + * - HTTP: Idempotent, full resource update + * + * @param {'PATCH'} PATCH - Partial Update operations (Not safe, Not idempotent) + * - Visual: Purple - represents refinement, partial change + * - Psychology: Precision, targeted modification + * - Use cases: Update specific fields, partial resource modification + * - HTTP: Partial update, may not be idempotent + * + * @param {'DELETE'} DELETE - Delete operations (Not safe, Idempotent) + * - Visual: Red - represents removal, destruction, danger + * - Psychology: Warning, irreversible action, stop + * - Use cases: Remove resource, deactivate, destroy data + * - HTTP: Idempotent, removes resource + * + * ## Size Variants + * + * @param {'sm'} sm - Small size for inline usage (px-2 py-0.5, text-xs) + * @param {'md'} md - Medium size for standard usage (px-3 py-1, text-xs) [default] + * + * ## Visual Language + * + * - **Rounded corners**: Modern, friendly appearance + * - **Semi-transparent backgrounds**: Integrates with dark theme + * - **Solid borders**: Adds definition and structure + * - **Bold text**: Ensures readability and emphasis + * - **Consistent sizing**: Aligns with other badges in the design system + * + * Color Opacity Strategy: + * - Background: 20% opacity for subtle presence + * - Border: 40% opacity for clear definition + * - Text: 100% (400 weight) for maximum readability + * + * ## Usage Examples + * + * ```tsx + * // API Endpoint Documentation + * /api/users + * /api/users + * + * // With size variants + * + * + * + * // In endpoint cards + *
+ * + * /api/text-to-image + *
+ * ``` + * + * ## Industry Standards Reference + * + * This color scheme aligns with popular API documentation tools: + * - Swagger UI: Blue (GET), Green (POST), Orange (PUT), Red (DELETE) + * - Postman: Similar color conventions + * - GitHub API Docs: Consistent method color coding + * + * @component + * @example + * + */ + +import { ReactNode } from 'react'; + +/** + * HTTP method types following REST conventions + */ +export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; + +/** + * Size variant for the badge + */ +export type MethodBadgeSize = 'sm' | 'md'; + +/** + * Props for the MethodBadge component + */ +export interface MethodBadgeProps { + /** The HTTP method to display */ + method: HttpMethod; + /** Size variant (default: 'md') */ + size?: MethodBadgeSize; + /** Optional CSS class name for additional styling */ + className?: string; +} + +/** + * Color system mapping HTTP methods to semantic colors + * Follows industry standards for API documentation + */ +const methodStyles: Record = { + GET: 'bg-cyan-600/20 text-cyan-400 border-cyan-500/40', + POST: 'bg-green-600/20 text-green-400 border-green-500/40', + PUT: 'bg-amber-600/20 text-amber-400 border-amber-500/40', + PATCH: 'bg-purple-600/20 text-purple-400 border-purple-500/40', + DELETE: 'bg-red-600/20 text-red-400 border-red-500/40', +}; + +/** + * Size system mapping size variant to padding and font size + */ +const sizeStyles: Record = { + sm: 'px-2 py-0.5 text-xs', + md: 'px-3 py-1 text-xs', +}; + +/** + * Accessibility labels describing the HTTP method's purpose + */ +const methodLabels: Record = { + GET: 'GET request - retrieve data', + POST: 'POST request - create resource', + PUT: 'PUT request - update resource', + PATCH: 'PATCH request - partial update', + DELETE: 'DELETE request - remove resource', +}; + +export const MethodBadge = ({ + method, + size = 'md', + className = '', +}: MethodBadgeProps) => { + return ( + + {method} + + ); +}; diff --git a/apps/landing/src/components/docs/blocks/ResponseBlock.tsx b/apps/landing/src/components/docs/blocks/ResponseBlock.tsx new file mode 100644 index 0000000..f5c108e --- /dev/null +++ b/apps/landing/src/components/docs/blocks/ResponseBlock.tsx @@ -0,0 +1,244 @@ +'use client'; + +/** + * ResponseBlock Component + * + * A semantic display block for API response examples with status indicators. + * Visually differentiates success and error responses through color psychology. + * + * ## Design Principles + * + * 1. **Status Communication**: Color instantly conveys response type + * - Green = Success (2xx responses, positive outcomes) + * - Red = Error (4xx/5xx responses, failures) + * - Consistent with universal traffic light conventions + * + * 2. **Information Layering**: Progressive disclosure of details + * - Status badge in top-right for immediate recognition + * - Optional title provides context + * - Content area for actual response data + * - Layered styling adds depth without clutter + * + * 3. **Visual Feedback**: Subtle effects reinforce status + * - Background tint matches status color + * - Border emphasis adds structure + * - Soft shadow/glow creates depth + * - All at low opacity to avoid overwhelming + * + * ## Status Semantics + * + * @param {'success'} success - Successful API responses (2xx status codes) + * - Visual: Green color palette (green-500) + * - Psychology: Positive, correct, achieved + * - Use cases: 200 OK, 201 Created, 204 No Content + * - Styling: bg-green-500/5, border-green-500/30, shadow-green-500/10 + * - Badge: "βœ“ 200 Success", "βœ“ 201 Created" + * + * @param {'error'} error - Error API responses (4xx/5xx status codes) + * - Visual: Red color palette (red-500) + * - Psychology: Warning, problem, attention needed + * - Use cases: 400 Bad Request, 401 Unauthorized, 500 Server Error + * - Styling: bg-red-500/5, border-red-500/30, shadow-red-500/10 + * - Badge: "βœ— 400 Error", "βœ— 500 Error" + * + * ## Opacity Strategy + * + * Three-tier opacity system: + * - Background: /5 (5% opacity) - Subtle tint, doesn't obscure content + * - Border: /30 (30% opacity) - Clear definition, visible structure + * - Shadow: /10 (10% opacity) - Soft depth, enhances without distraction + * + * This creates: + * - Cohesive visual grouping + * - Clear status communication + * - Maintains content readability + * - Professional, polished appearance + * + * ## Layout Structure + * + * ``` + * β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + * β”‚ [STATUS BADGE] ←─── Absolute positioned + * β”‚ Optional Title β”‚ + * β”‚ (if provided) β”‚ + * β”‚ β”‚ + * β”‚
                         β”‚
+ * β”‚    Response content                  β”‚
+ * β”‚    ...                               β”‚
+ * β”‚  
β”‚ + * β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + * ``` + * + * Positioning Strategy: + * - Container: relative positioning context + * - Badge: absolute top-3 right-3 (float in top-right) + * - Content: mt-6 when badge present (clear space for badge) + * - Title: mb-3 if provided (separate from content) + * + * ## Typography & Content + * + * Title (optional): + * - text-sm: Small, not competing with main content + * - font-semibold: Subtle emphasis + * - text-gray-300: Readable but secondary + * - Purpose: Labels response type, adds context + * + * Response Content: + * - text-xs: Appropriate for code samples + * - text-gray-300: High contrast on dark background + * - font-mono (implicit in ): Code appearance + * - overflow-x-auto: Handles long lines gracefully + * + * ## Usage Examples + * + * ```tsx + * // Success response with title + * + * + * // Error response without title + * + * + * // Custom status label + * + * ``` + * + * ## Content Guidelines + * + * Response Content: + * - Use actual JSON/text from your API + * - Format with proper indentation (2 or 4 spaces) + * - Include realistic data (not just placeholders) + * - Show relevant fields (omit excessive detail) + * - Keep under 20-30 lines for readability + * + * Status Labels: + * - Include status code (200, 400, etc.) + * - Add descriptive text (Success, Error, Created) + * - Use checkmark (βœ“) for success + * - Use X (βœ—) for errors + * - Keep concise (2-3 words max) + * + * ## Accessibility + * + * - Semantic HTML structure (
)
+ * - Color is supplementary (text + symbols)
+ * - High contrast text colors
+ * - StatusBadge includes aria-label
+ * - Proper heading hierarchy if title used
+ * - Scrollable overflow for long content
+ *
+ * ## Visual Language
+ *
+ * The ResponseBlock creates:
+ * - Immediate status recognition through color
+ * - Professional code presentation
+ * - Clear example/documentation relationship
+ * - Consistent pattern across all API docs
+ * - Supports learn-by-example documentation style
+ *
+ * @component
+ * @example
+ * 
+ */
+
+import { StatusBadge, StatusType } from './StatusBadge';
+
+/**
+ * Props for the ResponseBlock component
+ */
+export interface ResponseBlockProps {
+  /** Status type determining color scheme */
+  status: Extract;
+  /** HTTP status code (e.g., 200, 400, 500) */
+  statusCode: number;
+  /** The response content to display (typically JSON) */
+  content: string;
+  /** Optional title above the response */
+  title?: string;
+  /** Optional custom status label (default: auto-generated from statusCode) */
+  statusLabel?: string;
+  /** Optional CSS class name for additional styling */
+  className?: string;
+}
+
+/**
+ * Status styles mapping status type to background, border, and shadow colors
+ */
+const statusStyles = {
+  success: 'bg-green-500/5 border-green-500/30 shadow-lg shadow-green-500/10',
+  error: 'bg-red-500/5 border-red-500/30 shadow-lg shadow-red-500/10',
+};
+
+/**
+ * Generate default status label from code and status
+ */
+const getDefaultStatusLabel = (code: number, status: 'success' | 'error'): string => {
+  const symbol = status === 'success' ? 'βœ“' : 'βœ—';
+  const text = status === 'success' ? 'Success' : 'Error';
+  return `${symbol} ${code} ${text}`;
+};
+
+export const ResponseBlock = ({
+  status,
+  statusCode,
+  content,
+  title,
+  statusLabel,
+  className = '',
+}: ResponseBlockProps) => {
+  const label = statusLabel || getDefaultStatusLabel(statusCode, status);
+
+  return (
+    
+ {/* Status Badge - Floating Top Right */} +
+ + {label} + +
+ + {/* Optional Title */} + {title && ( +

{title}

+ )} + + {/* Response Content */} +
+        {content}
+      
+
+ ); +}; diff --git a/apps/landing/src/components/docs/blocks/SectionHeader.tsx b/apps/landing/src/components/docs/blocks/SectionHeader.tsx new file mode 100644 index 0000000..3398181 --- /dev/null +++ b/apps/landing/src/components/docs/blocks/SectionHeader.tsx @@ -0,0 +1,199 @@ +'use client'; + +/** + * SectionHeader Component + * + * Consistent heading elements for organizing documentation content into hierarchical sections. + * Provides visual rhythm and structure throughout documentation pages. + * + * ## Design Principles + * + * 1. **Visual Hierarchy**: Size and weight indicate content importance + * - Level 2 (h2): Major sections, primary content divisions + * - Level 3 (h3): Subsections, supporting details + * - Consistent styling creates predictable structure + * + * 2. **Semantic HTML**: Proper heading levels for accessibility + * - Uses correct HTML heading tags (h2, h3) + * - Supports screen readers and document outline + * - Enables Table of Contents generation + * - Critical for SEO and document structure + * + * 3. **Spacing System**: Establishes vertical rhythm + * - Top margin separates from previous content + * - Bottom margin creates breathing room before content + * - Consistent spacing improves scannability + * + * ## Heading Level Semantics + * + * @param {2} level2 - Major section headings (h2) + * - Visual: text-3xl (30px), font-bold, text-white + * - Spacing: mb-4 (16px) below, mb-6 (24px) for sections with mb-12 + * - Psychology: Primary divisions, main topics + * - Use cases: "Overview", "Parameters", "Response", "Error Codes" + * - Hierarchy: Second level (after page h1/Hero) + * - SEO: Key topic signals for search engines + * + * @param {3} level3 - Subsection headings (h3) + * - Visual: text-xl (20px), font-semibold, text-white + * - Spacing: mb-3 (12px) below, mb-4 (16px) for subsections with mb-8 + * - Psychology: Supporting topics, detailed breakdowns + * - Use cases: "Key Types", "Creating Keys", "Rate Limits" + * - Hierarchy: Third level (under h2 sections) + * - SEO: Supporting detail signals + * + * ## Typography Scale Reasoning + * + * Level 2 (text-3xl / 30px): + * - Large enough to clearly mark major sections + * - Smaller than Hero (36-48px) to maintain hierarchy + * - Bold weight adds emphasis and structure + * - White color ensures readability and prominence + * + * Level 3 (text-xl / 20px): + * - Noticeably smaller than h2, maintaining hierarchy + * - Semibold (600) instead of bold provides subtle distinction + * - Large enough to serve as clear subsection marker + * - Balances prominence with subordinate role + * + * ## Spacing Philosophy + * + * Bottom Margin Strategy: + * - h2: mb-4 or mb-6 depending on section context + * - mb-4 for tighter sections with nearby content + * - mb-6 for major sections introducing substantial content + * - h3: mb-3 or mb-4 depending on subsection context + * - Smaller margins reflect subordinate hierarchy + * - Still provides clear separation from content + * + * ## Anchor Link Support + * + * The `id` prop enables: + * - Direct linking to specific sections (#section-name) + * - Table of Contents navigation + * - Deep linking from external sources + * - Browser history for scrolled positions + * + * ID Naming Convention: + * - Use kebab-case (lowercase with hyphens) + * - Descriptive and unique per page + * - Example: "api-keys", "rate-limits", "error-handling" + * + * ## Accessibility Features + * + * - Semantic HTML heading levels (h2, h3) + * - Proper document outline structure + * - Sufficient color contrast (white on dark) + * - Clear visual distinction between levels + * - Screen reader friendly navigation + * - Keyboard accessible anchor links + * + * ## Usage Examples + * + * ```tsx + * // Major section heading (h2) + * + * Overview + * + * + * // Subsection heading (h3) + * + * Key Types + * + * + * // Custom spacing with className + * + * Parameters + * + * ``` + * + * ## Content Guidelines + * + * Level 2 Headings: + * - 1-3 words ideal (concise and scannable) + * - Sentence case (capitalize first word) + * - Action-oriented or descriptive nouns + * - Examples: "Quick Start", "Authentication", "Rate Limits" + * + * Level 3 Headings: + * - 1-4 words, slightly more descriptive + * - Sentence case + * - Specific subtopics or steps + * - Examples: "Creating Keys", "Using API Keys", "Security Best Practices" + * + * ## Visual Language + * + * The header system creates a visual rhythm that: + * - Guides the eye through content naturally + * - Breaks long pages into digestible chunks + * - Signals importance through size and weight + * - Maintains consistency across all documentation + * - Supports quick scanning and navigation + * + * @component + * @example + * + * Getting Started + * + */ + +import { ReactNode } from 'react'; + +/** + * Heading level determining HTML tag and visual styling + */ +export type SectionHeaderLevel = 2 | 3; + +/** + * Props for the SectionHeader component + */ +export interface SectionHeaderProps { + /** Heading level (h2 or h3) for semantic structure */ + level: SectionHeaderLevel; + /** The heading text content */ + children: ReactNode; + /** Optional ID for anchor linking and table of contents */ + id?: string; + /** Optional CSS class name for additional styling (e.g., custom margins) */ + className?: string; +} + +/** + * Typography styles mapping heading level to text size and weight + */ +const levelStyles: Record = { + 2: 'text-3xl font-bold', + 3: 'text-xl font-semibold', +}; + +/** + * Default spacing system for bottom margins + */ +const defaultSpacing: Record = { + 2: 'mb-4', + 3: 'mb-3', +}; + +export const SectionHeader = ({ + level, + children, + id, + className, +}: SectionHeaderProps) => { + const Tag = `h${level}` as 'h2' | 'h3'; + const spacing = className?.includes('mb-') ? '' : defaultSpacing[level]; + + return ( + + {children} + + ); +}; diff --git a/apps/landing/src/components/docs/blocks/StatusBadge.tsx b/apps/landing/src/components/docs/blocks/StatusBadge.tsx new file mode 100644 index 0000000..169ac41 --- /dev/null +++ b/apps/landing/src/components/docs/blocks/StatusBadge.tsx @@ -0,0 +1,176 @@ +'use client'; + +/** + * StatusBadge Component + * + * A semantic status indicator that uses color psychology and consistent styling + * to communicate state, result, or severity across documentation. + * + * ## Design Principles + * + * 1. **Semantic Color System**: Colors convey meaning, not just decoration + * - Uses consistent color mapping across all documentation + * - Follows industry standards (green = success, red = error, etc.) + * + * 2. **Visual Hierarchy**: Small, unobtrusive elements that enhance readability + * - Pill-shaped design for friendly, modern appearance + * - Subtle backgrounds with semi-transparent colors + * - Border emphasis for definition without heaviness + * + * 3. **Accessibility**: Meets WCAG 2.1 AA standards + * - Sufficient color contrast ratios + * - Semantic HTML with aria-label + * - Text labels (never color-only communication) + * + * ## Semantic Status Values + * + * @param {'success'} success - Positive outcomes, completed actions, 2xx HTTP responses + * - Visual: Green color palette + * - Psychology: Achievement, correctness, go-ahead signal + * - Use cases: "200 Success", "Completed", "Active", "βœ“ Passed" + * + * @param {'info'} info - Neutral information, documentation, helpful tips + * - Visual: Blue/Cyan color palette + * - Psychology: Calm, trustworthy, educational + * - Use cases: "Beta", "New", "Info", "Note" + * + * @param {'warning'} warning - Caution, deprecation, rate limits, 4xx client errors + * - Visual: Amber/Orange color palette + * - Psychology: Attention needed, proceed with caution + * - Use cases: "429 Rate Limit", "Deprecated", "Warning", "Limited" + * + * @param {'error'} error - Failures, critical issues, 5xx server errors, security alerts + * - Visual: Red color palette + * - Psychology: Stop, danger, requires immediate attention + * - Use cases: "500 Error", "Failed", "Critical", "Blocked" + * + * @param {'neutral'} neutral - Default state, placeholder, unspecified + * - Visual: Slate/Gray color palette + * - Psychology: Neutral, balanced, inactive + * - Use cases: "Pending", "Unknown", "Draft", "Inactive" + * + * ## Size Variants + * + * @param {'sm'} sm - Small size for inline usage, tight spaces + * - Font: text-xs + * - Padding: px-2 py-0.5 + * - Use: Inline with text, table cells, compact layouts + * + * @param {'md'} md - Medium size (default) for standard usage + * - Font: text-xs + * - Padding: px-3 py-1 + * - Use: General purpose, code examples, section markers + * + * ## Visual Language + * + * The badge uses a rounded-full design (pill shape) which: + * - Creates visual consistency with other UI elements (buttons, tags) + * - Feels modern and friendly (vs. harsh rectangular badges) + * - Groups related information visually + * - Works well at small sizes without appearing cramped + * + * Color opacity levels (X/20 bg, X/40 border): + * - Background: 20% opacity for subtle presence + * - Border: 40% opacity for definition + * - Text: 100% for maximum readability + * + * ## Usage Examples + * + * ```tsx + * // HTTP Status Codes + * 200 OK + * 500 Error + * + * // API States + * Beta + * Deprecated + * + * // System Status + * βœ“ Active + * Pending + * ``` + * + * @component + * @example + * 200 Success + */ + +import { ReactNode } from 'react'; + +/** + * Semantic status type representing the meaning/severity of the badge + */ +export type StatusType = 'success' | 'info' | 'warning' | 'error' | 'neutral'; + +/** + * Size variant for the badge + */ +export type StatusSize = 'sm' | 'md'; + +/** + * Props for the StatusBadge component + */ +export interface StatusBadgeProps { + /** The semantic status that determines color and meaning */ + status: StatusType; + /** The content to display inside the badge */ + children: ReactNode; + /** Size variant (default: 'md') */ + size?: StatusSize; + /** Optional CSS class name for additional styling */ + className?: string; +} + +/** + * Color system mapping semantic status to Tailwind color utilities + * Follows the established design system color palette + */ +const statusStyles: Record = { + success: 'bg-green-500/20 text-green-400 border border-green-500/40', + info: 'bg-cyan-500/20 text-cyan-400 border border-cyan-500/40', + warning: 'bg-amber-500/20 text-amber-400 border border-amber-500/40', + error: 'bg-red-500/20 text-red-400 border border-red-500/40', + neutral: 'bg-slate-500/20 text-slate-400 border border-slate-500/40', +}; + +/** + * Size system mapping size variant to padding and font size + */ +const sizeStyles: Record = { + sm: 'px-2 py-0.5 text-xs', + md: 'px-3 py-1 text-xs', +}; + +/** + * Human-readable labels for screen readers + */ +const statusLabels: Record = { + success: 'Success status', + info: 'Information status', + warning: 'Warning status', + error: 'Error status', + neutral: 'Neutral status', +}; + +export const StatusBadge = ({ + status, + children, + size = 'md', + className = '', +}: StatusBadgeProps) => { + return ( + + {children} + + ); +}; diff --git a/apps/landing/src/components/docs/blocks/index.ts b/apps/landing/src/components/docs/blocks/index.ts new file mode 100644 index 0000000..1f5de28 --- /dev/null +++ b/apps/landing/src/components/docs/blocks/index.ts @@ -0,0 +1,176 @@ +/** + * Documentation Block Components + * + * A comprehensive library of reusable, semantic components for building + * consistent, professional API documentation. + * + * ## Design System Overview + * + * This collection establishes a visual language for documentation through: + * - **Semantic Color System**: Enum-based color values with clear meanings + * - **Consistent Typography**: Hierarchical text sizing and weights + * - **Responsive Layouts**: Mobile-first, adaptive components + * - **Accessibility First**: WCAG 2.1 AA compliance throughout + * - **Comprehensive Documentation**: Every component fully documented + * + * ## Component Categories + * + * ### Status & Indicators + * - **StatusBadge**: Semantic status indicators (success, info, warning, error, neutral) + * - **MethodBadge**: HTTP method badges (GET, POST, PUT, PATCH, DELETE) + * + * ### Typography & Content + * - **Hero**: Page-level headings with title and subtitle + * - **SectionHeader**: Hierarchical section headings (h2, h3) + * - **InlineCode**: Semantic inline code elements + * + * ### API Documentation + * - **EndpointCard**: Structured API endpoint display + * - **ResponseBlock**: API response examples with status visualization + * + * ### Navigation + * - **LinkCard**: Interactive navigation cards with accent colors + * - **LinkCardGrid**: Responsive grid layout for link cards + * + * ## Usage Philosophy + * + * These components follow key principles: + * + * 1. **Composition over Configuration** + * - Small, focused components combine to create pages + * - Each component does one thing well + * - Easy to understand and maintain + * + * 2. **Semantic Props** + * - Enum values over raw values (accent='primary' not color='#8b5cf6') + * - Meaning-based names (status='success' not color='green') + * - Self-documenting API + * + * 3. **Consistent Patterns** + * - Similar props across components (className, children) + * - Predictable behavior and styling + * - Easy to learn and use + * + * 4. **Accessibility Built-in** + * - Semantic HTML throughout + * - ARIA labels where appropriate + * - Keyboard navigation support + * - Sufficient color contrast + * + * ## Example: Building a Documentation Page + * + * ```tsx + * import { + * Hero, + * SectionHeader, + * InlineCode, + * EndpointCard, + * ResponseBlock, + * LinkCard, + * LinkCardGrid, + * } from '@/components/docs/blocks'; + * + * export default function APIPage() { + * return ( + * <> + * + * + * + * Endpoint + * + * + * + * + * + * Response + * + * + * + * + * + * Next Steps + * + * + * + * + * + * + * + * ); + * } + * ``` + * + * ## Color System Reference + * + * ### Semantic Colors + * - **primary**: Purple - Brand primary, main content + * - **secondary**: Cyan - Complementary, supporting content + * - **success**: Green - Positive outcomes, achievements + * - **info**: Blue/Cyan - Informational, neutral + * - **warning**: Amber - Caution, important notices + * - **error**: Red - Errors, problems, danger + * - **neutral**: Slate/Gray - Default, inactive + * + * ### HTTP Method Colors + * - **GET**: Cyan - Read operations + * - **POST**: Green - Create operations + * - **PUT**: Amber - Update operations + * - **PATCH**: Purple - Partial update + * - **DELETE**: Red - Delete operations + * + * ## Spacing System + * + * Consistent spacing creates visual rhythm: + * - **sm**: Tight spacing for compact layouts + * - **md**: Standard spacing (default for most components) + * - **lg**: Generous spacing for major sections + * + * ## Typography Scale + * + * Hierarchical text sizing: + * - **Hero**: text-4xl β†’ text-6xl (large, page-level) + * - **H2**: text-3xl (section headings) + * - **H3**: text-xl (subsection headings) + * - **Body**: text-base (paragraph text) + * - **Small**: text-sm (supporting text) + * - **Code**: text-xs (code samples) + * + * @module blocks + */ + +// Status & Indicators +export { StatusBadge, type StatusBadgeProps, type StatusType, type StatusSize } from './StatusBadge'; +export { MethodBadge, type MethodBadgeProps, type HttpMethod, type MethodBadgeSize } from './MethodBadge'; + +// Typography & Content +export { Hero, type HeroProps, type HeroSize } from './Hero'; +export { SectionHeader, type SectionHeaderProps, type SectionHeaderLevel } from './SectionHeader'; +export { InlineCode, type InlineCodeProps, type InlineCodeColor } from './InlineCode'; + +// API Documentation +export { EndpointCard, type EndpointCardProps } from './EndpointCard'; +export { ResponseBlock, type ResponseBlockProps } from './ResponseBlock'; + +// Navigation +export { LinkCard, type LinkCardProps, type LinkCardAccent } from './LinkCard'; +export { LinkCardGrid, type LinkCardGridProps, type GridColumns } from './LinkCardGrid'; From da33f96c35fac9985d15c28f1f2d1d25e7cf1c81 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Tue, 21 Oct 2025 20:56:35 +0700 Subject: [PATCH 09/11] feat: improve docs layout --- .../src/app/docs/api/text-to-image/page.tsx | 38 +------ .../app/docs/guides/authentication/page.tsx | 47 ++------- apps/landing/src/app/docs/layout.tsx | 99 +++++++++++++++++-- apps/landing/src/app/docs/page.tsx | 33 +------ apps/landing/src/contexts/TocContext.tsx | 53 ++++++++++ 5 files changed, 162 insertions(+), 108 deletions(-) create mode 100644 apps/landing/src/contexts/TocContext.tsx 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 6c4d3c7..93065e7 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 @@ -4,16 +4,12 @@ * API Reference: Text to Image * * Refactored to use block components from @/components/docs/blocks - * Demonstrates API documentation patterns with semantic components + * Layout (SubsectionNav, DocsSidebar, Breadcrumb, TOC) handled by parent layout.tsx + * This page only provides TOC items and content. */ -import { DocsLayout } from '@/components/docs/layout/DocsLayout'; -import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; -import { DocsTOC } from '@/components/docs/layout/DocsTOC'; -import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget'; import { @@ -24,6 +20,7 @@ import { LinkCard, LinkCardGrid, } from '@/components/docs/blocks'; +import { TocProvider } from '@/contexts/TocContext'; const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, @@ -35,12 +32,6 @@ const tocItems = [ { id: 'next-steps', text: 'Next Steps', level: 2 }, ]; -const navItems = [ - { label: 'Documentation', href: '/docs' }, - { label: 'Demo', href: '/demo' }, - { label: 'Examples', href: '/docs/examples' }, -]; - const parameters = [ { name: 'prompt', type: 'string', required: true, description: 'Text description of the image to generate' }, { name: 'filename', type: 'string', required: false, description: 'Output filename (without extension)' }, @@ -50,25 +41,7 @@ const parameters = [ export default function TextToImageAPIPage() { return ( - <> - {/* Subsection Navigation with API Key Input */} - - - } - toc={} - > - + {/* Hero Section */}

- - + ); } diff --git a/apps/landing/src/app/docs/guides/authentication/page.tsx b/apps/landing/src/app/docs/guides/authentication/page.tsx index 6b3d159..a8d1a73 100644 --- a/apps/landing/src/app/docs/guides/authentication/page.tsx +++ b/apps/landing/src/app/docs/guides/authentication/page.tsx @@ -1,23 +1,15 @@ 'use client'; /** - * Authentication Guide - Final Variant + * Authentication Guide * - * Features: - * - SubsectionNav at top - * - Prominent TipBox for security warnings - * - Compact TipBox for general tips - * - Enhanced tables for rate limits and key types - * - Simplified Next Steps + * 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. */ -import { DocsLayout } from '@/components/docs/layout/DocsLayout'; -import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; -import { DocsTOC } from '@/components/docs/layout/DocsTOC'; -import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { Hero, @@ -26,6 +18,7 @@ import { LinkCard, LinkCardGrid, } from '@/components/docs/blocks'; +import { TocProvider } from '@/contexts/TocContext'; const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, @@ -38,34 +31,9 @@ const tocItems = [ { id: 'next-steps', text: 'Next Steps', level: 2 }, ]; -const navItems = [ - { label: 'Documentation', href: '/docs' }, - { label: 'Demo', href: '/demo' }, - { label: 'Examples', href: '/docs/examples' }, -]; - export default function AuthenticationGuidePage() { return ( - <> - {/* Subsection Navigation */} - - - } - toc={} - > - + {/* Hero Section */}
- - + ); } diff --git a/apps/landing/src/app/docs/layout.tsx b/apps/landing/src/app/docs/layout.tsx index 7c810cb..0f01a99 100644 --- a/apps/landing/src/app/docs/layout.tsx +++ b/apps/landing/src/app/docs/layout.tsx @@ -1,22 +1,78 @@ +'use client'; + 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 * - * Simple wrapper for all documentation pages. - * Each variant handles its own layout/navigation. + * Centralized layout for all documentation pages providing: + * - SubsectionNav at the top + * - Three-column layout (sidebar, content, TOC) + * - Automatic breadcrumb generation + * - Consistent background and styling + * + * Pages only need to: + * 1. Wrap content with + * 2. Provide their content * * Features: - * - Consistent background gradient matching landing page - * - No navigation/sidebars at this level - * - Children render their own layouts + * - Animated gradient background matching landing page + * - Automatic active page detection via pathname + * - Auto-generated breadcrumbs from URL structure + * - Responsive layout (mobile β†’ tablet β†’ desktop) */ interface DocsRootLayoutProps { children: ReactNode; } +const navItems = [ + { label: 'Documentation', href: '/docs' }, + { label: 'Demo', href: '/demo' }, + { 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 (
{/* Animated gradient background (matching landing page) */} @@ -25,8 +81,37 @@ export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
- {/* Content */} -
{children}
+ {/* Subsection Navigation */} + + + {/* Three-column Documentation Layout */} +
+ {/* Left Sidebar - Thin, minimal design */} + + + {/* Main Content Area - Wide margins for comfortable reading */} +
+
+ {/* Breadcrumb */} + + + {/* Page Content */} + {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 8a05d26..969db2f 100644 --- a/apps/landing/src/app/docs/page.tsx +++ b/apps/landing/src/app/docs/page.tsx @@ -4,16 +4,12 @@ * Getting Started Page - Production Documentation * * Refactored to use block components from @/components/docs/blocks - * Demonstrates composition of reusable semantic components + * Layout (SubsectionNav, DocsSidebar, Breadcrumb, TOC) handled by parent layout.tsx + * This page only provides TOC items and content. */ -import { DocsLayout } from '@/components/docs/layout/DocsLayout'; -import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; -import { DocsTOC } from '@/components/docs/layout/DocsTOC'; -import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { TipBox } from '@/components/docs/shared/TipBox'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; -import { Breadcrumb } from '@/components/docs/shared/Breadcrumb'; import { Hero, SectionHeader, @@ -21,6 +17,7 @@ import { LinkCard, LinkCardGrid, } from '@/components/docs/blocks'; +import { TocProvider } from '@/contexts/TocContext'; const tocItems = [ { id: 'introduction', text: 'Introduction', level: 2 }, @@ -31,28 +28,9 @@ const tocItems = [ { id: 'next-steps', text: 'Next Steps', level: 2 }, ]; -const navItems = [ - { label: 'Documentation', href: '/docs' }, - { label: 'Demo', href: '/demo' }, - { label: 'Examples', href: '/docs/examples' }, -]; - export default function GettingStartedPage() { return ( - <> - {/* Subsection Navigation */} - - - } - toc={} - > - + {/* Hero Section */}
- - + ); } diff --git a/apps/landing/src/contexts/TocContext.tsx b/apps/landing/src/contexts/TocContext.tsx new file mode 100644 index 0000000..7460375 --- /dev/null +++ b/apps/landing/src/contexts/TocContext.tsx @@ -0,0 +1,53 @@ +'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; +}; From f90fd8f65a397c4b21f00d585527b71c67de9a71 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Tue, 21 Oct 2025 22:47:45 +0700 Subject: [PATCH 10/11] 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; -}; From da6887d41c6dbaaee6368455e09776144a737b89 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Tue, 21 Oct 2025 23:31:08 +0700 Subject: [PATCH 11/11] feat: update navbar --- apps/landing/src/app/docs/layout.tsx | 32 ++--- .../src/components/docs/layout/DocPage.tsx | 78 ++++++------ .../components/layout/ThreeColumnLayout.tsx | 119 ++++++++++++++++++ .../src/components/shared/SubsectionNav.tsx | 85 ++++++++----- 4 files changed, 231 insertions(+), 83 deletions(-) create mode 100644 apps/landing/src/components/layout/ThreeColumnLayout.tsx diff --git a/apps/landing/src/app/docs/layout.tsx b/apps/landing/src/app/docs/layout.tsx index 65616e6..69e1d52 100644 --- a/apps/landing/src/app/docs/layout.tsx +++ b/apps/landing/src/app/docs/layout.tsx @@ -4,20 +4,25 @@ import { ReactNode } from 'react'; import { usePathname } from 'next/navigation'; import { SubsectionNav } from '@/components/shared/SubsectionNav'; import { DocsSidebar } from '@/components/docs/layout/DocsSidebar'; +import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout'; /** * Root Documentation Layout * * Provides shared layout elements for all documentation pages: * - SubsectionNav at the top - * - Left Sidebar (DocsSidebar) + * - Three-column layout (left sidebar + content + right TOC via DocPage) * - Background gradients - * - Two-column flex wrapper (sidebar + main content) + * + * Uses ThreeColumnLayout for consistent column structure: + * - Left: DocsSidebar (w-64, hidden lg:block) + * - Center: Page content (flex-1) + * - Right: Handled by DocPage component * * Pages handle their own: * - Breadcrumbs (manually specified) * - Article content - * - TOC sidebar (on the right) + * - TOC sidebar (on the right via DocPage) * * Features: * - Animated gradient background matching landing page @@ -54,17 +59,16 @@ export default function DocsRootLayout({ children }: DocsRootLayoutProps) { ctaHref="/signup" /> - {/* Two-column Documentation Layout */} -
- {/* Left Sidebar - Thin, minimal design */} - - - {/* Main Content Area - Pages render here with their own article + TOC structure */} -
- {children} -
+ {/* Three-column Documentation Layout */} +
+ + +
+ } + center={children} + />
); diff --git a/apps/landing/src/components/docs/layout/DocPage.tsx b/apps/landing/src/components/docs/layout/DocPage.tsx index a14f9e1..3b5ff94 100644 --- a/apps/landing/src/components/docs/layout/DocPage.tsx +++ b/apps/landing/src/components/docs/layout/DocPage.tsx @@ -9,6 +9,10 @@ * - Next Steps section at bottom * - Table of Contents sidebar on the right * + * Uses ThreeColumnLayout for consistent column structure: + * - Center: Article content (max-w-3xl) + * - Right: Table of Contents (w-56, hidden xl:block) + * * This component extracts common layout patterns from all doc pages, * reducing duplication and ensuring consistency. * @@ -29,6 +33,7 @@ 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'; +import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout'; /** * Next step link card configuration @@ -92,45 +97,46 @@ export const DocPage = ({ children, }: DocPageProps) => { return ( -
- {/* Article Content */} -
- {/* Breadcrumb Navigation */} - + + {/* Breadcrumb Navigation */} + - {/* Page Content (Hero + Sections) */} - {children} + {/* Page Content (Hero + Sections) */} + {children} - {/* Next Steps Section */} -
- - Next Steps - + {/* Next Steps Section */} +
+ + Next Steps + - {nextSteps.description && ( -

- {nextSteps.description} -

- )} + {nextSteps.description && ( +

+ {nextSteps.description} +

+ )} - - {nextSteps.links.map((link, index) => ( - - ))} - -
-
- - {/* Right TOC Sidebar */} - -
+ + {nextSteps.links.map((link, index) => ( + + ))} + +
+ + } + right={ +
+ +
+ } + /> ); }; diff --git a/apps/landing/src/components/layout/ThreeColumnLayout.tsx b/apps/landing/src/components/layout/ThreeColumnLayout.tsx new file mode 100644 index 0000000..4a0c01e --- /dev/null +++ b/apps/landing/src/components/layout/ThreeColumnLayout.tsx @@ -0,0 +1,119 @@ +'use client'; + +/** + * Three Column Layout - Core Wireframe Component + * + * Provides a consistent three-column layout structure used across the application. + * This is the single source of truth for column widths, breakpoints, and responsive behavior. + * + * Column Structure: + * - Left: w-64 (256px), hidden until lg breakpoint + * - Center: flex-1 (flexible, takes remaining space) + * - Right: w-56 (224px), hidden until xl breakpoint + * + * Usage Examples: + * + * 1. SubsectionNav (3 columns): + * } + * center={} + * right={} + * /> + * + * 2. Docs Layout (2 columns - left + center): + * } + * center={} + * /> + * + * 3. Doc Page (2 columns - center + right): + * } + * right={} + * /> + * + * Design Principles: + * - Responsive breakpoints match Tailwind defaults (lg: 1024px, xl: 1280px) + * - Column widths ensure visual alignment across all usage contexts + * - Flexible center column adapts to available space + * - Optional columns enable 1, 2, or 3 column layouts + */ + +import { ReactNode } from 'react'; + +/** + * Props for ThreeColumnLayout component + */ +export interface ThreeColumnLayoutProps { + /** Left column content (w-64, hidden until lg breakpoint) */ + left?: ReactNode; + + /** Center column content (flex-1, always visible) */ + center: ReactNode; + + /** Right column content (w-56, hidden until xl breakpoint) */ + right?: ReactNode; + + /** Additional classes for left column */ + leftClassName?: string; + + /** Additional classes for center column */ + centerClassName?: string; + + /** Additional classes for right column */ + rightClassName?: string; + + /** Additional classes for container */ + containerClassName?: string; + + /** Breakpoint for showing left column (default: 'lg') */ + leftBreakpoint?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'; + + /** Breakpoint for showing right column (default: 'xl') */ + rightBreakpoint?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'; +} + +/** + * Three Column Layout Component + * + * Core wireframe for consistent three-column layouts across the application. + * Handles responsive behavior and provides customization via className props. + */ +export const ThreeColumnLayout = ({ + left, + center, + right, + leftClassName = '', + centerClassName = '', + rightClassName = '', + containerClassName = '', + leftBreakpoint = 'lg', + rightBreakpoint = 'xl', +}: ThreeColumnLayoutProps) => { + // Generate responsive visibility classes + const leftHidden = `hidden ${leftBreakpoint}:block`; + const rightHidden = `hidden ${rightBreakpoint}:block`; + + return ( +
+ {/* Left Column - w-64 (256px) */} + {left && ( +
+ {left} +
+ )} + + {/* Center Column - flex-1 (flexible) */} +
+ {center} +
+ + {/* Right Column - w-56 (224px) */} + {right && ( +
+ {right} +
+ )} +
+ ); +}; diff --git a/apps/landing/src/components/shared/SubsectionNav.tsx b/apps/landing/src/components/shared/SubsectionNav.tsx index f3800a9..33ce3aa 100644 --- a/apps/landing/src/components/shared/SubsectionNav.tsx +++ b/apps/landing/src/components/shared/SubsectionNav.tsx @@ -9,17 +9,24 @@ * - Active state indicator (purple color) * - Optional API Key input on the right * - Responsive (hamburger menu on mobile) - * - Can be reused across landing app sections + * - Three-column layout matching docs structure + * - Customizable left/right slots + * + * Uses ThreeColumnLayout for consistent alignment with docs pages. + * Columns align with docs layout at all screen widths. * * Usage: * } + * rightSlot={} * /> */ -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, ReactNode } from 'react'; +import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout'; interface NavItem { label: string; @@ -33,6 +40,10 @@ interface SubsectionNavProps { ctaHref?: string; onCtaClick?: () => void; showApiKeyInput?: boolean; + /** Optional content for left column (w-64, hidden until lg) */ + leftSlot?: ReactNode; + /** Optional content for right column (w-56, hidden until xl). If not provided and showApiKeyInput is true, API key input is used. */ + rightSlot?: ReactNode; } const API_KEY_STORAGE = 'banatie_docs_api_key'; @@ -41,6 +52,8 @@ export const SubsectionNav = ({ items, currentPath, showApiKeyInput = false, + leftSlot, + rightSlot, }: SubsectionNavProps) => { const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const [apiKey, setApiKey] = useState(''); @@ -110,32 +123,8 @@ export const SubsectionNav = ({ }; }, []); - return ( -