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 */}
+
+
+
+ {/* 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
+
+
+
+
+
Body Parameters
+
+
+
+
+ Parameter
+ Type
+ Description
+ Required
+
+
+
+
+ prompt
+ string
+ Text description of the image to generate
+
+ Yes
+
+
+
+ filename
+ string
+ Name for the generated image file
+
+ Yes
+
+
+
+ aspectRatio
+ string
+
+ Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
+
+
+ No
+
+
+
+ autoEnhance
+ boolean
+ Enable automatic prompt enhancement (default: true)
+
+ No
+
+
+
+ enhancementOptions
+ object
+ Template 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
+
+
+
+
+ Code
+ Description
+
+
+
+
+ 400
+ Invalid request parameters
+
+
+ 401
+ Missing or invalid API key
+
+
+ 429
+ Rate limit exceeded
+
+
+ 500
+ Internal 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 Type
+ Limit
+ Window
+
+
+
+
+ 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-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 */}
+
+
+ );
+}
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.2 Body Parameters
+
+
+
+
+ Parameter
+ Type
+ Description
+ Required
+
+
+
+
+ prompt
+ string
+ Text description of the image to generate
+
+ Yes
+
+
+
+ filename
+ string
+ Name for the generated image file
+
+ Yes
+
+
+
+ aspectRatio
+ string
+
+ Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
+
+
+ No
+
+
+
+ autoEnhance
+ boolean
+ Enable automatic prompt enhancement (default: true)
+
+ No
+
+
+
+ enhancementOptions
+ object
+ Template 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
+
+
+
+
+ Code
+ Description
+
+
+
+
+ 400
+ Invalid request parameters
+
+
+ 401
+ Missing or invalid API key
+
+
+ 429
+ Rate limit exceeded
+
+
+ 500
+ Internal 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 Type
+ Limit
+ Window
+
+
+
+
+ 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-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 */}
+
+
+ );
+}
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
+
+
+
+
+
+
+ βοΈ
+
Body Parameters
+
+
+
+
+
+ Parameter
+ Type
+ Description
+ Required
+
+
+
+
+ prompt
+ string
+ Text description of the image to generate
+
+
+ Required
+
+
+
+
+ filename
+ string
+ Name for the generated image file
+
+
+ Required
+
+
+
+
+ aspectRatio
+ string
+
+ Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
+
+
+
+ Optional
+
+
+
+
+ autoEnhance
+ boolean
+ Enable automatic prompt enhancement (default: true)
+
+
+ Optional
+
+
+
+
+ enhancementOptions
+ object
+ Template 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
+
+
+
+
+
+ Code
+ Description
+
+
+
+
+ 400
+ Invalid request parameters
+
+
+ 401
+ Missing or invalid API key
+
+
+ 429
+ Rate limit exceeded
+
+
+ 500
+ Internal 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 Type
+ Limit
+ Window
+
+
+
+
+ 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 (
+
+
+ {items.map((item, index) => {
+ const isLast = index === items.length - 1;
+
+ return (
+
+ {item.href && !isLast ? (
+
+ {item.label}
+
+ ) : (
+
+ {item.label}
+
+ )}
+
+ {!isLast && (
+
+
+
+ )}
+
+ );
+ })}
+
+
+ );
+};
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}
+ )}
+
+
+ {copied ? 'Copied!' : 'Copy'}
+
+
+
+ {/* 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 (
+
+ {/* Logo/Title */}
+
+
Documentation
+
Variant A: Clean
+
+
+ {/* Navigation Items */}
+
+ {navigationItems.map((item) => {
+ const hasChildren = item.children && item.children.length > 0;
+ const expanded = isExpanded(item.label);
+ const active = isActive(item.href);
+
+ return (
+
+ {/* Parent Item */}
+
+
+ {/* Children Items */}
+ {hasChildren && expanded && (
+
+ {item.children!.map((child) => {
+ const childActive = isActive(child.href);
+ return (
+
+
+ {child.label}
+
+
+ );
+ })}
+
+ )}
+
+ );
+ })}
+
+
+ {/* Bottom Links */}
+
+
+ );
+};
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 (
+
+
+ On This Page
+
+
+
+ {items.map((item) => {
+ const isActive = activeId === item.id;
+ const isH3 = item.level === 3;
+
+ return (
+
+ scrollToSection(item.id)}
+ className={`
+ flex items-start gap-2 text-left w-full transition-colors group
+ ${isActive ? 'text-purple-400' : 'text-gray-500 hover:text-gray-300'}
+ `}
+ >
+ {/* Indicator dot */}
+
+ {item.text}
+
+
+ );
+ })}
+
+
+ );
+};
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) => (
+ setLanguage(lang)}
+ className={`px-3 py-1 text-xs rounded transition-colors ${
+ language === lang
+ ? 'bg-slate-700 text-white'
+ : 'text-gray-400 hover:text-white'
+ }`}
+ >
+ {lang === 'javascript' ? 'JavaScript' : lang.charAt(0).toUpperCase() + lang.slice(1)}
+
+ ))}
+
+
+ Copy
+
+
+
+ {/* Code Display */}
+
+
+ {/* Try It Button */}
+
+
+ {isExecuting ? 'Executing...' : 'Try It'}
+
+
+
+ {/* 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 (
+
+ {/* Header */}
+
+
Documentation
+
Variant B: Dense
+
+
+ {/* Search (placeholder) */}
+
+
+ {/* Navigation Tree */}
+
+
+ {/* Bottom Links */}
+
+
+ );
+};
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 (
+
+ {/* Header with Progress */}
+
+
+ On This Page
+
+ {/* Progress Bar */}
+
+
{Math.round(scrollProgress)}% read
+
+
+ {/* TOC Items with Numbers */}
+
+ {items.map((item, index) => {
+ const isActive = activeId === item.id;
+ const isH3 = item.level === 3;
+ const number = isH3 ? `${Math.floor(index / 2)}.${index % 2 + 1}` : `${index + 1}`;
+
+ return (
+
+ scrollToSection(item.id)}
+ className={`
+ flex items-start gap-2 text-left w-full transition-colors py-1 px-2 rounded-md
+ ${isActive ? 'bg-purple-500/20 text-purple-300 font-semibold' : 'text-gray-500 hover:text-gray-300 hover:bg-slate-800/30'}
+ `}
+ >
+ {/* Section number */}
+
+ {isH3 ? 'β³' : number}
+
+ {item.text}
+
+
+ );
+ })}
+
+
+ {/* Back to Top Button */}
+ {scrollProgress > 20 && (
+ window.scrollTo({ top: 0, behavior: 'smooth' })}
+ className="mt-6 w-full px-3 py-2 text-xs bg-slate-800/50 hover:bg-slate-800 text-gray-400 hover:text-white rounded-lg transition-colors flex items-center justify-center gap-2"
+ >
+
+
+
+ Back to top
+
+ )}
+
+ );
+};
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 */}
+
+
+ API Key:
+ 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) => (
+ setLanguage(lang)}
+ className={`px-2 py-1 text-xs rounded transition-colors ${
+ language === lang ? 'bg-slate-700 text-white' : 'text-gray-500 hover:text-white'
+ }`}
+ >
+ {lang === 'javascript' ? 'JS' : lang.toUpperCase()}
+
+ ))}
+
+
+ Copy
+
+
+
+ {/* Code Display */}
+
+
+
+ {/* Right Column: Response */}
+
+
+
Response
+
+
+
+ {error ? (
+
+ {error}
+
+ ) : response ? (
+
+ {JSON.stringify(response, null, 2)}
+
+ ) : (
+
+ Click "Execute Request" to see the response
+
+ )}
+
+
+
+
+ {/* Try It Button - Full Width */}
+
+ {isExecuting ? 'Executing...' : 'βΆ Execute Request'}
+
+
+
{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 (
+
+ {/* Header - Colorful */}
+
+
+ π
+
Documentation
+
+
Variant C: Modern & Visual
+
+
+ {/* Search (placeholder) - Colorful border */}
+
+
+ {/* Navigation Cards */}
+
+
+ {/* Bottom Links - Colorful Card */}
+
+
+ );
+};
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 (
+
+ {/* Floating Card with Gradient Border */}
+
+ {/* Header with Icon and Progress */}
+
+
+ π
+
+ On This Page
+
+
+
+ {/* Rainbow Progress Bar */}
+
+
+
{Math.round(scrollProgress)}% complete
+
+ {items.findIndex((item) => item.id === activeId) + 1}/{items.length}
+
+
+
+
+ {/* TOC Items with Colorful Dots */}
+
+ {items.map((item, index) => {
+ const isActive = activeId === item.id;
+ const isH3 = item.level === 3;
+ const color = getColorForIndex(index);
+ const cleanText = item.text.replace(/^\d+\.?\s*/, '');
+
+ return (
+
+ scrollToSection(item.id)}
+ className={`
+ flex items-start gap-3 text-left w-full transition-all duration-300 py-2 px-3 rounded-lg
+ ${
+ isActive
+ ? 'bg-gradient-to-br from-purple-500/20 to-cyan-500/20 text-white font-semibold shadow-lg scale-105'
+ : 'text-gray-400 hover:text-white hover:bg-slate-800/50 hover:scale-102'
+ }
+ `}
+ >
+ {/* Colorful Dot Indicator */}
+
+ {isH3 ? (
+ β³
+ ) : (
+
+ )}
+
+
+ {/* Text */}
+ {cleanText}
+
+
+ );
+ })}
+
+
+ {/* Back to Top Button - Colorful */}
+ {scrollProgress > 20 && (
+
+
window.scrollTo({ top: 0, behavior: 'smooth' })}
+ className="w-full px-4 py-3 text-sm bg-gradient-to-r from-purple-600/30 to-cyan-600/30 hover:from-purple-600/50 hover:to-cyan-600/50 text-white rounded-xl transition-all duration-300 flex items-center justify-center gap-2 border-2 border-purple-500/40 hover:border-purple-500/60 shadow-lg hover:shadow-purple-500/30 hover:scale-105"
+ >
+
+
+
+ Back to top
+
+
+ )}
+
+
+ {/* Fun Floating Tip Card */}
+
+
+
π‘
+
+ Tip: Click any item to jump directly to that section!
+
+
+
+
+ );
+};
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 */}
+
+
+ π
+ Your API Key
+
+
+
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}
+
+
setIsExpanded(!isExpanded)}
+ className="px-4 py-2 bg-cyan-600/20 hover:bg-cyan-600/30 text-cyan-400 rounded-lg transition-all text-sm font-semibold border-2 border-cyan-500/40 hover:border-cyan-500/60"
+ >
+ {isExpanded ? 'β Close' : 'βΆ Expand'}
+
+
+
+
+ {/* 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 (
+ setLanguage(lang)}
+ className={`px-4 py-2 text-sm rounded-xl font-semibold transition-all border-2 ${
+ language === lang
+ ? color === 'purple'
+ ? 'bg-purple-500/30 text-white border-purple-500/60 shadow-lg shadow-purple-500/30'
+ : color === 'cyan'
+ ? 'bg-cyan-500/30 text-white border-cyan-500/60 shadow-lg shadow-cyan-500/30'
+ : 'bg-amber-500/30 text-white border-amber-500/60 shadow-lg shadow-amber-500/30'
+ : 'bg-slate-800/30 text-gray-400 border-slate-700 hover:border-slate-600 hover:text-white'
+ }`}
+ >
+ {lang === 'javascript' ? 'JS' : lang.toUpperCase()}
+
+ );
+ })}
+
+
+ {/* Code Display - Gradient Border */}
+
+
+ Code Example
+
+ π Copy
+
+
+
+
+
+
+ {/* Right: Response */}
+
+
+ π¦
+ Response
+
+
+
+
+ {response && (
+
+ {response.success ? 'β Success' : 'β Error'}
+
+ )}
+
+
+ {error ? (
+
+ ) : response ? (
+
+ {JSON.stringify(response, null, 2)}
+
+ ) : (
+
+
+
π
+
+ Click "Test Now" below to see the response
+
+
+
+ )}
+
+
+
+
+
+ {/* Large Test Now Button */}
+
+
+ {isExecuting ? (
+ <>
+ β‘
+ Executing...
+ >
+ ) : (
+ <>
+ β‘
+ Test Now
+ >
+ )}
+
+
{description}
+
+
+
+ );
+};