Compare commits

..

No commits in common. "da6887d41c6dbaaee6368455e09776144a737b89" and "7368d287e9edf9bf0a30928f9f6fb3cd791bc55b" have entirely different histories.

45 changed files with 5859 additions and 2854 deletions

View File

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

View File

@ -6,8 +6,7 @@
"dev": "next dev -p 3010",
"build": "next build",
"start": "next start",
"deploy": "cp -r out/* /var/www/banatie.app/",
"typecheck": "tsc --noEmit"
"deploy": "cp -r out/* /var/www/banatie.app/"
},
"dependencies": {
"react": "19.1.0",

View File

@ -1,25 +1,25 @@
'use client';
/**
* API Reference: Text to Image
* API Reference: Text to Image - Final Variant
*
* 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)
* 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';
import { DocPage } from '@/components/docs/layout/DocPage';
import { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget';
import {
Hero,
SectionHeader,
InlineCode,
EndpointCard,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
@ -31,6 +31,12 @@ const tocItems = [
{ 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)' },
@ -40,70 +46,67 @@ const parameters = [
export default function TextToImageAPIPage() {
return (
<DocPage
breadcrumbItems={[
<>
{/* Subsection Navigation with API Key Input */}
<SubsectionNav
items={navItems}
currentPath="/docs/final/api/text-to-image"
showApiKeyInput={true}
/>
<DocsLayoutFinal
sidebar={<DocsSidebarFinal currentPath="/docs/final/api/text-to-image" />}
toc={<DocsTOCFinal items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/api' },
{ label: 'API Reference', href: '/docs/final/api' },
{ label: 'Text to Image' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/upload',
title: 'Upload API',
description: 'Learn how to upload reference images for image-to-image generation.',
accent: 'primary',
},
{
href: '/docs/guides/error-handling',
title: 'Error Handling',
description: 'Best practices for handling errors and retries in production.',
accent: 'secondary',
},
],
}}
>
/>
{/* Hero Section */}
<Hero
title="Text to Image"
subtitle="Generate high-quality images from text prompts using AI-powered models."
/>
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Text to Image</h1>
<p className="text-xl text-gray-400 leading-relaxed">
Generate high-quality images from text prompts using AI-powered models.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview">
Overview
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<TipBox variant="compact" type="info">
<strong>Tip:</strong> Enable <InlineCode>autoEnhance</InlineCode>
<strong>Tip:</strong> Enable <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">autoEnhance</code>
to let AI improve your prompts for better image quality.
</TipBox>
</section>
{/* Endpoint */}
<section id="endpoint" className="mb-12">
<SectionHeader level={2} id="endpoint">
Endpoint
</SectionHeader>
<EndpointCard
method="POST"
endpoint="/api/text-to-image"
baseUrl="https://api.banatie.com"
/>
<h2 className="text-3xl font-bold text-white mb-4">Endpoint</h2>
<div className="p-4 bg-slate-900/50 border border-slate-700 rounded-xl">
<div className="flex items-center gap-3 mb-2">
<span className="px-3 py-1 bg-green-600/20 text-green-400 text-xs font-bold rounded">
POST
</span>
<code className="text-sm text-white">/api/text-to-image</code>
</div>
<p className="text-xs text-gray-400">
Base URL: <code className="text-purple-400">https://api.banatie.com</code>
</p>
</div>
</section>
{/* Parameters */}
<section id="parameters" className="mb-12">
<SectionHeader level={2} id="parameters" className="mb-6">
Parameters
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-6">Parameters</h2>
<p className="text-gray-300 leading-relaxed mb-6">
All parameters should be sent in the request body as JSON.
</p>
@ -111,7 +114,7 @@ export default function TextToImageAPIPage() {
<Table
headers={['Parameter', 'Type', 'Required', 'Description']}
rows={parameters.map((param) => [
<InlineCode key="name">{param.name}</InlineCode>,
<code key="name" className="text-purple-400">{param.name}</code>,
<span key="type" className="text-cyan-400">{param.type}</span>,
<span key="required" className={param.required ? 'text-green-400' : 'text-gray-500'}>
{param.required ? 'Yes' : 'No'}
@ -122,18 +125,16 @@ export default function TextToImageAPIPage() {
<div className="mt-6">
<TipBox variant="compact" type="info">
<strong>Default Values:</strong> If not specified, <InlineCode>filename</InlineCode> is
auto-generated, <InlineCode>aspectRatio</InlineCode> defaults
to "1:1", and <InlineCode>autoEnhance</InlineCode> is false.
<strong>Default Values:</strong> If not specified, <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">filename</code> is
auto-generated, <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">aspectRatio</code> defaults
to "1:1", and <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">autoEnhance</code> is false.
</TipBox>
</div>
</section>
{/* Response */}
<section id="response" className="mb-12">
<SectionHeader level={2} id="response" className="mb-4">
Response
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-4">Response</h2>
<p className="text-gray-300 leading-relaxed mb-4">
On success, the API returns a JSON object containing the generated image URL and metadata.
</p>
@ -163,9 +164,7 @@ export default function TextToImageAPIPage() {
{/* Error Codes */}
<section id="error-codes" className="mb-12">
<SectionHeader level={2} id="error-codes" className="mb-6">
Error Codes
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-6">Error Codes</h2>
<p className="text-gray-300 leading-relaxed mb-6">
The API uses standard HTTP status codes and returns descriptive error messages.
</p>
@ -174,22 +173,22 @@ export default function TextToImageAPIPage() {
headers={['Status Code', 'Error Type', 'Description']}
rows={[
[
<InlineCode key="code" color="error">400</InlineCode>,
<code key="code" className="text-red-400">400</code>,
'Bad Request',
'Missing or invalid parameters in the request body',
],
[
<InlineCode key="code" color="error">401</InlineCode>,
<code key="code" className="text-red-400">401</code>,
'Unauthorized',
'Missing or invalid API key in X-API-Key header',
],
[
<InlineCode key="code" color="error">429</InlineCode>,
<code key="code" className="text-red-400">429</code>,
'Rate Limit',
'Too many requests. Check rate limit headers for retry timing',
],
[
<InlineCode key="code" color="error">500</InlineCode>,
<code key="code" className="text-red-400">500</code>,
'Server Error',
'Internal server error. Contact support if persists',
],
@ -206,14 +205,12 @@ export default function TextToImageAPIPage() {
{/* Interactive Widget */}
<section id="interactive" className="mb-12">
<SectionHeader level={2} id="interactive" className="mb-4">
Try It Live
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-4">Try It Live</h2>
<p className="text-gray-300 leading-relaxed mb-6">
Test the API directly from this page. Enter your API key and customize the parameters below.
</p>
<InteractiveAPIWidget
<InteractiveAPIWidgetFinal
endpoint="/api/text-to-image"
method="POST"
description="Generate an image from a text prompt"
@ -221,6 +218,37 @@ export default function TextToImageAPIPage() {
/>
</section>
</DocPage>
{/* Next Steps */}
<section id="next-steps" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
<div className="grid md:grid-cols-2 gap-4">
<a
href="/docs/final/api/upload"
className="p-5 bg-gradient-to-br from-purple-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-purple-500/40 transition-colors group"
>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
Upload API
</h3>
<p className="text-sm text-gray-400">
Learn how to upload reference images for image-to-image generation.
</p>
</a>
<a
href="/docs/final/guides/error-handling"
className="p-5 bg-gradient-to-br from-cyan-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-cyan-500/40 transition-colors group"
>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
Error Handling
</h3>
<p className="text-sm text-gray-400">
Best practices for handling errors and retries in production.
</p>
</a>
</div>
</section>
</DocsLayoutFinal>
</>
);
}

View File

@ -1,23 +1,24 @@
'use client';
/**
* Authentication Guide
* Authentication Guide - Final Variant
*
* 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)
* 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';
import { DocPage } from '@/components/docs/layout/DocPage';
import {
Hero,
SectionHeader,
InlineCode,
} from '@/components/docs/blocks';
const tocItems = [
{ id: 'overview', text: 'Overview', level: 2 },
@ -30,53 +31,56 @@ const tocItems = [
{ 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 (
<DocPage
breadcrumbItems={[
<>
{/* Subsection Navigation */}
<SubsectionNav
items={navItems}
currentPath="/docs/final/guides/authentication"
ctaText="Join Beta"
ctaHref="/signup"
/>
<DocsLayoutFinal
sidebar={<DocsSidebarFinal currentPath="/docs/final/guides/authentication" />}
toc={<DocsTOCFinal items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Guides', href: '/docs/guides' },
{ label: 'Guides', href: '/docs/final/guides' },
{ label: 'Authentication' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/text-to-image',
title: 'Start Generating Images',
description: 'Explore the Text to Image API and start building your integration.',
accent: 'primary',
},
{
href: '/docs/guides/error-handling',
title: 'Error Handling Guide',
description: 'Learn how to handle authentication errors and implement retry logic.',
accent: 'secondary',
},
],
}}
>
/>
{/* Hero Section */}
<Hero
title="Authentication"
subtitle="Learn how to authenticate with the Banatie API using API keys, manage rate limits, and implement security best practices."
/>
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Authentication</h1>
<p className="text-xl text-gray-400 leading-relaxed">
Learn how to authenticate with the Banatie API using API keys, manage rate limits, and
implement security best practices.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-12">
<SectionHeader level={2} id="overview" className="mb-4">
Overview
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie uses API keys to authenticate requests. All API endpoints require authentication
via the <InlineCode>X-API-Key</InlineCode> header.
via the <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">X-API-Key</code> header.
API keys are tied to organizations and projects, providing fine-grained access control.
</p>
<TipBox variant="compact" type="info">
<strong>Quick Start:</strong> New to API authentication? Check out our{' '}
<a href="/docs" className="text-purple-400 hover:underline">
<a href="/docs/final" className="text-purple-400 hover:underline">
Getting Started guide
</a>{' '}
for a step-by-step walkthrough.
@ -85,14 +89,10 @@ export default function AuthenticationGuidePage() {
{/* API Keys */}
<section id="api-keys" className="mb-12">
<SectionHeader level={2} id="api-keys" className="mb-6">
API Keys
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-6">API Keys</h2>
<div id="key-types" className="mb-8">
<SectionHeader level={3} id="key-types" className="mb-4">
Key Types
</SectionHeader>
<h3 className="text-xl font-semibold text-white mb-4">Key Types</h3>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie supports two types of API keys, each with different permissions and use cases:
</p>
@ -101,13 +101,13 @@ export default function AuthenticationGuidePage() {
headers={['Key Type', 'Permissions', 'Expiration', 'Use Case']}
rows={[
[
<InlineCode key="type">Master Key</InlineCode>,
<code key="type" className="text-purple-400">Master Key</code>,
'Full admin access, can create/revoke keys',
<span key="exp" className="text-green-400">Never expires</span>,
'Server-side admin operations, key management',
],
[
<InlineCode key="type" color="success">Project Key</InlineCode>,
<code key="type" className="text-cyan-400">Project Key</code>,
'Image generation only',
<span key="exp" className="text-amber-400">90 days</span>,
'Application integration, API requests',
@ -126,9 +126,7 @@ export default function AuthenticationGuidePage() {
</div>
<div id="creating-keys" className="mb-8">
<SectionHeader level={3} id="creating-keys" className="mb-4">
Creating Keys
</SectionHeader>
<h3 className="text-xl font-semibold text-white mb-4">Creating Keys</h3>
<p className="text-gray-300 leading-relaxed mb-4">
For first-time setup, use the bootstrap endpoint to create your initial master key:
</p>
@ -183,11 +181,9 @@ curl -X POST https://api.banatie.com/api/admin/keys \\
{/* Using API Keys */}
<section id="using-keys" className="mb-12">
<SectionHeader level={2} id="using-keys" className="mb-4">
Using API Keys
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-4">Using API Keys</h2>
<p className="text-gray-300 leading-relaxed mb-4">
Include your API key in the <InlineCode>X-API-Key</InlineCode> header
Include your API key in the <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">X-API-Key</code> header
with every request:
</p>
@ -208,16 +204,14 @@ curl -X POST https://api.banatie.com/api/text-to-image \\
<TipBox variant="compact" type="info">
<strong>Environment Variables:</strong> Store API keys in environment variables, not
hardcoded in your application. Example:{' '}
<InlineCode>BANATIE_API_KEY</InlineCode>
<code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">BANATIE_API_KEY</code>
</TipBox>
</div>
</section>
{/* Rate Limits */}
<section id="rate-limits" className="mb-12">
<SectionHeader level={2} id="rate-limits" className="mb-6">
Rate Limits
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-6">Rate Limits</h2>
<p className="text-gray-300 leading-relaxed mb-6">
API keys are subject to rate limits to ensure fair usage and system stability. Limits
vary by key type and plan tier:
@ -227,19 +221,19 @@ curl -X POST https://api.banatie.com/api/text-to-image \\
headers={['Key Type', 'Rate Limit', 'Reset Window', 'Upgrade Available']}
rows={[
[
<InlineCode key="type">Master Key</InlineCode>,
<code key="type" className="text-purple-400">Master Key</code>,
<span key="limit" className="text-green-400">Unlimited</span>,
'N/A',
'N/A',
],
[
<InlineCode key="type" color="success">Project Key (Free)</InlineCode>,
<code key="type" className="text-cyan-400">Project Key (Free)</code>,
<span key="limit" className="text-amber-400">100 requests/hour</span>,
'1 hour rolling',
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
],
[
<InlineCode key="type" color="success">Project Key (Pro)</InlineCode>,
<code key="type" className="text-cyan-400">Project Key (Pro)</code>,
<span key="limit" className="text-green-400">1,000 requests/hour</span>,
'1 hour rolling',
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
@ -249,7 +243,7 @@ curl -X POST https://api.banatie.com/api/text-to-image \\
<div className="mt-6">
<p className="text-gray-300 leading-relaxed mb-4">
When you exceed rate limits, the API returns a <InlineCode color="error">429 Too Many Requests</InlineCode> status.
When you exceed rate limits, the API returns a <code className="px-1.5 py-0.5 bg-slate-800 rounded text-red-400">429 Too Many Requests</code> status.
Check the response headers for retry timing:
</p>
@ -272,9 +266,7 @@ X-RateLimit-Reset: 1704153600
{/* Security Best Practices */}
<section id="security" className="mb-12">
<SectionHeader level={2} id="security" className="mb-6">
Security Best Practices
</SectionHeader>
<h2 className="text-3xl font-bold text-white mb-6">Security Best Practices</h2>
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Critical Security Guidelines:</strong>
@ -308,6 +300,37 @@ curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\
</div>
</section>
</DocPage>
{/* Next Steps */}
<section id="next-steps" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
<div className="grid md:grid-cols-2 gap-4">
<a
href="/docs/final/api/text-to-image"
className="p-5 bg-gradient-to-br from-purple-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-purple-500/40 transition-colors group"
>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
Start Generating Images
</h3>
<p className="text-sm text-gray-400">
Explore the Text to Image API and start building your integration.
</p>
</a>
<a
href="/docs/final/guides/error-handling"
className="p-5 bg-gradient-to-br from-cyan-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-cyan-500/40 transition-colors group"
>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
Error Handling Guide
</h3>
<p className="text-sm text-gray-400">
Learn how to handle authentication errors and implement retry logic.
</p>
</a>
</div>
</section>
</DocsLayoutFinal>
</>
);
}

View File

@ -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 */}
<SubsectionNav
items={navItems}
currentPath="/docs/final"
ctaText="Join Beta"
ctaHref="/signup"
/>
<DocsLayoutFinal
sidebar={<DocsSidebarFinal currentPath="/docs/final" />}
toc={<DocsTOCFinal items={tocItems} />}
>
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
{/* Hero Section */}
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Getting Started</h1>
<p className="text-xl text-gray-400 leading-relaxed">
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
generation into your applications in minutes.
</p>
</div>
{/* Introduction */}
<section id="introduction" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Introduction</h2>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<p className="text-gray-300 leading-relaxed mb-6">
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.
</p>
{/* Compact Tip Box */}
<TipBox variant="compact" type="info">
<strong>New to API integration?</strong> Start with our{' '}
<a href="/docs/final/examples" className="text-purple-400 hover:underline">
code examples
</a>{' '}
to see common use cases in action.
</TipBox>
</section>
{/* Quick Start */}
<section id="quick-start" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Quick Start</h2>
<div id="installation" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-3">Installation</h3>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<CodeBlock
code={`# Using npm (JavaScript/TypeScript)
npm install @banatie/sdk
# Using pip (Python)
pip install banatie
# Using Go
go get github.com/banatie/sdk-go`}
language="bash"
filename="Installation"
/>
</div>
<div id="authentication" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-3">Authentication</h3>
<p className="text-gray-300 leading-relaxed mb-4">
All API requests require an API key. You can create an API key from your dashboard or
using the bootstrap endpoint for initial setup.
</p>
{/* Prominent Tip Box for Security Warning */}
<div className="mb-6">
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Security Best Practice:</strong> 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.
</TipBox>
</div>
<CodeBlock
code={`# Create your first API key (one-time bootstrap)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Save the returned key securely
export BANATIE_API_KEY="bnt_your_key_here"`}
language="bash"
filename="Get API Key"
/>
</div>
</section>
{/* First Request */}
<section id="first-request" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Your First Request</h2>
<p className="text-gray-300 leading-relaxed mb-6">
Let's generate your first image! This example uses curl, but you can use any HTTP client
or our SDKs.
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"filename": "mountain_sunset",
"aspectRatio": "16:9",
"autoEnhance": true
}'`}
language="bash"
filename="Generate Image"
/>
<div className="mt-6">
<p className="text-sm font-semibold text-gray-300 mb-3">Expected Response:</p>
<div className="relative p-4 bg-green-500/5 border border-green-500/30 rounded-xl shadow-lg shadow-green-500/10">
<div className="absolute top-3 right-3">
<span className="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded-full">
200 Success
</span>
</div>
<pre className="text-xs text-gray-300 overflow-x-auto mt-6">
<code>{`{
"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..."
}
}
}`}</code>
</pre>
</div>
</div>
</section>
{/* Next Steps - Simplified to 2 Cards */}
<section id="next-steps" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
<p className="text-gray-300 leading-relaxed mb-6">
Now that you have generated your first image, explore these resources to build more advanced integrations:
</p>
<div className="grid md:grid-cols-2 gap-4">
<a
href="/docs/final/api/text-to-image"
className="p-5 bg-gradient-to-br from-purple-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-purple-500/40 transition-colors group"
>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
API Reference
</h3>
<p className="text-sm text-gray-400">
Explore all available endpoints, parameters, and response formats.
</p>
</a>
<a
href="/docs/final/guides/authentication"
className="p-5 bg-gradient-to-br from-cyan-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-cyan-500/40 transition-colors group"
>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
Authentication Guide
</h3>
<p className="text-sm text-gray-400">
Learn about API keys, rate limits, and security best practices.
</p>
</a>
</div>
</section>
</DocsLayoutFinal>
</>
);
}

View File

@ -1,48 +1,22 @@
'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 { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
/**
* Root Documentation Layout
*
* Provides shared layout elements for all documentation pages:
* - SubsectionNav at the top
* - Three-column layout (left sidebar + content + right TOC via DocPage)
* - Background gradients
*
* 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 via DocPage)
* Simple wrapper for all documentation pages.
* Each variant handles its own layout/navigation.
*
* Features:
* - Animated gradient background matching landing page
* - Automatic active page detection via pathname
* - Responsive layout (mobile tablet desktop)
* - Consistent background gradient matching landing page
* - No navigation/sidebars at this level
* - Children render their own layouts
*/
interface DocsRootLayoutProps {
children: ReactNode;
}
const navItems = [
{ label: 'Documentation', href: '/docs' },
{ label: 'Demo', href: '/demo' },
{ label: 'Examples', href: '/docs/examples' },
];
export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
const pathname = usePathname();
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
{/* Animated gradient background (matching landing page) */}
@ -51,25 +25,8 @@ export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
</div>
{/* Subsection Navigation */}
<SubsectionNav
items={navItems}
currentPath={pathname}
ctaText="Join Beta"
ctaHref="/signup"
/>
{/* Three-column Documentation Layout */}
<div className="relative z-10">
<ThreeColumnLayout
left={
<div className="border-r border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
<DocsSidebar currentPath={pathname} />
</div>
}
center={children}
/>
</div>
{/* Content */}
<div className="relative z-10">{children}</div>
</div>
);
}

View File

@ -1,196 +1,376 @@
'use client';
/**
* Getting Started Page - Production Documentation
* Documentation Variants Comparison Page
*
* 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)
* 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
*/
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,
} from '@/components/docs/blocks';
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 GettingStartedPage() {
export default function DocsIndexPage() {
return (
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Getting Started' },
]}
tocItems={tocItems}
nextSteps={{
description:
'Now that you have generated your first image, explore these resources to build more advanced integrations:',
links: [
{
href: '/docs/api/text-to-image',
title: 'API Reference',
description: 'Explore all available endpoints, parameters, and response formats.',
accent: 'primary',
},
{
href: '/docs/guides/authentication',
title: 'Authentication Guide',
description: 'Learn about API keys, rate limits, and security best practices.',
accent: 'secondary',
},
],
}}
<div className="min-h-screen">
{/* Header with back to home */}
<div className="border-b border-white/10 bg-slate-950/80 backdrop-blur-sm">
<div className="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
<a
href="/"
className="flex items-center gap-2 text-gray-400 hover:text-white transition-colors"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
<span className="text-sm">Back to Home</span>
</a>
<div className="text-sm text-gray-500">Choose Your Documentation Style</div>
</div>
</div>
<div className="max-w-7xl mx-auto px-6 py-16">
{/* Hero Section */}
<Hero
title="Getting Started"
subtitle="Welcome to the Banatie API documentation. Learn how to integrate AI-powered image generation into your applications in minutes."
/>
{/* Introduction */}
<section id="introduction" className="mb-12">
<SectionHeader level={2} id="introduction">
Introduction
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
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.
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/20 to-cyan-500/20 border-2 border-purple-500/40 mb-6">
<span className="text-2xl">📚</span>
<span className="text-sm font-bold text-white">DOCUMENTATION</span>
</div>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6">
Choose Your Documentation Style
</h1>
<p className="text-xl text-gray-400 max-w-3xl mx-auto leading-relaxed">
We've created three distinct documentation designs. Pick the style that works best for
yousame content, different presentation.
</p>
<p className="text-gray-300 leading-relaxed mb-6">
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.
</p>
{/* Compact Tip Box */}
<TipBox variant="compact" type="info">
<strong>New to API integration?</strong> Start with our{' '}
<a href="/docs/examples" className="text-purple-400 hover:underline">
code examples
</a>{' '}
to see common use cases in action.
</TipBox>
</section>
{/* Quick Start */}
<section id="quick-start" className="mb-12">
<SectionHeader level={2} id="quick-start" className="mb-6">
Quick Start
</SectionHeader>
<div id="installation" className="mb-8">
<SectionHeader level={3} id="installation">
Installation
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<CodeBlock
code={`# Using npm (JavaScript/TypeScript)
npm install @banatie/sdk
# Using pip (Python)
pip install banatie
# Using Go
go get github.com/banatie/sdk-go`}
language="bash"
filename="Installation"
/>
</div>
<div id="authentication" className="mb-8">
<SectionHeader level={3} id="authentication">
Authentication
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
All API requests require an API key. You can create an API key from your dashboard or
using the bootstrap endpoint for initial setup.
{/* Final Variant - Recommended */}
<div className="mb-12">
<div className="text-center mb-6">
<span className="inline-block px-4 py-1.5 rounded-full bg-gradient-to-r from-purple-500 to-cyan-500 text-white text-sm font-semibold mb-2">
RECOMMENDED
</span>
<h2 className="text-2xl font-bold text-white">Production-Ready Design</h2>
</div>
<a
href="/docs/final"
className="group block p-10 bg-gradient-to-br from-purple-500/20 via-cyan-500/20 to-purple-500/20 border-4 border-purple-500/50 rounded-3xl hover:border-purple-500/80 transition-all duration-300 shadow-2xl hover:shadow-purple-500/40 hover:scale-[1.02]"
>
<div className="flex flex-col md:flex-row items-center gap-8">
<div className="flex-shrink-0 text-6xl"></div>
<div className="flex-1 text-center md:text-left">
<h3 className="text-3xl font-bold text-white mb-3 group-hover:text-purple-300 transition-colors">
Final Variant
</h3>
<h4 className="text-xl font-semibold text-purple-300 mb-4">
Best of All Worlds - Clean, Enhanced & Production-Ready
</h4>
<p className="text-base text-gray-300 mb-6 leading-relaxed max-w-3xl">
The perfect combination: Variant A's clean aesthetic enhanced with expandable code blocks, success/error response styling, clickable image URLs, two tip box styles, enhanced tables, and simplified navigation. This is the variant we recommend for production use.
</p>
{/* Prominent Tip Box for Security Warning */}
<div className="mb-6">
<TipBox variant="prominent" type="warning">
<strong className="text-amber-300">Security Best Practice:</strong> 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.
</TipBox>
</div>
<CodeBlock
code={`# Create your first API key (one-time bootstrap)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Save the returned key securely
export BANATIE_API_KEY="bnt_your_key_here"`}
language="bash"
filename="Get API Key"
<div className="grid md:grid-cols-3 gap-4 mb-6">
<div className="flex items-center gap-2 text-sm text-gray-300">
<svg className="w-5 h-5 text-purple-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Clean Variant A base</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-300">
<svg className="w-5 h-5 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Expandable code blocks</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-300">
<svg className="w-5 h-5 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Success/error styling</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-300">
<svg className="w-5 h-5 text-purple-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Two tip box styles</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-300">
<svg className="w-5 h-5 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Enhanced tables</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-300">
<svg className="w-5 h-5 text-green-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Reusable navigation</span>
</div>
</div>
</section>
{/* First Request */}
<section id="first-request" className="mb-12">
<SectionHeader level={2} id="first-request">
Your First Request
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Let's generate your first image! This example uses curl, but you can use any HTTP client
or our SDKs.
<div className="flex items-center justify-center md:justify-start gap-3 text-purple-300 text-lg font-bold group-hover:gap-4 transition-all">
<span>Explore Final Variant</span>
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M9 5l7 7-7 7" />
</svg>
</div>
</div>
</div>
</a>
</div>
{/* Other Variants for Reference */}
<div className="text-center mb-8">
<h3 className="text-xl font-semibold text-gray-400 mb-2">Other Variants (Reference)</h3>
<p className="text-sm text-gray-500">
Explore the original variants that inspired the final design
</p>
</div>
{/* Variant Cards */}
<div className="grid md:grid-cols-3 gap-8 mb-16">
{/* Variant A: Clean & Minimal */}
<a
href="/docs/variant-a"
className="group p-8 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl hover:border-purple-500/60 transition-all duration-300 shadow-xl hover:shadow-purple-500/30 hover:scale-105"
>
<div className="text-4xl mb-6"></div>
<h2 className="text-2xl font-bold text-white mb-4 group-hover:text-purple-400 transition-colors">
Variant A
</h2>
<h3 className="text-lg font-semibold text-purple-400 mb-4">Clean & Minimal</h3>
<p className="text-sm text-gray-400 mb-6 leading-relaxed">
Vercel-inspired spacious layout with generous whitespace, focused reading experience,
and subtle visual hierarchy.
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"filename": "mountain_sunset",
"aspectRatio": "16:9",
"autoEnhance": true
}'`}
language="bash"
filename="Generate Image"
/>
<div className="mt-6">
<p className="text-sm font-semibold text-gray-300 mb-3">Expected Response:</p>
<ResponseBlock
status="success"
statusCode={200}
statusLabel="✓ 200 Success"
content={`{
"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..."
}
}
}`}
<div className="space-y-3 mb-6">
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-purple-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Wide margins, comfortable reading</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-purple-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Subtle borders and minimal design</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-purple-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Focus on content clarity</span>
</div>
</div>
</section>
</DocPage>
<div className="flex items-center gap-2 text-purple-400 font-semibold group-hover:gap-3 transition-all">
<span>Explore Variant A</span>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</a>
{/* Variant B: Dense & Information-Rich */}
<a
href="/docs/variant-b"
className="group p-8 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl hover:border-cyan-500/60 transition-all duration-300 shadow-xl hover:shadow-cyan-500/30 hover:scale-105"
>
<div className="text-4xl mb-6">📊</div>
<h2 className="text-2xl font-bold text-white mb-4 group-hover:text-cyan-400 transition-colors">
Variant B
</h2>
<h3 className="text-lg font-semibold text-cyan-400 mb-4">Dense & Information-Rich</h3>
<p className="text-sm text-gray-400 mb-6 leading-relaxed">
Next.js docs-inspired compact layout with section numbers, nested navigation, and
maximum information density per screen.
</p>
<div className="space-y-3 mb-6">
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Compact spacing, more content visible</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Section numbers (1., 2.1, etc.)</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Hierarchical nested tree navigation</span>
</div>
</div>
<div className="flex items-center gap-2 text-cyan-400 font-semibold group-hover:gap-3 transition-all">
<span>Explore Variant B</span>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</a>
{/* Variant C: Modern & Visual */}
<a
href="/docs/variant-c"
className="group p-8 bg-gradient-to-br from-amber-500/10 via-purple-500/10 to-cyan-500/10 border-2 border-amber-500/30 rounded-2xl hover:border-amber-500/60 transition-all duration-300 shadow-xl hover:shadow-amber-500/30 hover:scale-105"
>
<div className="text-4xl mb-6">🎨</div>
<h2 className="text-2xl font-bold text-white mb-4 group-hover:text-amber-400 transition-colors">
Variant C
</h2>
<h3 className="text-lg font-semibold text-amber-400 mb-4">Modern & Visual</h3>
<p className="text-sm text-gray-400 mb-6 leading-relaxed">
Shopify-inspired colorful card-based design with large emoji icons, gradient borders,
and playful engaging visual style.
</p>
<div className="space-y-3 mb-6">
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Colorful gradient borders everywhere</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Large emoji icons and visual elements</span>
</div>
<div className="flex items-center gap-2 text-sm text-gray-500">
<svg className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span>Fun, engaging, playful design</span>
</div>
</div>
<div className="flex items-center gap-2 text-amber-400 font-semibold group-hover:gap-3 transition-all">
<span>Explore Variant C</span>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</div>
</a>
</div>
{/* Feature Comparison */}
<div className="p-8 bg-slate-900/50 border-2 border-slate-700 rounded-2xl backdrop-blur-sm">
<h3 className="text-2xl font-bold text-white mb-6 text-center">
All Variants Include
</h3>
<div className="grid md:grid-cols-3 gap-6">
<div className="text-center">
<div className="text-3xl mb-3">📚</div>
<h4 className="text-base font-semibold text-white mb-2">Same Content</h4>
<p className="text-sm text-gray-400">
Identical API documentation, just styled differently
</p>
</div>
<div className="text-center">
<div className="text-3xl mb-3"></div>
<h4 className="text-base font-semibold text-white mb-2">Interactive Widgets</h4>
<p className="text-sm text-gray-400">
Live API testing with your own keys
</p>
</div>
<div className="text-center">
<div className="text-3xl mb-3">🔍</div>
<h4 className="text-base font-semibold text-white mb-2">Navigation & Search</h4>
<p className="text-sm text-gray-400">
Sidebar, TOC, and breadcrumb navigation
</p>
</div>
</div>
</div>
{/* Footer CTA */}
<div className="mt-16 text-center">
<p className="text-gray-400 mb-4">
Not sure which to choose? Try all three and see which feels right!
</p>
<p className="text-sm text-gray-500">
Each variant links to the same API contentpick your preferred reading experience.
</p>
</div>
</div>
</div>
);
}

View File

@ -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 (
<DocsLayoutA
sidebar={<DocsSidebarA currentPath="/docs/variant-a/api/text-to-image" />}
toc={<DocsTOCA items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/variant-a/api' },
{ label: 'Text to Image' },
]}
/>
{/* Hero Section */}
<div className="mb-12">
<div className="inline-block px-3 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-300 text-xs font-medium mb-4">
POST
</div>
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Text to Image</h1>
<p className="text-xl text-gray-400 leading-relaxed">
Generate high-quality images from text prompts using AI-powered models.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<div className="p-4 bg-cyan-500/10 border border-cyan-500/20 rounded-xl">
<p className="text-sm text-cyan-300">
<strong>Tip:</strong> Enable autoEnhance for better results. The AI will optimize your
prompt for higher quality outputs while preserving your intent.
</p>
</div>
</section>
{/* Endpoint */}
<section id="endpoint" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Endpoint</h2>
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<code className="text-purple-400">POST</code>
<code className="ml-3 text-gray-300">https://api.banatie.com/api/text-to-image</code>
</div>
</section>
{/* Request */}
<section id="request" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Request</h2>
<div id="headers" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-4">Headers</h3>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-3 px-4 text-gray-400 font-medium">Header</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Value</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Required</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">X-API-Key</td>
<td className="py-3 px-4">Your project API key</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">Content-Type</td>
<td className="py-3 px-4">application/json</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="body" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-4">Body Parameters</h3>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-3 px-4 text-gray-400 font-medium">Parameter</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Type</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Description</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Required</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">prompt</td>
<td className="py-3 px-4">string</td>
<td className="py-3 px-4">Text description of the image to generate</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">filename</td>
<td className="py-3 px-4">string</td>
<td className="py-3 px-4">Name for the generated image file</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">aspectRatio</td>
<td className="py-3 px-4">string</td>
<td className="py-3 px-4">
Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">autoEnhance</td>
<td className="py-3 px-4">boolean</td>
<td className="py-3 px-4">Enable automatic prompt enhancement (default: true)</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-purple-400">enhancementOptions</td>
<td className="py-3 px-4">object</td>
<td className="py-3 px-4">Template and enhancement settings</td>
<td className="py-3 px-4">
<span className="px-2 py-1 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
{/* Interactive API Widget */}
<InteractiveAPIWidgetA
endpoint="/api/text-to-image"
method="POST"
description="Try generating an image with your own API key"
parameters={[
{
name: 'prompt',
type: 'string',
required: true,
description: 'Image description',
defaultValue: 'a futuristic city at sunset',
},
{
name: 'filename',
type: 'string',
required: true,
description: 'Output filename',
defaultValue: 'city',
},
{
name: 'aspectRatio',
type: 'string',
required: false,
description: 'Aspect ratio',
defaultValue: '16:9',
},
]}
/>
{/* Response */}
<section id="response" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Response</h2>
<p className="text-gray-300 leading-relaxed mb-4">
Returns a JSON object with the generated image URL and metadata.
</p>
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{`{
"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"
}
}`}</code>
</pre>
</div>
</section>
{/* Examples */}
<section id="examples" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Examples</h2>
<div className="space-y-6">
<div>
<h4 className="text-lg font-semibold text-white mb-3">Basic Image Generation</h4>
<p className="text-sm text-gray-400 mb-3">Generate a simple image with default settings</p>
<div className="p-4 bg-slate-950/50 border border-slate-700 rounded-xl">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{`{
"prompt": "a serene mountain landscape",
"filename": "mountain"
}`}</code>
</pre>
</div>
</div>
<div>
<h4 className="text-lg font-semibold text-white mb-3">Custom Aspect Ratio</h4>
<p className="text-sm text-gray-400 mb-3">Generate a widescreen image</p>
<div className="p-4 bg-slate-950/50 border border-slate-700 rounded-xl">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{`{
"prompt": "cinematic space battle scene",
"filename": "space_battle",
"aspectRatio": "21:9"
}`}</code>
</pre>
</div>
</div>
</div>
</section>
{/* Error Codes */}
<section id="errors" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Error Codes</h2>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-3 px-4 text-gray-400 font-medium">Code</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Description</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-red-400">400</td>
<td className="py-3 px-4">Invalid request parameters</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-red-400">401</td>
<td className="py-3 px-4">Missing or invalid API key</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-red-400">429</td>
<td className="py-3 px-4">Rate limit exceeded</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4 font-mono text-red-400">500</td>
<td className="py-3 px-4">Internal server error</td>
</tr>
</tbody>
</table>
</div>
</section>
</DocsLayoutA>
);
}

View File

@ -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 (
<DocsLayoutA
sidebar={<DocsSidebarA currentPath="/docs/variant-a/guides/authentication" />}
toc={<DocsTOCA items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Guides', href: '/docs/variant-a/guides' },
{ label: 'Authentication' },
]}
/>
{/* Hero Section */}
<div className="mb-12">
<div className="inline-block px-3 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-300 text-xs font-medium mb-4">
GUIDE
</div>
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Authentication</h1>
<p className="text-xl text-gray-400 leading-relaxed">
Learn how to authenticate your requests and manage API keys securely.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<div className="p-4 bg-purple-500/10 border border-purple-500/20 rounded-xl">
<p className="text-sm text-purple-300">
<strong>Security First:</strong> Never expose your API keys in client-side code, public
repositories, or logs. Treat them like passwords.
</p>
</div>
</section>
{/* API Keys */}
<section id="api-keys" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">API Keys</h2>
<div id="key-types" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-4">Key Types</h3>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie provides two types of API keys, each with different permissions and use cases:
</p>
<div className="space-y-4">
<div className="p-6 bg-slate-800/50 border border-slate-700 rounded-xl">
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-10 h-10 rounded-lg bg-purple-500/20 flex items-center justify-center text-xl">
🔑
</div>
<div className="flex-1">
<h4 className="text-lg font-semibold text-white mb-2">Master Keys</h4>
<p className="text-sm text-gray-400 mb-3">
Full administrative access to your organization. Can create and revoke other
keys, access all projects, and manage settings.
</p>
<ul className="text-sm text-gray-400 space-y-1">
<li> Never expire</li>
<li> Full API access</li>
<li> One per organization (initially)</li>
<li> Should be kept extremely secure</li>
</ul>
</div>
</div>
</div>
<div className="p-6 bg-slate-800/50 border border-slate-700 rounded-xl">
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-10 h-10 rounded-lg bg-cyan-500/20 flex items-center justify-center text-xl">
🎫
</div>
<div className="flex-1">
<h4 className="text-lg font-semibold text-white mb-2">Project Keys</h4>
<p className="text-sm text-gray-400 mb-3">
Scoped to a specific project. Used for image generation and resource access
within that project only.
</p>
<ul className="text-sm text-gray-400 space-y-1">
<li> Expire after 90 days</li>
<li> Project-specific access</li>
<li> Rate limited</li>
<li> Safe for production use</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div id="creating-keys" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-4">Creating Keys</h3>
<div className="mb-6">
<h4 className="text-base font-semibold text-white mb-3">Bootstrap Your First Key</h4>
<p className="text-gray-300 text-sm leading-relaxed mb-3">
When setting up Banatie for the first time, create your initial master key using the
bootstrap endpoint:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Response
{
"success": true,
"key": "bnt_master_abc123...",
"message": "Master key created successfully"
}`}
language="bash"
filename="Create Master Key"
/>
<div className="mt-3 p-3 bg-amber-500/10 border border-amber-500/20 rounded-lg">
<p className="text-xs text-amber-300">
<strong>Important:</strong> This endpoint can only be used once. Save the returned
key immediately - it will never be shown again.
</p>
</div>
</div>
<div className="mb-6">
<h4 className="text-base font-semibold text-white mb-3">Create Project Keys</h4>
<p className="text-gray-300 text-sm leading-relaxed mb-3">
Use your master key to create project-specific keys:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/admin/keys \\
-H "X-API-Key: YOUR_MASTER_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"type": "project",
"projectId": "my-project",
"name": "Production Key"
}'
# Response
{
"success": true,
"key": "bnt_project_xyz789...",
"keyId": "key_abc123",
"expiresAt": "2025-04-15T10:30:00Z"
}`}
language="bash"
filename="Create Project Key"
/>
</div>
</div>
</section>
{/* Using Keys */}
<section id="using-keys" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Using API Keys</h2>
<p className="text-gray-300 leading-relaxed mb-6">
Include your API key in every request using the X-API-Key header:
</p>
<CodeBlock
code={`# Using curl
curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_PROJECT_KEY" \\
-H "Content-Type: application/json" \\
-d '{"prompt": "sunset", "filename": "test"}'
# Using JavaScript fetch
const response = await fetch('https://api.banatie.com/api/text-to-image', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_PROJECT_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'sunset',
filename: 'test'
})
});`}
language="bash"
filename="API Request Example"
/>
</section>
{/* Security */}
<section id="security" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Security Best Practices</h2>
<div className="space-y-4">
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<div className="flex-shrink-0 text-2xl">🔒</div>
<div>
<h4 className="text-sm font-semibold text-white mb-1">Never Commit Keys</h4>
<p className="text-sm text-gray-400">
Use environment variables or secret management tools. Never commit keys to version
control.
</p>
</div>
</div>
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<div className="flex-shrink-0 text-2xl">🔄</div>
<div>
<h4 className="text-sm font-semibold text-white mb-1">Rotate Keys Regularly</h4>
<p className="text-sm text-gray-400">
Project keys expire after 90 days. Plan for rotation and implement graceful
handling.
</p>
</div>
</div>
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<div className="flex-shrink-0 text-2xl">🚫</div>
<div>
<h4 className="text-sm font-semibold text-white mb-1">Server-Side Only</h4>
<p className="text-sm text-gray-400">
Never use API keys in client-side code. Always make requests from your backend.
</p>
</div>
</div>
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<div className="flex-shrink-0 text-2xl">👁</div>
<div>
<h4 className="text-sm font-semibold text-white mb-1">Monitor Usage</h4>
<p className="text-sm text-gray-400">
Track API key usage patterns. Unusual activity may indicate a compromised key.
</p>
</div>
</div>
</div>
</section>
{/* Rate Limits */}
<section id="rate-limits" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Rate Limits</h2>
<p className="text-gray-300 leading-relaxed mb-6">
To ensure fair usage and system stability, all API keys are subject to rate limits:
</p>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-3 px-4 text-gray-400 font-medium">Key Type</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Limit</th>
<th className="text-left py-3 px-4 text-gray-400 font-medium">Window</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-3 px-4">Master Key</td>
<td className="py-3 px-4 font-mono">500 requests</td>
<td className="py-3 px-4">per hour</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-3 px-4">Project Key</td>
<td className="py-3 px-4 font-mono">100 requests</td>
<td className="py-3 px-4">per hour</td>
</tr>
</tbody>
</table>
</div>
<div className="mt-6 p-4 bg-cyan-500/10 border border-cyan-500/20 rounded-xl">
<p className="text-sm text-cyan-300">
<strong>Need Higher Limits?</strong> Contact our sales team to discuss enterprise plans
with custom rate limits.
</p>
</div>
</section>
</DocsLayoutA>
);
}

View File

@ -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 (
<DocsLayoutA
sidebar={<DocsSidebarA currentPath="/docs/variant-a" />}
toc={<DocsTOCA items={tocItems} />}
>
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
{/* Hero Section */}
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Getting Started</h1>
<p className="text-xl text-gray-400 leading-relaxed">
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
generation into your applications in minutes.
</p>
</div>
{/* Introduction */}
<section id="introduction" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Introduction</h2>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<p className="text-gray-300 leading-relaxed">
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.
</p>
</section>
{/* Quick Start */}
<section id="quick-start" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Quick Start</h2>
<div id="installation" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-3">Installation</h3>
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<CodeBlock
code={`# Using npm (JavaScript/TypeScript)
npm install @banatie/sdk
# Using pip (Python)
pip install banatie
# Using Go
go get github.com/banatie/sdk-go`}
language="bash"
filename="Installation"
/>
</div>
<div id="authentication" className="mb-8">
<h3 className="text-xl font-semibold text-white mb-3">Authentication</h3>
<p className="text-gray-300 leading-relaxed mb-4">
All API requests require an API key. You can create an API key from your dashboard or
using the bootstrap endpoint for initial setup.
</p>
<div className="p-4 bg-purple-500/10 border border-purple-500/20 rounded-xl mb-4">
<p className="text-sm text-purple-300">
<strong>Note:</strong> Keep your API keys secure. Never commit them to public
repositories or expose them in client-side code.
</p>
</div>
<CodeBlock
code={`# Create your first API key (one-time bootstrap)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Save the returned key securely
export BANATIE_API_KEY="bnt_your_key_here"`}
language="bash"
filename="Get API Key"
/>
</div>
</section>
{/* First Request */}
<section id="first-request" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-4">Your First Request</h2>
<p className="text-gray-300 leading-relaxed mb-6">
Let's generate your first image! This example uses curl, but you can use any HTTP client
or our SDKs.
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"filename": "mountain_sunset",
"aspectRatio": "16:9",
"autoEnhance": true
}'`}
language="bash"
filename="Generate Image"
/>
<div className="mt-6 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
<p className="text-sm font-semibold text-gray-300 mb-2">Response:</p>
<pre className="text-xs text-gray-400 overflow-x-auto">
<code>{`{
"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..."
}
}
}`}</code>
</pre>
</div>
</section>
{/* Next Steps */}
<section id="next-steps" className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
<div className="grid md:grid-cols-2 gap-4">
<a
href="/docs/variant-a/api/text-to-image"
className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-xl hover:border-purple-500/40 transition-colors group"
>
<div className="text-2xl mb-3">📚</div>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
API Reference
</h3>
<p className="text-sm text-gray-400">
Explore all available endpoints, parameters, and response formats.
</p>
</a>
<a
href="/docs/variant-a/guides/authentication"
className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-xl hover:border-cyan-500/40 transition-colors group"
>
<div className="text-2xl mb-3">🔐</div>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
Authentication Guide
</h3>
<p className="text-sm text-gray-400">
Learn about API keys, rate limits, and security best practices.
</p>
</a>
<a
href="/docs/variant-a/examples"
className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-xl hover:border-purple-500/40 transition-colors group"
>
<div className="text-2xl mb-3">💡</div>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
Examples
</h3>
<p className="text-sm text-gray-400">
Browse code examples and use cases for common scenarios.
</p>
</a>
<a
href="/docs/variant-a/guides/error-handling"
className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-xl hover:border-cyan-500/40 transition-colors group"
>
<div className="text-2xl mb-3"></div>
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
Error Handling
</h3>
<p className="text-sm text-gray-400">
Understand error codes and how to handle failures gracefully.
</p>
</a>
</div>
</section>
</DocsLayoutA>
);
}

View File

@ -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 (
<DocsLayoutB
sidebar={<DocsSidebarB currentPath="/docs/variant-b/api/text-to-image" />}
toc={<DocsTOCB items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/variant-b/api' },
{ label: 'Text to Image' },
]}
/>
{/* Hero Section - More compact */}
<div className="mb-10">
<div className="inline-block px-2.5 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-300 text-xs font-medium mb-3">
POST
</div>
<h1 className="text-4xl md:text-5xl font-bold text-white mb-3">Text to Image</h1>
<p className="text-lg text-gray-400 leading-relaxed">
Generate high-quality images from text prompts using AI-powered models.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">1. Overview</h2>
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
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.
</p>
<div className="p-3 bg-cyan-500/10 border border-cyan-500/20 rounded-lg">
<p className="text-xs text-cyan-300">
<strong>Tip:</strong> Enable autoEnhance for better results. The AI will optimize your
prompt for higher quality outputs while preserving your intent.
</p>
</div>
</section>
{/* Endpoint */}
<section id="endpoint" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">2. Endpoint</h2>
<div className="p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<code className="text-purple-400 text-sm">POST</code>
<code className="ml-3 text-gray-300 text-sm">https://api.banatie.com/api/text-to-image</code>
</div>
</section>
{/* Request */}
<section id="request" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-5">3. Request</h2>
<div id="headers" className="mb-6">
<h3 className="text-lg font-semibold text-white mb-3">3.1 Headers</h3>
<div className="overflow-x-auto">
<table className="w-full text-xs">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-2 px-3 text-gray-400 font-medium">Header</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Value</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Required</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">X-API-Key</td>
<td className="py-2 px-3">Your project API key</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">Content-Type</td>
<td className="py-2 px-3">application/json</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="body" className="mb-6">
<h3 className="text-lg font-semibold text-white mb-3">3.2 Body Parameters</h3>
<div className="overflow-x-auto">
<table className="w-full text-xs">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-2 px-3 text-gray-400 font-medium">Parameter</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Type</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Description</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Required</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">prompt</td>
<td className="py-2 px-3">string</td>
<td className="py-2 px-3">Text description of the image to generate</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">filename</td>
<td className="py-2 px-3">string</td>
<td className="py-2 px-3">Name for the generated image file</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">aspectRatio</td>
<td className="py-2 px-3">string</td>
<td className="py-2 px-3">
Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">autoEnhance</td>
<td className="py-2 px-3">boolean</td>
<td className="py-2 px-3">Enable automatic prompt enhancement (default: true)</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-purple-400">enhancementOptions</td>
<td className="py-2 px-3">object</td>
<td className="py-2 px-3">Template and enhancement settings</td>
<td className="py-2 px-3">
<span className="px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
{/* Interactive API Widget */}
<InteractiveAPIWidgetB
endpoint="/api/text-to-image"
method="POST"
description="Try generating an image with your own API key"
parameters={[
{
name: 'prompt',
type: 'string',
required: true,
description: 'Image description',
defaultValue: 'a futuristic city at sunset',
},
{
name: 'filename',
type: 'string',
required: true,
description: 'Output filename',
defaultValue: 'city',
},
{
name: 'aspectRatio',
type: 'string',
required: false,
description: 'Aspect ratio',
defaultValue: '16:9',
},
]}
/>
{/* Response */}
<section id="response" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">4. Response</h2>
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
Returns a JSON object with the generated image URL and metadata.
</p>
<div className="p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{`{
"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"
}
}`}</code>
</pre>
</div>
</section>
{/* Examples */}
<section id="examples" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-5">5. Examples</h2>
<div className="space-y-4">
<div>
<h4 className="text-base font-semibold text-white mb-2">5.1 Basic Image Generation</h4>
<p className="text-xs text-gray-400 mb-2">Generate a simple image with default settings</p>
<div className="p-3 bg-slate-950/50 border border-slate-700 rounded-lg">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{`{
"prompt": "a serene mountain landscape",
"filename": "mountain"
}`}</code>
</pre>
</div>
</div>
<div>
<h4 className="text-base font-semibold text-white mb-2">5.2 Custom Aspect Ratio</h4>
<p className="text-xs text-gray-400 mb-2">Generate a widescreen image</p>
<div className="p-3 bg-slate-950/50 border border-slate-700 rounded-lg">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{`{
"prompt": "cinematic space battle scene",
"filename": "space_battle",
"aspectRatio": "21:9"
}`}</code>
</pre>
</div>
</div>
</div>
</section>
{/* Error Codes */}
<section id="errors" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">6. Error Codes</h2>
<div className="overflow-x-auto">
<table className="w-full text-xs">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-2 px-3 text-gray-400 font-medium">Code</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Description</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-red-400">400</td>
<td className="py-2 px-3">Invalid request parameters</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-red-400">401</td>
<td className="py-2 px-3">Missing or invalid API key</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-red-400">429</td>
<td className="py-2 px-3">Rate limit exceeded</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3 font-mono text-red-400">500</td>
<td className="py-2 px-3">Internal server error</td>
</tr>
</tbody>
</table>
</div>
</section>
</DocsLayoutB>
);
}

View File

@ -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 (
<DocsLayoutB
sidebar={<DocsSidebarB currentPath="/docs/variant-b/guides/authentication" />}
toc={<DocsTOCB items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Guides', href: '/docs/variant-b/guides' },
{ label: 'Authentication' },
]}
/>
{/* Hero Section - More compact */}
<div className="mb-10">
<div className="inline-block px-2.5 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-300 text-xs font-medium mb-3">
GUIDE
</div>
<h1 className="text-4xl md:text-5xl font-bold text-white mb-3">Authentication</h1>
<p className="text-lg text-gray-400 leading-relaxed">
Learn how to authenticate your requests and manage API keys securely.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">1. Overview</h2>
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
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.
</p>
<div className="p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg">
<p className="text-xs text-purple-300">
<strong>Security First:</strong> Never expose your API keys in client-side code, public
repositories, or logs. Treat them like passwords.
</p>
</div>
</section>
{/* API Keys */}
<section id="api-keys" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-5">2. API Keys</h2>
<div id="key-types" className="mb-6">
<h3 className="text-lg font-semibold text-white mb-3">2.1 Key Types</h3>
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
Banatie provides two types of API keys, each with different permissions and use cases:
</p>
<div className="space-y-3">
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-lg">
<div className="flex items-start gap-3">
<div className="flex-shrink-0 w-8 h-8 rounded-lg bg-purple-500/20 flex items-center justify-center text-lg">
🔑
</div>
<div className="flex-1">
<h4 className="text-base font-semibold text-white mb-1.5">Master Keys</h4>
<p className="text-xs text-gray-400 mb-2">
Full administrative access to your organization. Can create and revoke other
keys, access all projects, and manage settings.
</p>
<ul className="text-xs text-gray-400 space-y-0.5">
<li> Never expire</li>
<li> Full API access</li>
<li> One per organization (initially)</li>
<li> Should be kept extremely secure</li>
</ul>
</div>
</div>
</div>
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-lg">
<div className="flex items-start gap-3">
<div className="flex-shrink-0 w-8 h-8 rounded-lg bg-cyan-500/20 flex items-center justify-center text-lg">
🎫
</div>
<div className="flex-1">
<h4 className="text-base font-semibold text-white mb-1.5">Project Keys</h4>
<p className="text-xs text-gray-400 mb-2">
Scoped to a specific project. Used for image generation and resource access
within that project only.
</p>
<ul className="text-xs text-gray-400 space-y-0.5">
<li> Expire after 90 days</li>
<li> Project-specific access</li>
<li> Rate limited</li>
<li> Safe for production use</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div id="creating-keys" className="mb-6">
<h3 className="text-lg font-semibold text-white mb-3">2.2 Creating Keys</h3>
<div className="mb-5">
<h4 className="text-sm font-semibold text-white mb-2">2.2.1 Bootstrap Your First Key</h4>
<p className="text-gray-300 text-xs leading-relaxed mb-2">
When setting up Banatie for the first time, create your initial master key using the
bootstrap endpoint:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Response
{
"success": true,
"key": "bnt_master_abc123...",
"message": "Master key created successfully"
}`}
language="bash"
filename="Create Master Key"
/>
<div className="mt-2 p-2.5 bg-amber-500/10 border border-amber-500/20 rounded-lg">
<p className="text-xs text-amber-300">
<strong>Important:</strong> This endpoint can only be used once. Save the returned
key immediately - it will never be shown again.
</p>
</div>
</div>
<div className="mb-5">
<h4 className="text-sm font-semibold text-white mb-2">2.2.2 Create Project Keys</h4>
<p className="text-gray-300 text-xs leading-relaxed mb-2">
Use your master key to create project-specific keys:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/admin/keys \\
-H "X-API-Key: YOUR_MASTER_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"type": "project",
"projectId": "my-project",
"name": "Production Key"
}'
# Response
{
"success": true,
"key": "bnt_project_xyz789...",
"keyId": "key_abc123",
"expiresAt": "2025-04-15T10:30:00Z"
}`}
language="bash"
filename="Create Project Key"
/>
</div>
</div>
</section>
{/* Using Keys */}
<section id="using-keys" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">3. Using API Keys</h2>
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
Include your API key in every request using the X-API-Key header:
</p>
<CodeBlock
code={`# Using curl
curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_PROJECT_KEY" \\
-H "Content-Type: application/json" \\
-d '{"prompt": "sunset", "filename": "test"}'
# Using JavaScript fetch
const response = await fetch('https://api.banatie.com/api/text-to-image', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_PROJECT_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'sunset',
filename: 'test'
})
});`}
language="bash"
filename="API Request Example"
/>
</section>
{/* Security */}
<section id="security" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-5">4. Security Best Practices</h2>
<div className="space-y-3">
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<div className="flex-shrink-0 text-xl">🔒</div>
<div>
<h4 className="text-xs font-semibold text-white mb-0.5">Never Commit Keys</h4>
<p className="text-xs text-gray-400">
Use environment variables or secret management tools. Never commit keys to version
control.
</p>
</div>
</div>
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<div className="flex-shrink-0 text-xl">🔄</div>
<div>
<h4 className="text-xs font-semibold text-white mb-0.5">Rotate Keys Regularly</h4>
<p className="text-xs text-gray-400">
Project keys expire after 90 days. Plan for rotation and implement graceful
handling.
</p>
</div>
</div>
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<div className="flex-shrink-0 text-xl">🚫</div>
<div>
<h4 className="text-xs font-semibold text-white mb-0.5">Server-Side Only</h4>
<p className="text-xs text-gray-400">
Never use API keys in client-side code. Always make requests from your backend.
</p>
</div>
</div>
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<div className="flex-shrink-0 text-xl">👁</div>
<div>
<h4 className="text-xs font-semibold text-white mb-0.5">Monitor Usage</h4>
<p className="text-xs text-gray-400">
Track API key usage patterns. Unusual activity may indicate a compromised key.
</p>
</div>
</div>
</div>
</section>
{/* Rate Limits */}
<section id="rate-limits" className="mb-8">
<h2 className="text-2xl font-bold text-white mb-3">5. Rate Limits</h2>
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
To ensure fair usage and system stability, all API keys are subject to rate limits:
</p>
<div className="overflow-x-auto">
<table className="w-full text-xs">
<thead>
<tr className="border-b border-slate-700">
<th className="text-left py-2 px-3 text-gray-400 font-medium">Key Type</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Limit</th>
<th className="text-left py-2 px-3 text-gray-400 font-medium">Window</th>
</tr>
</thead>
<tbody className="text-gray-300">
<tr className="border-b border-slate-800">
<td className="py-2 px-3">Master Key</td>
<td className="py-2 px-3 font-mono">500 requests</td>
<td className="py-2 px-3">per hour</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-2 px-3">Project Key</td>
<td className="py-2 px-3 font-mono">100 requests</td>
<td className="py-2 px-3">per hour</td>
</tr>
</tbody>
</table>
</div>
<div className="mt-4 p-3 bg-cyan-500/10 border border-cyan-500/20 rounded-lg">
<p className="text-xs text-cyan-300">
<strong>Need Higher Limits?</strong> Contact our sales team to discuss enterprise plans
with custom rate limits.
</p>
</div>
</section>
</DocsLayoutB>
);
}

View File

@ -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 (
<DocsLayoutB
sidebar={<DocsSidebarB currentPath="/docs/variant-b" />}
toc={<DocsTOCB items={tocItems} />}
>
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
{/* Hero Section - More compact */}
<div className="mb-10">
<h1 className="text-4xl md:text-5xl font-bold text-white mb-3">Getting Started</h1>
<p className="text-lg text-gray-400 leading-relaxed">
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
generation into your applications in minutes.
</p>
</div>
{/* Introduction */}
<section id="introduction" className="mb-10">
<h2 className="text-2xl font-bold text-white mb-3">1. Introduction</h2>
<p className="text-gray-300 leading-relaxed mb-3">
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.
</p>
<p className="text-gray-300 leading-relaxed">
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.
</p>
</section>
{/* Quick Start */}
<section id="quick-start" className="mb-10">
<h2 className="text-2xl font-bold text-white mb-5">2. Quick Start</h2>
<div id="installation" className="mb-6">
<h3 className="text-lg font-semibold text-white mb-2">2.1 Installation</h3>
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
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.
</p>
<CodeBlock
code={`# Using npm (JavaScript/TypeScript)
npm install @banatie/sdk
# Using pip (Python)
pip install banatie
# Using Go
go get github.com/banatie/sdk-go`}
language="bash"
filename="Installation"
/>
</div>
<div id="authentication" className="mb-6">
<h3 className="text-lg font-semibold text-white mb-2">2.2 Authentication</h3>
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
All API requests require an API key. You can create an API key from your dashboard or
using the bootstrap endpoint for initial setup.
</p>
<div className="p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg mb-3">
<p className="text-xs text-purple-300">
<strong>Note:</strong> Keep your API keys secure. Never commit them to public
repositories or expose them in client-side code.
</p>
</div>
<CodeBlock
code={`# Create your first API key (one-time bootstrap)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Save the returned key securely
export BANATIE_API_KEY="bnt_your_key_here"`}
language="bash"
filename="Get API Key"
/>
</div>
</section>
{/* First Request */}
<section id="first-request" className="mb-10">
<h2 className="text-2xl font-bold text-white mb-3">3. Your First Request</h2>
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
Let's generate your first image! This example uses curl, but you can use any HTTP client
or our SDKs.
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"filename": "mountain_sunset",
"aspectRatio": "16:9",
"autoEnhance": true
}'`}
language="bash"
filename="Generate Image"
/>
<div className="mt-4 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
<p className="text-xs font-semibold text-gray-300 mb-2">Response:</p>
<pre className="text-xs text-gray-400 overflow-x-auto">
<code>{`{
"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..."
}
}
}`}</code>
</pre>
</div>
</section>
{/* Next Steps */}
<section id="next-steps" className="mb-10">
<h2 className="text-2xl font-bold text-white mb-5">4. Next Steps</h2>
<div className="grid md:grid-cols-2 gap-3">
<a
href="/docs/variant-b/api/text-to-image"
className="p-4 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-lg hover:border-purple-500/40 transition-colors group"
>
<div className="text-xl mb-2">📚</div>
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-purple-400 transition-colors">
API Reference
</h3>
<p className="text-xs text-gray-400">
Explore all available endpoints, parameters, and response formats.
</p>
</a>
<a
href="/docs/variant-b/guides/authentication"
className="p-4 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-lg hover:border-cyan-500/40 transition-colors group"
>
<div className="text-xl mb-2">🔐</div>
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-cyan-400 transition-colors">
Authentication Guide
</h3>
<p className="text-xs text-gray-400">
Learn about API keys, rate limits, and security best practices.
</p>
</a>
<a
href="/docs/variant-b/examples"
className="p-4 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-lg hover:border-purple-500/40 transition-colors group"
>
<div className="text-xl mb-2">💡</div>
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-purple-400 transition-colors">
Examples
</h3>
<p className="text-xs text-gray-400">
Browse code examples and use cases for common scenarios.
</p>
</a>
<a
href="/docs/variant-b/guides/error-handling"
className="p-4 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-lg hover:border-cyan-500/40 transition-colors group"
>
<div className="text-xl mb-2"></div>
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-cyan-400 transition-colors">
Error Handling
</h3>
<p className="text-xs text-gray-400">
Understand error codes and how to handle failures gracefully.
</p>
</a>
</div>
</section>
</DocsLayoutB>
);
}

View File

@ -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 (
<DocsLayoutC
sidebar={<DocsSidebarC currentPath="/docs/variant-c/api/text-to-image" />}
toc={<DocsTOCC items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'API Reference', href: '/docs/variant-c/api' },
{ label: 'Text to Image' },
]}
/>
{/* Hero Section - Large and Colorful */}
<div className="mb-12">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/30 to-purple-600/30 border-2 border-purple-500/50 shadow-lg shadow-purple-500/30 mb-6">
<span className="text-lg font-bold text-white">POST</span>
</div>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 bg-gradient-to-r from-purple-400 to-cyan-400 bg-clip-text text-transparent">
Text to Image
</h1>
<p className="text-xl text-gray-300 leading-relaxed">
Generate high-quality images from text prompts using AI-powered models.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">📖</span>
<h2 className="text-3xl font-bold text-white">Overview</h2>
</div>
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<div className="p-4 bg-cyan-500/10 border-2 border-cyan-500/30 rounded-xl">
<div className="flex items-start gap-3">
<span className="text-2xl">💡</span>
<div>
<p className="text-sm font-bold text-cyan-300 mb-1">Pro Tip</p>
<p className="text-sm text-cyan-200">
Enable autoEnhance for better results. The AI will optimize your prompt for higher
quality outputs while preserving your intent.
</p>
</div>
</div>
</div>
</div>
</section>
{/* Endpoint */}
<section id="endpoint" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">🔗</span>
<h2 className="text-3xl font-bold text-white">Endpoint</h2>
</div>
<div className="p-6 bg-gradient-to-br from-slate-900/80 to-slate-950/80 border-2 border-purple-500/30 rounded-2xl shadow-xl">
<div className="flex flex-wrap items-center gap-3">
<span className="px-3 py-1.5 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-lg font-bold text-sm shadow-lg">
POST
</span>
<code className="text-purple-400 font-mono">https://api.banatie.com/api/text-to-image</code>
</div>
</div>
</section>
{/* Request */}
<section id="request" className="mb-12">
<div className="flex items-center gap-3 mb-8">
<span className="text-3xl">📤</span>
<h2 className="text-3xl font-bold text-white">Request</h2>
</div>
<div id="headers" className="mb-8">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🏷</span>
<h3 className="text-2xl font-semibold text-white">Headers</h3>
</div>
<div className="overflow-hidden border-2 border-cyan-500/30 rounded-2xl shadow-lg">
<table className="w-full">
<thead>
<tr className="bg-slate-950/80 border-b-2 border-cyan-500/20">
<th className="text-left py-4 px-6 text-cyan-400 font-bold text-sm">Header</th>
<th className="text-left py-4 px-6 text-cyan-400 font-bold text-sm">Value</th>
<th className="text-left py-4 px-6 text-cyan-400 font-bold text-sm">Required</th>
</tr>
</thead>
<tbody className="text-gray-300 bg-slate-900/50">
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-purple-400 font-semibold">X-API-Key</td>
<td className="py-4 px-6">Your project API key</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
Required
</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-purple-400 font-semibold">Content-Type</td>
<td className="py-4 px-6">application/json</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
Required
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="body" className="mb-8">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl"></span>
<h3 className="text-2xl font-semibold text-white">Body Parameters</h3>
</div>
<div className="overflow-hidden border-2 border-purple-500/30 rounded-2xl shadow-lg">
<table className="w-full">
<thead>
<tr className="bg-slate-950/80 border-b-2 border-purple-500/20">
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Parameter</th>
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Type</th>
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Description</th>
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Required</th>
</tr>
</thead>
<tbody className="text-gray-300 bg-slate-900/50">
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">prompt</td>
<td className="py-4 px-6 text-sm">string</td>
<td className="py-4 px-6 text-sm">Text description of the image to generate</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
Required
</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">filename</td>
<td className="py-4 px-6 text-sm">string</td>
<td className="py-4 px-6 text-sm">Name for the generated image file</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
Required
</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">aspectRatio</td>
<td className="py-4 px-6 text-sm">string</td>
<td className="py-4 px-6 text-sm">
Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-gray-500/20 text-gray-400 rounded-lg text-xs font-bold border-2 border-gray-500/30">
Optional
</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">autoEnhance</td>
<td className="py-4 px-6 text-sm">boolean</td>
<td className="py-4 px-6 text-sm">Enable automatic prompt enhancement (default: true)</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-gray-500/20 text-gray-400 rounded-lg text-xs font-bold border-2 border-gray-500/30">
Optional
</span>
</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">enhancementOptions</td>
<td className="py-4 px-6 text-sm">object</td>
<td className="py-4 px-6 text-sm">Template and enhancement settings</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-gray-500/20 text-gray-400 rounded-lg text-xs font-bold border-2 border-gray-500/30">
Optional
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
{/* Interactive API Widget */}
<InteractiveAPIWidgetC
endpoint="/api/text-to-image"
method="POST"
description="Try generating an image with your own API key"
parameters={[
{
name: 'prompt',
type: 'string',
required: true,
description: 'Image description',
defaultValue: 'a futuristic city at sunset',
},
{
name: 'filename',
type: 'string',
required: true,
description: 'Output filename',
defaultValue: 'city',
},
{
name: 'aspectRatio',
type: 'string',
required: false,
description: 'Aspect ratio',
defaultValue: '16:9',
},
]}
/>
{/* Response */}
<section id="response" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">📦</span>
<h2 className="text-3xl font-bold text-white">Response</h2>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
Returns a JSON object with the generated image URL and metadata.
</p>
<div className="p-6 bg-gradient-to-br from-slate-900/80 to-slate-950/80 border-2 border-green-500/30 rounded-2xl shadow-xl shadow-green-500/20">
<div className="flex items-center gap-2 mb-4">
<span className="px-3 py-1.5 bg-green-500/20 text-green-400 rounded-lg text-xs font-bold border-2 border-green-500/40">
200 Success
</span>
</div>
<pre className="text-sm text-gray-300 overflow-x-auto">
<code>{`{
"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"
}
}`}</code>
</pre>
</div>
</section>
{/* Examples */}
<section id="examples" className="mb-12">
<div className="flex items-center gap-3 mb-8">
<span className="text-3xl">💡</span>
<h2 className="text-3xl font-bold text-white">Examples</h2>
</div>
<div className="space-y-6">
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-lg">
<div className="flex items-center gap-2 mb-3">
<span className="text-xl">🎨</span>
<h4 className="text-xl font-bold text-white">Basic Image Generation</h4>
</div>
<p className="text-sm text-gray-400 mb-4">Generate a simple image with default settings</p>
<div className="p-4 bg-slate-950/50 border-2 border-purple-500/20 rounded-xl">
<pre className="text-sm text-gray-300 overflow-x-auto">
<code>{`{
"prompt": "a serene mountain landscape",
"filename": "mountain"
}`}</code>
</pre>
</div>
</div>
<div className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-lg">
<div className="flex items-center gap-2 mb-3">
<span className="text-xl">🎬</span>
<h4 className="text-xl font-bold text-white">Custom Aspect Ratio</h4>
</div>
<p className="text-sm text-gray-400 mb-4">Generate a widescreen image</p>
<div className="p-4 bg-slate-950/50 border-2 border-cyan-500/20 rounded-xl">
<pre className="text-sm text-gray-300 overflow-x-auto">
<code>{`{
"prompt": "cinematic space battle scene",
"filename": "space_battle",
"aspectRatio": "21:9"
}`}</code>
</pre>
</div>
</div>
</div>
</section>
{/* Error Codes */}
<section id="errors" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl"></span>
<h2 className="text-3xl font-bold text-white">Error Codes</h2>
</div>
<div className="overflow-hidden border-2 border-red-500/30 rounded-2xl shadow-xl shadow-red-500/20">
<table className="w-full">
<thead>
<tr className="bg-slate-950/80 border-b-2 border-red-500/20">
<th className="text-left py-4 px-6 text-red-400 font-bold text-sm">Code</th>
<th className="text-left py-4 px-6 text-red-400 font-bold text-sm">Description</th>
</tr>
</thead>
<tbody className="text-gray-300 bg-slate-900/50">
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">400</td>
<td className="py-4 px-6">Invalid request parameters</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">401</td>
<td className="py-4 px-6">Missing or invalid API key</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">429</td>
<td className="py-4 px-6">Rate limit exceeded</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">500</td>
<td className="py-4 px-6">Internal server error</td>
</tr>
</tbody>
</table>
</div>
</section>
</DocsLayoutC>
);
}

View File

@ -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 (
<DocsLayoutC
sidebar={<DocsSidebarC currentPath="/docs/variant-c/guides/authentication" />}
toc={<DocsTOCC items={tocItems} />}
>
<Breadcrumb
items={[
{ label: 'Documentation', href: '/docs' },
{ label: 'Guides', href: '/docs/variant-c/guides' },
{ label: 'Authentication' },
]}
/>
{/* Hero Section - Large and Colorful */}
<div className="mb-12">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-cyan-500/20 to-cyan-600/20 border-2 border-cyan-500/50 shadow-lg shadow-cyan-500/30 mb-6">
<span className="text-2xl">📚</span>
<span className="text-sm font-bold text-white">GUIDE</span>
</div>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 bg-gradient-to-r from-cyan-400 to-purple-400 bg-clip-text text-transparent">
Authentication
</h1>
<p className="text-xl text-gray-300 leading-relaxed">
Learn how to authenticate your requests and manage API keys securely.
</p>
</div>
{/* Overview */}
<section id="overview" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">🔐</span>
<h2 className="text-3xl font-bold text-white">Overview</h2>
</div>
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<div className="p-4 bg-red-500/10 border-2 border-red-500/30 rounded-xl">
<div className="flex items-start gap-3">
<span className="text-2xl">🛡</span>
<div>
<p className="text-sm font-bold text-red-300 mb-1">Security First</p>
<p className="text-sm text-red-200">
Never expose your API keys in client-side code, public repositories, or logs. Treat
them like passwords.
</p>
</div>
</div>
</div>
</div>
</section>
{/* API Keys */}
<section id="api-keys" className="mb-12">
<div className="flex items-center gap-3 mb-8">
<span className="text-3xl">🔑</span>
<h2 className="text-3xl font-bold text-white">API Keys</h2>
</div>
<div id="key-types" className="mb-8">
<div className="flex items-center gap-2 mb-6">
<span className="text-2xl">🏷</span>
<h3 className="text-2xl font-semibold text-white">Key Types</h3>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
Banatie provides two types of API keys, each with different permissions and use cases:
</p>
<div className="space-y-6">
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20 hover:scale-105 transition-transform duration-300">
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-16 h-16 rounded-2xl bg-gradient-to-br from-purple-500/30 to-purple-600/30 border-2 border-purple-500/50 flex items-center justify-center text-3xl shadow-lg">
🔑
</div>
<div className="flex-1">
<h4 className="text-2xl font-bold text-white mb-3">Master Keys</h4>
<p className="text-sm text-gray-400 mb-4">
Full administrative access to your organization. Can create and revoke other
keys, access all projects, and manage settings.
</p>
<ul className="text-sm text-gray-400 space-y-2">
<li className="flex items-center gap-2">
<span className="text-purple-400"></span> Never expire
</li>
<li className="flex items-center gap-2">
<span className="text-purple-400"></span> Full API access
</li>
<li className="flex items-center gap-2">
<span className="text-purple-400"></span> One per organization (initially)
</li>
<li className="flex items-center gap-2">
<span className="text-purple-400"></span> Should be kept extremely secure
</li>
</ul>
</div>
</div>
</div>
<div className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-xl shadow-cyan-500/20 hover:scale-105 transition-transform duration-300">
<div className="flex items-start gap-4">
<div className="flex-shrink-0 w-16 h-16 rounded-2xl bg-gradient-to-br from-cyan-500/30 to-cyan-600/30 border-2 border-cyan-500/50 flex items-center justify-center text-3xl shadow-lg">
🎫
</div>
<div className="flex-1">
<h4 className="text-2xl font-bold text-white mb-3">Project Keys</h4>
<p className="text-sm text-gray-400 mb-4">
Scoped to a specific project. Used for image generation and resource access
within that project only.
</p>
<ul className="text-sm text-gray-400 space-y-2">
<li className="flex items-center gap-2">
<span className="text-cyan-400"></span> Expire after 90 days
</li>
<li className="flex items-center gap-2">
<span className="text-cyan-400"></span> Project-specific access
</li>
<li className="flex items-center gap-2">
<span className="text-cyan-400"></span> Rate limited
</li>
<li className="flex items-center gap-2">
<span className="text-cyan-400"></span> Safe for production use
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div id="creating-keys" className="mb-8">
<div className="flex items-center gap-2 mb-6">
<span className="text-2xl"></span>
<h3 className="text-2xl font-semibold text-white">Creating Keys</h3>
</div>
<div className="mb-8 p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 rounded-2xl shadow-xl shadow-amber-500/20">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🚀</span>
<h4 className="text-xl font-bold text-white">Bootstrap Your First Key</h4>
</div>
<p className="text-gray-300 text-sm leading-relaxed mb-4">
When setting up Banatie for the first time, create your initial master key using the
bootstrap endpoint:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Response
{
"success": true,
"key": "bnt_master_abc123...",
"message": "Master key created successfully"
}`}
language="bash"
filename="Create Master Key"
/>
<div className="mt-4 p-4 bg-red-500/10 border-2 border-red-500/30 rounded-xl">
<div className="flex items-start gap-2">
<span className="text-xl"></span>
<div>
<p className="text-xs font-bold text-red-300 mb-1">Important</p>
<p className="text-xs text-red-200">
This endpoint can only be used once. Save the returned key immediately - it will
never be shown again.
</p>
</div>
</div>
</div>
</div>
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🎨</span>
<h4 className="text-xl font-bold text-white">Create Project Keys</h4>
</div>
<p className="text-gray-300 text-sm leading-relaxed mb-4">
Use your master key to create project-specific keys:
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/admin/keys \\
-H "X-API-Key: YOUR_MASTER_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"type": "project",
"projectId": "my-project",
"name": "Production Key"
}'
# Response
{
"success": true,
"key": "bnt_project_xyz789...",
"keyId": "key_abc123",
"expiresAt": "2025-04-15T10:30:00Z"
}`}
language="bash"
filename="Create Project Key"
/>
</div>
</div>
</section>
{/* Using Keys */}
<section id="using-keys" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">💻</span>
<h2 className="text-3xl font-bold text-white">Using API Keys</h2>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
Include your API key in every request using the X-API-Key header:
</p>
<CodeBlock
code={`# Using curl
curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_PROJECT_KEY" \\
-H "Content-Type: application/json" \\
-d '{"prompt": "sunset", "filename": "test"}'
# Using JavaScript fetch
const response = await fetch('https://api.banatie.com/api/text-to-image', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_PROJECT_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'sunset',
filename: 'test'
})
});`}
language="bash"
filename="API Request Example"
/>
</section>
{/* Security */}
<section id="security" className="mb-12">
<div className="flex items-center gap-3 mb-8">
<span className="text-3xl">🛡</span>
<h2 className="text-3xl font-bold text-white">Security Best Practices</h2>
</div>
<div className="grid md:grid-cols-2 gap-6">
<div className="p-6 bg-gradient-to-br from-red-500/10 to-transparent border-2 border-red-500/30 rounded-2xl shadow-lg hover:shadow-red-500/30 hover:scale-105 transition-all">
<div className="text-3xl mb-4">🔒</div>
<h4 className="text-lg font-bold text-white mb-2">Never Commit Keys</h4>
<p className="text-sm text-gray-400">
Use environment variables or secret management tools. Never commit keys to version
control.
</p>
</div>
<div className="p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 rounded-2xl shadow-lg hover:shadow-amber-500/30 hover:scale-105 transition-all">
<div className="text-3xl mb-4">🔄</div>
<h4 className="text-lg font-bold text-white mb-2">Rotate Keys Regularly</h4>
<p className="text-sm text-gray-400">
Project keys expire after 90 days. Plan for rotation and implement graceful handling.
</p>
</div>
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-lg hover:shadow-purple-500/30 hover:scale-105 transition-all">
<div className="text-3xl mb-4">🚫</div>
<h4 className="text-lg font-bold text-white mb-2">Server-Side Only</h4>
<p className="text-sm text-gray-400">
Never use API keys in client-side code. Always make requests from your backend.
</p>
</div>
<div className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-lg hover:shadow-cyan-500/30 hover:scale-105 transition-all">
<div className="text-3xl mb-4">👁</div>
<h4 className="text-lg font-bold text-white mb-2">Monitor Usage</h4>
<p className="text-sm text-gray-400">
Track API key usage patterns. Unusual activity may indicate a compromised key.
</p>
</div>
</div>
</section>
{/* Rate Limits */}
<section id="rate-limits" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl"></span>
<h2 className="text-3xl font-bold text-white">Rate Limits</h2>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
To ensure fair usage and system stability, all API keys are subject to rate limits:
</p>
<div className="overflow-hidden border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
<table className="w-full">
<thead>
<tr className="bg-slate-950/80 border-b-2 border-purple-500/20">
<th className="text-left py-4 px-6 text-purple-400 font-bold">Key Type</th>
<th className="text-left py-4 px-6 text-purple-400 font-bold">Limit</th>
<th className="text-left py-4 px-6 text-purple-400 font-bold">Window</th>
</tr>
</thead>
<tbody className="text-gray-300 bg-slate-900/50">
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-semibold">Master Key</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-purple-500/20 text-purple-400 rounded-lg font-mono font-bold border-2 border-purple-500/40">
500 requests
</span>
</td>
<td className="py-4 px-6">per hour</td>
</tr>
<tr className="border-b border-slate-800">
<td className="py-4 px-6 font-semibold">Project Key</td>
<td className="py-4 px-6">
<span className="px-3 py-1.5 bg-cyan-500/20 text-cyan-400 rounded-lg font-mono font-bold border-2 border-cyan-500/40">
100 requests
</span>
</td>
<td className="py-4 px-6">per hour</td>
</tr>
</tbody>
</table>
</div>
<div className="mt-6 p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-xl shadow-cyan-500/20">
<div className="flex items-start gap-3">
<span className="text-2xl">💬</span>
<div>
<p className="text-sm font-bold text-cyan-300 mb-1">Need Higher Limits?</p>
<p className="text-sm text-cyan-200">
Contact our sales team to discuss enterprise plans with custom rate limits.
</p>
</div>
</div>
</div>
</section>
</DocsLayoutC>
);
}

View File

@ -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 (
<DocsLayoutC
sidebar={<DocsSidebarC currentPath="/docs/variant-c" />}
toc={<DocsTOCC items={tocItems} />}
>
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
{/* Hero Section - Large and Colorful */}
<div className="mb-12">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/20 to-cyan-500/20 border-2 border-purple-500/40 mb-6">
<span className="text-2xl">🚀</span>
<span className="text-sm font-bold text-white">START HERE</span>
</div>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 bg-gradient-to-r from-purple-400 to-cyan-400 bg-clip-text text-transparent">
Getting Started
</h1>
<p className="text-xl text-gray-300 leading-relaxed">
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
generation into your applications in minutes.
</p>
</div>
{/* Introduction */}
<section id="introduction" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">👋</span>
<h2 className="text-3xl font-bold text-white">Introduction</h2>
</div>
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
<p className="text-gray-300 leading-relaxed mb-4">
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.
</p>
<p className="text-gray-300 leading-relaxed">
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.
</p>
</div>
</section>
{/* Quick Start */}
<section id="quick-start" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl"></span>
<h2 className="text-3xl font-bold text-white">Quick Start</h2>
</div>
<div id="installation" className="mb-8">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">📦</span>
<h3 className="text-2xl font-semibold text-white">Installation</h3>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
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.
</p>
<CodeBlock
code={`# Using npm (JavaScript/TypeScript)
npm install @banatie/sdk
# Using pip (Python)
pip install banatie
# Using Go
go get github.com/banatie/sdk-go`}
language="bash"
filename="Installation"
/>
</div>
<div id="authentication" className="mb-8">
<div className="flex items-center gap-2 mb-4">
<span className="text-2xl">🔑</span>
<h3 className="text-2xl font-semibold text-white">Authentication</h3>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
All API requests require an API key. You can create an API key from your dashboard or
using the bootstrap endpoint for initial setup.
</p>
<div className="p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/40 rounded-2xl mb-6 shadow-xl shadow-amber-500/20">
<div className="flex items-start gap-3">
<span className="text-2xl">💡</span>
<div>
<p className="text-sm font-bold text-amber-300 mb-2">Security Tip</p>
<p className="text-sm text-amber-200">
Keep your API keys secure. Never commit them to public repositories or expose them
in client-side code.
</p>
</div>
</div>
</div>
<CodeBlock
code={`# Create your first API key (one-time bootstrap)
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
# Save the returned key securely
export BANATIE_API_KEY="bnt_your_key_here"`}
language="bash"
filename="Get API Key"
/>
</div>
</section>
{/* First Request */}
<section id="first-request" className="mb-12">
<div className="flex items-center gap-3 mb-6">
<span className="text-3xl">🎨</span>
<h2 className="text-3xl font-bold text-white">Your First Request</h2>
</div>
<p className="text-gray-300 leading-relaxed mb-6">
Let's generate your first image! This example uses curl, but you can use any HTTP client
or our SDKs.
</p>
<CodeBlock
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
-H "X-API-Key: YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"prompt": "a serene mountain landscape at sunset",
"filename": "mountain_sunset",
"aspectRatio": "16:9",
"autoEnhance": true
}'`}
language="bash"
filename="Generate Image"
/>
<div className="mt-6 p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-xl shadow-cyan-500/20">
<div className="flex items-start gap-3 mb-4">
<span className="text-2xl"></span>
<p className="text-sm font-bold text-cyan-300">Expected Response:</p>
</div>
<pre className="text-sm text-gray-300 overflow-x-auto bg-slate-950/50 p-4 rounded-xl border-2 border-cyan-500/20">
<code>{`{
"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..."
}
}
}`}</code>
</pre>
</div>
</section>
{/* Next Steps */}
<section id="next-steps" className="mb-12">
<div className="flex items-center gap-3 mb-8">
<span className="text-3xl">🎯</span>
<h2 className="text-3xl font-bold text-white">Next Steps</h2>
</div>
<div className="grid md:grid-cols-2 gap-6">
<a
href="/docs/variant-c/api/text-to-image"
className="group p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl hover:border-purple-500/60 transition-all duration-300 shadow-lg hover:shadow-purple-500/30 hover:scale-105"
>
<div className="text-3xl mb-4">📚</div>
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-purple-400 transition-colors">
API Reference
</h3>
<p className="text-sm text-gray-400">
Explore all available endpoints, parameters, and response formats.
</p>
</a>
<a
href="/docs/variant-c/guides/authentication"
className="group p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl hover:border-cyan-500/60 transition-all duration-300 shadow-lg hover:shadow-cyan-500/30 hover:scale-105"
>
<div className="text-3xl mb-4">🔐</div>
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-cyan-400 transition-colors">
Authentication Guide
</h3>
<p className="text-sm text-gray-400">
Learn about API keys, rate limits, and security best practices.
</p>
</a>
<a
href="/docs/variant-c/examples"
className="group p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 rounded-2xl hover:border-amber-500/60 transition-all duration-300 shadow-lg hover:shadow-amber-500/30 hover:scale-105"
>
<div className="text-3xl mb-4">💡</div>
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-amber-400 transition-colors">
Examples
</h3>
<p className="text-sm text-gray-400">
Browse code examples and use cases for common scenarios.
</p>
</a>
<a
href="/docs/variant-c/guides/error-handling"
className="group p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl hover:border-purple-500/60 transition-all duration-300 shadow-lg hover:shadow-purple-500/30 hover:scale-105"
>
<div className="text-3xl mb-4"></div>
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-purple-400 transition-colors">
Error Handling
</h3>
<p className="text-sm text-gray-400">
Understand error codes and how to handle failures gracefully.
</p>
</a>
</div>
</section>
{/* Fun CTA Card */}
<div className="mt-12 p-8 bg-gradient-to-br from-purple-500/20 via-cyan-500/20 to-amber-500/20 border-2 border-purple-500/40 rounded-2xl shadow-2xl shadow-purple-500/30 text-center">
<div className="text-4xl mb-4">🎉</div>
<h3 className="text-2xl font-bold text-white mb-3">Ready to Build Something Amazing?</h3>
<p className="text-gray-300 mb-6">
Start creating stunning AI-generated images for your applications today!
</p>
<a
href="/docs/variant-c/api/text-to-image"
className="inline-flex items-center gap-2 px-8 py-4 bg-gradient-to-r from-purple-600 to-cyan-600 hover:from-purple-500 hover:to-cyan-500 text-white font-bold rounded-xl transition-all duration-300 shadow-lg hover:shadow-purple-500/50 hover:scale-105"
>
<span></span>
<span>Explore the API</span>
</a>
</div>
</DocsLayoutC>
);
}

View File

@ -1,202 +0,0 @@
'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 <code>: 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
* <EndpointCard
* method="POST"
* endpoint="/api/text-to-image"
* baseUrl="https://api.banatie.com"
* />
*
* // Different HTTP methods
* <EndpointCard
* method="GET"
* endpoint="/api/images"
* />
*
* <EndpointCard
* method="DELETE"
* endpoint="/api/admin/keys/:keyId"
* />
*
* // Custom base URL
* <EndpointCard
* method="PUT"
* endpoint="/api/projects/:id"
* baseUrl="https://api.custom-domain.com"
* />
* ```
*
* ## 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
* <EndpointCard
* method="POST"
* endpoint="/api/text-to-image"
* baseUrl="https://api.banatie.com"
* />
*/
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 (
<div
className={`
p-4
bg-slate-900/50
border border-slate-700
rounded-xl
${className}
`}
>
{/* Method + Endpoint Row */}
<div className="flex items-center gap-3 mb-2">
<MethodBadge method={method} />
<code className="text-sm text-white">{endpoint}</code>
</div>
{/* Base URL */}
<p className="text-xs text-gray-400">
Base URL: <code className="text-purple-400">{baseUrl}</code>
</p>
</div>
);
};

View File

@ -1,185 +0,0 @@
'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 (<h1> 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
* <Hero
* title="Text to Image"
* subtitle="Generate high-quality images from text prompts using AI-powered models."
* />
*
* // Documentation home page
* <Hero
* size="large"
* title="Welcome to Banatie API Documentation"
* subtitle="Learn how to integrate AI-powered image generation into your applications in minutes."
* />
*
* // Guide page
* <Hero
* title="Authentication"
* subtitle="Learn how to authenticate with the Banatie API using API keys, manage rate limits, and implement security best practices."
* />
* ```
*
* ## 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
* <Hero
* title="Getting Started"
* subtitle="Welcome to the Banatie API documentation."
* size="default"
* />
*/
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<HeroSize, string> = {
default: 'text-4xl md:text-5xl',
large: 'text-5xl md:text-6xl',
};
/**
* Spacing system for bottom margin
*/
const spacingSizes: Record<HeroSize, string> = {
default: 'mb-12',
large: 'mb-16',
};
export const Hero = ({
title,
subtitle,
size = 'default',
className = '',
}: HeroProps) => {
return (
<div className={`${spacingSizes[size]} ${className}`}>
<h1 className={`${titleSizes[size]} font-bold text-white mb-4`}>
{title}
</h1>
<p className="text-xl text-gray-400 leading-relaxed">
{subtitle}
</p>
</div>
);
};

View File

@ -1,156 +0,0 @@
'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 <InlineCode>API_KEY</InlineCode> environment variable.
*
* // With semantic colors
* The response includes <InlineCode color="success">status: 200</InlineCode>.
* Avoid using <InlineCode color="error">hardcoded credentials</InlineCode>.
* Include the <InlineCode color="neutral">X-API-Key</InlineCode> header.
*
* // Parameter documentation
* The <InlineCode>autoEnhance</InlineCode> parameter defaults to false.
*
* // Error messages
* If you receive <InlineCode color="error">401 Unauthorized</InlineCode>, 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
* <InlineCode color="primary">apiKey</InlineCode>
*/
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<InlineCodeColor, string> = {
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 (
<code
className={`
inline-block
px-1.5 py-0.5
bg-slate-800
rounded
font-mono text-sm
${colorStyles[color]}
${className}
`}
>
{children}
</code>
);
};

View File

@ -1,281 +0,0 @@
'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 (<a> 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
* <LinkCard
* href="/docs/api/text-to-image"
* title="API Reference"
* description="Explore all available endpoints, parameters, and response formats."
* accent="primary"
* />
*
* // Getting started
* <LinkCard
* href="/docs/quick-start"
* title="Quick Start"
* description="Get up and running with Banatie API in 5 minutes."
* accent="success"
* />
*
* // Supporting guide
* <LinkCard
* href="/docs/guides/authentication"
* title="Authentication Guide"
* description="Learn about API keys, rate limits, and security best practices."
* accent="secondary"
* />
*
* // Important notice
* <LinkCard
* href="/docs/migration"
* title="Migration Guide"
* description="Upgrade to v2 API with this step-by-step migration guide."
* accent="warning"
* />
* ```
*
* ## 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
* <LinkCard
* href="/docs/api"
* title="API Reference"
* description="Complete API documentation"
* accent="primary"
* />
*/
/**
* 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<LinkCardAccent, {
gradient: string;
hoverBorder: string;
hoverText: string;
}> = {
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 (
<a
href={href}
className={`
block
p-5
bg-gradient-to-br ${styles.gradient} to-transparent
border border-slate-700/50
rounded-xl
${styles.hoverBorder}
transition-colors
group
${className}
`}
>
{icon && (
<div className="text-2xl mb-3">{icon}</div>
)}
<h3
className={`
text-lg font-semibold text-white mb-2
${styles.hoverText}
transition-colors
`}
>
{title}
</h3>
<p className="text-sm text-gray-400">
{description}
</p>
</a>
);
};

View File

@ -1,216 +0,0 @@
'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
* <LinkCardGrid columns={2}>
* <LinkCard
* href="/docs/api"
* title="API Reference"
* description="Explore all endpoints"
* accent="primary"
* />
* <LinkCard
* href="/docs/guides"
* title="Guides"
* description="Learn best practices"
* accent="secondary"
* />
* </LinkCardGrid>
*
* // Three-column resource hub
* <LinkCardGrid columns={3}>
* <LinkCard href="..." title="Getting Started" accent="success" description="..." />
* <LinkCard href="..." title="API Docs" accent="primary" description="..." />
* <LinkCard href="..." title="Examples" accent="secondary" description="..." />
* </LinkCardGrid>
*
* // Four-column comprehensive navigation
* <LinkCardGrid columns={4}>
* <LinkCard href="..." title="Text to Image" accent="primary" description="..." />
* <LinkCard href="..." title="Upload" accent="primary" description="..." />
* <LinkCard href="..." title="Authentication" accent="secondary" description="..." />
* <LinkCard href="..." title="Rate Limits" accent="secondary" description="..." />
* </LinkCardGrid>
* ```
*
* ## 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
* <LinkCardGrid columns={2}>
* {children}
* </LinkCardGrid>
*/
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<GridColumns, string> = {
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 (
<div
className={`
grid
grid-cols-1
${columnStyles[columns]}
gap-4
${className}
`}
>
{children}
</div>
);
};

View File

@ -1,181 +0,0 @@
'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
* <MethodBadge method="GET" /> /api/users
* <MethodBadge method="POST" /> /api/users
*
* // With size variants
* <MethodBadge method="DELETE" size="sm" />
* <MethodBadge method="PUT" size="md" />
*
* // In endpoint cards
* <div className="flex items-center gap-2">
* <MethodBadge method="POST" />
* <code>/api/text-to-image</code>
* </div>
* ```
*
* ## 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
* <MethodBadge method="POST" size="md" />
*/
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<HttpMethod, string> = {
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<MethodBadgeSize, string> = {
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<HttpMethod, string> = {
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 (
<span
className={`
inline-flex items-center justify-center
rounded border font-bold
${methodStyles[method]}
${sizeStyles[size]}
${className}
`}
role="status"
aria-label={methodLabels[method]}
>
{method}
</span>
);
};

View File

@ -1,244 +0,0 @@
'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)
*
* <pre><code>
* Response content
* ...
* </code></pre>
*
* ```
*
* 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>): Code appearance
* - overflow-x-auto: Handles long lines gracefully
*
* ## Usage Examples
*
* ```tsx
* // Success response with title
* <ResponseBlock
* status="success"
* statusCode={200}
* title="Expected Response:"
* content={`{
* "success": true,
* "data": { ... }
* }`}
* />
*
* // Error response without title
* <ResponseBlock
* status="error"
* statusCode={401}
* content={`{
* "error": "Unauthorized",
* "message": "Invalid API key"
* }`}
* />
*
* // Custom status label
* <ResponseBlock
* status="success"
* statusCode={201}
* statusLabel="✓ 201 Created"
* content="{ ... }"
* />
* ```
*
* ## 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 (<pre><code>)
* - 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
* <ResponseBlock
* status="success"
* statusCode={200}
* title="Success Response"
* content={jsonString}
* />
*/
import { StatusBadge, StatusType } from './StatusBadge';
/**
* Props for the ResponseBlock component
*/
export interface ResponseBlockProps {
/** Status type determining color scheme */
status: Extract<StatusType, 'success' | 'error'>;
/** 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 (
<div
className={`
relative
p-4
border rounded-xl
${statusStyles[status]}
${className}
`}
>
{/* Status Badge - Floating Top Right */}
<div className="absolute top-3 right-3">
<StatusBadge status={status} size="sm">
{label}
</StatusBadge>
</div>
{/* Optional Title */}
{title && (
<p className="text-sm font-semibold text-gray-300 mb-3">{title}</p>
)}
{/* Response Content */}
<pre className={`text-xs text-gray-300 overflow-x-auto ${title || statusLabel ? 'mt-6' : ''}`}>
<code>{content}</code>
</pre>
</div>
);
};

View File

@ -1,199 +0,0 @@
'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)
* <SectionHeader level={2} id="overview">
* Overview
* </SectionHeader>
*
* // Subsection heading (h3)
* <SectionHeader level={3} id="key-types">
* Key Types
* </SectionHeader>
*
* // Custom spacing with className
* <SectionHeader level={2} id="parameters" className="mb-6">
* Parameters
* </SectionHeader>
* ```
*
* ## 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
* <SectionHeader level={2} id="getting-started">
* Getting Started
* </SectionHeader>
*/
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<SectionHeaderLevel, string> = {
2: 'text-3xl font-bold',
3: 'text-xl font-semibold',
};
/**
* Default spacing system for bottom margins
*/
const defaultSpacing: Record<SectionHeaderLevel, string> = {
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 (
<Tag
id={id}
className={`
${levelStyles[level]}
text-white
${spacing}
${className || ''}
`}
>
{children}
</Tag>
);
};

View File

@ -1,176 +0,0 @@
'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
* <StatusBadge status="success" size="sm">200 OK</StatusBadge>
* <StatusBadge status="error" size="sm">500 Error</StatusBadge>
*
* // API States
* <StatusBadge status="info">Beta</StatusBadge>
* <StatusBadge status="warning">Deprecated</StatusBadge>
*
* // System Status
* <StatusBadge status="success"> Active</StatusBadge>
* <StatusBadge status="neutral">Pending</StatusBadge>
* ```
*
* @component
* @example
* <StatusBadge status="success" size="md">200 Success</StatusBadge>
*/
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<StatusType, string> = {
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<StatusSize, string> = {
sm: 'px-2 py-0.5 text-xs',
md: 'px-3 py-1 text-xs',
};
/**
* Human-readable labels for screen readers
*/
const statusLabels: Record<StatusType, string> = {
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 (
<span
className={`
inline-flex items-center justify-center
rounded-full font-bold
${statusStyles[status]}
${sizeStyles[size]}
${className}
`}
role="status"
aria-label={statusLabels[status]}
>
{children}
</span>
);
};

View File

@ -1,176 +0,0 @@
/**
* 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 (
* <>
* <Hero
* title="Text to Image API"
* subtitle="Generate images from text prompts"
* />
*
* <SectionHeader level={2} id="endpoint">
* Endpoint
* </SectionHeader>
*
* <EndpointCard
* method="POST"
* endpoint="/api/text-to-image"
* />
*
* <SectionHeader level={2} id="response">
* Response
* </SectionHeader>
*
* <ResponseBlock
* status="success"
* statusCode={200}
* content={responseJSON}
* />
*
* <SectionHeader level={2} id="next-steps">
* Next Steps
* </SectionHeader>
*
* <LinkCardGrid columns={2}>
* <LinkCard
* href="/docs/guides"
* title="Guides"
* description="Learn best practices"
* accent="secondary"
* />
* <LinkCard
* href="/docs/examples"
* title="Examples"
* description="See code samples"
* accent="primary"
* />
* </LinkCardGrid>
* </>
* );
* }
* ```
*
* ## 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';

View File

@ -1,7 +1,7 @@
'use client';
/**
* Documentation Layout - Production Version
* Documentation Layout - Final Variant
*
* 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 DocsLayoutProps {
interface DocsLayoutFinalProps {
sidebar: ReactNode;
children: ReactNode;
toc: ReactNode;
}
export const DocsLayout = ({ sidebar, children, toc }: DocsLayoutProps) => {
export const DocsLayoutFinal = ({ sidebar, children, toc }: DocsLayoutFinalProps) => {
return (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
{/* Animated gradient background (matching landing page) */}

View File

@ -1,7 +1,7 @@
'use client';
/**
* Documentation Sidebar - Production Version
* Documentation Sidebar - Final Variant
*
* Based on Variant A with FIXED active states
*
@ -33,44 +33,44 @@ interface NavItem {
children?: NavItem[];
}
interface DocsSidebarProps {
interface DocsSidebarFinalProps {
currentPath: string;
}
const navigationItems: NavItem[] = [
{
label: 'Getting Started',
href: '/docs',
href: '/docs/final',
icon: '🚀',
},
{
label: 'API Reference',
href: '/docs/api',
href: '/docs/final/api',
icon: '📚',
children: [
{ label: 'Text to Image', href: '/docs/api/text-to-image' },
{ label: 'Upload', href: '/docs/api/upload' },
{ label: 'Images', href: '/docs/api/images' },
{ 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/guides',
href: '/docs/final/guides',
icon: '📖',
children: [
{ label: 'Authentication', href: '/docs/guides/authentication' },
{ label: 'Error Handling', href: '/docs/guides/error-handling' },
{ label: 'Rate Limits', href: '/docs/guides/rate-limits' },
{ 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/examples',
href: '/docs/final/examples',
icon: '💡',
},
];
export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => {
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
const toggleSection = (label: string) => {
@ -87,7 +87,7 @@ export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
{/* Logo/Title */}
<div className="mb-8">
<h2 className="text-lg font-semibold text-white">Documentation</h2>
<p className="text-xs text-gray-500 mt-1">API Reference</p>
<p className="text-xs text-gray-500 mt-1">Final: Production</p>
</div>
{/* Navigation Items */}
@ -170,8 +170,8 @@ export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
<div className="mt-12 pt-6 border-t border-slate-800">
<ul className="space-y-2 text-sm">
<li>
<a href="/" className="text-gray-500 hover:text-gray-300 transition-colors">
Back to home
<a href="/docs" className="text-gray-500 hover:text-gray-300 transition-colors">
Back to variants
</a>
</li>
</ul>

View File

@ -1,7 +1,7 @@
'use client';
/**
* Table of Contents - Production Version
* Table of Contents - Final Variant
*
* Based on Variant A: Clean & Minimal (no changes needed)
*
@ -26,11 +26,11 @@ interface TocItem {
level: number;
}
interface DocsTOCProps {
interface DocsTOCFinalProps {
items: TocItem[];
}
export const DocsTOC = ({ items }: DocsTOCProps) => {
export const DocsTOCFinal = ({ items }: DocsTOCFinalProps) => {
const [activeId, setActiveId] = useState<string>('');
useEffect(() => {

View File

@ -1,9 +1,9 @@
'use client';
/**
* Interactive API Widget - Production Version
* Interactive API Widget - Final Variant (Redesigned)
*
* Minimized layout with clean design system:
* Minimized layout inspired by Variant C with Final variant 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 InteractiveAPIWidgetProps {
interface InteractiveAPIWidgetFinalProps {
endpoint: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
description: string;
@ -26,32 +26,32 @@ interface InteractiveAPIWidgetProps {
}>;
}
type Language = 'curl' | 'javascript' | 'python' | 'go' | 'js-sdk' | 'mcp';
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 getMethodBadgeStyle = (method: string): string => {
const getMethodColor = (method: string): string => {
switch (method) {
case 'GET':
return 'bg-cyan-600/20 text-cyan-400 border border-cyan-500/40';
return 'from-cyan-500 to-cyan-600';
case 'POST':
return 'bg-green-600/20 text-green-400 border border-green-500/40';
return 'from-purple-500 to-purple-600';
case 'PUT':
return 'bg-amber-600/20 text-amber-400 border border-amber-500/40';
return 'from-amber-500 to-amber-600';
case 'DELETE':
return 'bg-red-600/20 text-red-400 border border-red-500/40';
return 'from-red-500 to-red-600';
default:
return 'bg-slate-600/20 text-slate-400 border border-slate-500/40';
return 'from-purple-500 to-cyan-500';
}
};
export const InteractiveAPIWidget = ({
export const InteractiveAPIWidgetFinal = ({
endpoint,
method,
description,
parameters = [],
}: InteractiveAPIWidgetProps) => {
}: InteractiveAPIWidgetFinalProps) => {
const [language, setLanguage] = useState<Language>('curl');
const [apiKey, setApiKey] = useState('');
const [isExecuting, setIsExecuting] = useState(false);
@ -96,33 +96,10 @@ export const InteractiveAPIWidget = ({
};
}, [parameters]);
// Get language display name
const getLanguageLabel = (lang: Language): string => {
switch (lang) {
case 'curl':
return 'cURL';
case 'javascript':
return 'JavaScript';
case 'python':
return 'Python';
case 'go':
return 'Go';
case 'js-sdk':
return 'JS SDK';
case 'mcp':
return 'MCP';
}
};
// Generate code examples
const generateCode = (): string => {
const url = `${API_BASE_URL}${endpoint}`;
// Coming soon placeholders
if (language === 'js-sdk' || language === 'mcp') {
return `# Coming soon\n# ${getLanguageLabel(language)} integration is under development`;
}
switch (language) {
case 'curl':
return `curl -X ${method} "${url}" \\
@ -274,52 +251,59 @@ func main() {
return (
<>
{/* Minimized Widget */}
<div className="my-8 bg-slate-900/50 backdrop-blur-sm border border-slate-700/50 rounded-2xl overflow-hidden">
<div className="my-8 bg-slate-900/50 backdrop-blur-sm border border-purple-500/30 rounded-2xl overflow-hidden shadow-xl">
{/* Header */}
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-slate-700/50">
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-purple-500/30">
<div className="flex items-center gap-3">
<div className={`px-3 py-1 rounded text-xs font-bold ${getMethodBadgeStyle(method)}`}>
<div className={`px-3 py-1.5 rounded-lg bg-gradient-to-r ${getMethodColor(method)} text-white text-sm font-bold shadow-lg`}>
{method}
</div>
<code className="text-sm text-gray-400">{endpoint}</code>
</div>
<button
onClick={() => setIsExpanded(true)}
className="flex items-center gap-2 px-4 py-2 bg-cyan-600/10 hover:bg-cyan-600/20 text-cyan-400 rounded-lg transition-all text-sm font-medium border border-cyan-500/30 hover:border-cyan-500/50"
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 border-cyan-500/40 hover:border-cyan-500/60"
>
<span></span>
<span>Expand</span>
Expand
</button>
</div>
{/* Code Section - Full Width */}
<div className="p-6">
{/* Language Tabs */}
<div className="flex items-center gap-2 mb-4 flex-wrap">
{(['curl', 'javascript', 'python', 'go', 'js-sdk', 'mcp'] as Language[]).map((lang) => (
<div className="flex items-center gap-2 mb-4">
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => {
const colors = ['purple', 'cyan', 'amber', 'purple'];
const color = colors[idx];
return (
<button
key={lang}
onClick={() => setLanguage(lang)}
className={`px-3 py-1.5 text-xs rounded-lg font-medium transition-all border ${
className={`px-4 py-2 text-sm rounded-xl font-semibold transition-all border ${
language === lang
? 'bg-slate-700 text-white border-slate-600'
: 'bg-slate-800/50 text-gray-400 border-slate-700/50 hover:border-slate-600 hover:text-gray-300'
? color === 'purple'
? 'bg-purple-500/30 text-white border-purple-500/60 shadow-lg shadow-purple-500/20'
: color === 'cyan'
? 'bg-cyan-500/30 text-white border-cyan-500/60 shadow-lg shadow-cyan-500/20'
: 'bg-amber-500/30 text-white border-amber-500/60 shadow-lg shadow-amber-500/20'
: 'bg-slate-800/30 text-gray-400 border-slate-700 hover:border-slate-600 hover:text-white'
}`}
>
{getLanguageLabel(lang)}
{lang === 'javascript' ? 'JS' : lang.toUpperCase()}
</button>
))}
);
})}
</div>
{/* Code Display */}
<div className="border border-slate-700/50 rounded-xl overflow-hidden">
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-slate-700/50">
<span className="text-xs text-gray-400 font-medium">Code Example</span>
<div className="border border-cyan-500/30 rounded-xl overflow-hidden shadow-lg">
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-cyan-500/20">
<span className="text-xs text-cyan-400 font-semibold">Code Example</span>
<button
onClick={copyCode}
className="text-xs text-gray-400 hover:text-white transition-colors font-medium"
className="px-3 py-1.5 text-xs bg-purple-600/30 hover:bg-purple-600/50 text-purple-300 rounded-lg transition-all font-semibold"
>
Copy
📋 Copy
</button>
</div>
<div className="p-4 bg-slate-950/50 max-h-80 overflow-auto">
@ -331,43 +315,50 @@ func main() {
</div>
{/* Footer */}
<div className="flex items-center justify-between px-6 pb-6">
<div className="grid grid-cols-2 gap-4 px-6 pb-6">
<button
onClick={expandApiKey}
className="text-sm text-gray-400 hover:text-white underline-offset-4 hover:underline transition-colors"
className="flex items-center gap-2 px-4 py-2.5 bg-slate-800/50 hover:bg-slate-800 border border-slate-700 rounded-lg text-gray-400 hover:text-white text-sm transition-colors"
>
{apiKey ? 'API Key Set' : 'Enter API Key'}
<span>🔑</span>
<span>{apiKey ? 'API Key Set' : 'Enter API Key'}</span>
</button>
<button
onClick={executeRequest}
disabled={!apiKey || isExecuting}
className="px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-sm font-medium transition-all disabled:opacity-50 disabled:cursor-not-allowed"
className="px-4 py-2.5 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-lg hover:shadow-purple-500/30"
>
{isExecuting ? 'Executing...' : 'Try It'}
{isExecuting ? 'Executing...' : 'Try It'}
</button>
</div>
{/* Inline Response (if any) */}
{(response || error) && (
<div className="border-t border-slate-700/50 p-6 bg-slate-950/50">
<h4 className="text-sm font-semibold text-white mb-3">
<div className="border-t border-purple-500/30 p-6 bg-slate-950/50">
<h4 className="text-sm font-semibold text-white mb-3 flex items-center gap-2">
<span>📦</span>
Response
</h4>
{error ? (
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm">
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm shadow-lg shadow-red-500/10">
<div className="flex items-start gap-2">
<span></span>
<div>
<p className="font-semibold mb-1">Error</p>
<p className="text-xs">{error}</p>
</div>
</div>
</div>
) : (
<div className={`p-4 rounded-xl ${
<div className={`p-4 rounded-xl border ${
isSuccess
? 'bg-green-500/5 border border-green-500/30'
: 'bg-slate-800/50 border border-slate-700'
? 'bg-green-500/5 border-green-500/40 shadow-lg shadow-green-500/10'
: 'bg-slate-800/50 border-slate-700'
}`}>
{isSuccess && (
<div className="flex items-center gap-2 mb-3">
<span className="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded border border-green-500/40">
200 Success
<span className="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded-full border border-green-500/40">
200 Success
</span>
</div>
)}
@ -383,59 +374,63 @@ func main() {
{/* Expanded Modal */}
{isExpanded && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm">
<div className="relative w-[90vw] h-[85vh] bg-slate-900 border border-slate-700/50 rounded-2xl shadow-2xl overflow-hidden flex flex-col">
<div className="relative w-[90vw] h-[85vh] bg-slate-900 border border-purple-500/30 rounded-2xl shadow-2xl overflow-hidden flex flex-col">
{/* Modal Header */}
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-slate-700/50">
<div className="flex items-center gap-4">
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-purple-500/30">
<div className="flex items-center gap-3">
<div className={`px-3 py-1 rounded text-xs font-bold ${getMethodBadgeStyle(method)}`}>
<div className={`px-3 py-1.5 rounded-lg bg-gradient-to-r ${getMethodColor(method)} text-white text-sm font-bold shadow-lg`}>
{method}
</div>
<code className="text-sm text-gray-400">{endpoint}</code>
</div>
<span className="text-xs text-gray-500"></span>
<p className="text-xs text-gray-500">{description}</p>
</div>
<button
onClick={() => setIsExpanded(false)}
className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-gray-400 hover:text-white rounded-lg transition-all text-sm font-medium"
className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-gray-400 hover:text-white rounded-lg transition-all text-sm font-semibold"
>
Close
Close
</button>
</div>
{/* Two-Panel Layout */}
<div className="grid grid-cols-2 gap-6 p-6 flex-1 overflow-hidden">
{/* Left: Code */}
<div className="flex flex-col h-full min-h-0">
<div className="flex items-center gap-2 mb-4 flex-wrap min-h-[32px] flex-shrink-0">
{(['curl', 'javascript', 'python', 'go', 'js-sdk', 'mcp'] as Language[]).map((lang) => (
<div className="flex flex-col overflow-hidden">
<div className="flex items-center gap-2 mb-4">
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => {
const colors = ['purple', 'cyan', 'amber', 'purple'];
const color = colors[idx];
return (
<button
key={lang}
onClick={() => setLanguage(lang)}
className={`px-3 py-1.5 text-xs rounded-lg font-medium transition-all border ${
className={`px-4 py-2 text-sm rounded-xl font-semibold transition-all border ${
language === lang
? 'bg-slate-700 text-white border-slate-600'
: 'bg-slate-800/50 text-gray-400 border-slate-700/50 hover:border-slate-600 hover:text-gray-300'
? color === 'purple'
? 'bg-purple-500/30 text-white border-purple-500/60 shadow-lg shadow-purple-500/20'
: color === 'cyan'
? 'bg-cyan-500/30 text-white border-cyan-500/60 shadow-lg shadow-cyan-500/20'
: 'bg-amber-500/30 text-white border-amber-500/60 shadow-lg shadow-amber-500/20'
: 'bg-slate-800/30 text-gray-400 border-slate-700 hover:border-slate-600 hover:text-white'
}`}
>
{getLanguageLabel(lang)}
{lang === 'javascript' ? 'JS' : lang.toUpperCase()}
</button>
))}
);
})}
</div>
<div className="border border-slate-700/50 rounded-xl overflow-hidden flex-1 flex flex-col min-h-0">
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-slate-700/50 flex-shrink-0">
<span className="text-xs text-gray-400 font-medium">Code Example</span>
<div className="border border-cyan-500/30 rounded-xl overflow-hidden shadow-lg flex-1 flex flex-col">
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-cyan-500/20">
<span className="text-xs text-cyan-400 font-semibold">Code Example</span>
<button
onClick={copyCode}
className="text-xs text-gray-400 hover:text-white transition-colors font-medium"
className="px-3 py-1.5 text-xs bg-purple-600/30 hover:bg-purple-600/50 text-purple-300 rounded-lg transition-all font-semibold"
>
Copy
📋 Copy
</button>
</div>
<div className="p-4 bg-slate-950/50 overflow-auto flex-1 min-h-0">
<pre className="text-sm text-gray-300 leading-relaxed">
<div className="p-4 bg-slate-950/50 overflow-auto flex-1">
<pre className="text-base text-gray-300 leading-relaxed">
<code>{generateCode()}</code>
</pre>
</div>
@ -443,31 +438,37 @@ func main() {
</div>
{/* Right: Response */}
<div className="flex flex-col h-full min-h-0">
<h4 className="text-sm font-semibold text-white mb-4 min-h-[32px] flex items-center flex-shrink-0">
<div className="flex flex-col overflow-hidden">
<h4 className="text-sm font-semibold text-white mb-4 flex items-center gap-2">
<span>📦</span>
Response
</h4>
<div className="border border-slate-700/50 rounded-xl overflow-hidden flex-1 flex flex-col min-h-0">
<div className="bg-slate-950/80 px-4 py-3 border-b border-slate-700/50 flex-shrink-0">
<div className="border border-purple-500/30 rounded-xl overflow-hidden shadow-lg flex-1 flex flex-col">
<div className="bg-slate-950/80 px-4 py-3 border-b border-purple-500/20">
{response && (
<span
className={`inline-flex items-center gap-2 px-3 py-1 rounded text-xs font-bold ${
className={`inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-bold ${
response.success
? 'bg-green-500/20 text-green-400 border border-green-500/40'
: 'bg-red-500/20 text-red-400 border border-red-500/40'
? 'bg-green-500/20 text-green-400 border border-green-500/40 shadow-lg shadow-green-500/10'
: 'bg-red-500/20 text-red-400 border border-red-500/40 shadow-lg shadow-red-500/10'
}`}
>
{response.success ? 'Success' : 'Error'}
{response.success ? 'Success' : 'Error'}
</span>
)}
</div>
<div className="p-4 bg-slate-950/50 overflow-auto flex-1 min-h-0">
<div className="p-4 bg-slate-950/50 overflow-auto flex-1">
{error ? (
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm">
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm shadow-lg shadow-red-500/10">
<div className="flex items-start gap-2">
<span className="text-xl"></span>
<div>
<p className="font-semibold mb-1">Error</p>
<p className="text-xs">{error}</p>
</div>
</div>
</div>
) : response ? (
<pre className="text-sm text-gray-300 leading-relaxed">
<code>{JSON.stringify(response, null, 2)}</code>
@ -475,8 +476,9 @@ func main() {
) : (
<div className="flex items-center justify-center h-full">
<div className="text-center">
<p className="text-4xl mb-3">🚀</p>
<p className="text-sm text-gray-500">
Click <strong className="text-white">"Try It"</strong> below to see the response
Click <strong className="text-purple-400">"Try It"</strong> below to see the response
</p>
</div>
</div>
@ -488,12 +490,17 @@ func main() {
<button
onClick={executeRequest}
disabled={!apiKey || isExecuting}
className="mt-4 px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-sm font-medium transition-all disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0"
className="mt-4 px-6 py-3 rounded-xl bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-base font-bold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-2xl hover:shadow-purple-500/50"
>
{isExecuting ? 'Executing...' : 'Try It'}
{isExecuting ? 'Executing...' : 'Try It Now'}
</button>
</div>
</div>
{/* Footer hint */}
<div className="px-6 pb-4 text-center">
<p className="text-xs text-gray-500">{description}</p>
</div>
</div>
</div>
)}

View File

@ -1,142 +0,0 @@
'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
*
* 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.
*
* Usage:
* ```tsx
* <DocPage
* breadcrumbItems={[...]}
* tocItems={[...]}
* nextSteps={{ description: "...", links: [...] }}
* >
* <Hero ... />
* <section>...</section>
* </DocPage>
* ```
*/
import { ReactNode } from 'react';
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
import { DocsTOC } from '@/components/docs/layout/DocsTOC';
import { SectionHeader, LinkCard, LinkCardGrid } from '@/components/docs/blocks';
import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
/**
* 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 (
<ThreeColumnLayout
center={
<article className="max-w-3xl mx-auto px-6 lg:px-12 py-12">
{/* Breadcrumb Navigation */}
<Breadcrumb items={breadcrumbItems} />
{/* Page Content (Hero + Sections) */}
{children}
{/* Next Steps Section */}
<section id="next-steps" className="mb-12">
<SectionHeader level={2} id="next-steps" className="mb-6">
Next Steps
</SectionHeader>
{nextSteps.description && (
<p className="text-gray-300 leading-relaxed mb-6">
{nextSteps.description}
</p>
)}
<LinkCardGrid columns={2}>
{nextSteps.links.map((link, index) => (
<LinkCard
key={index}
href={link.href}
title={link.title}
description={link.description}
accent={link.accent}
/>
))}
</LinkCardGrid>
</section>
</article>
}
right={
<div className="border-l border-white/10 bg-slate-950/30 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
<DocsTOC items={tocItems} />
</div>
}
/>
);
};

View File

@ -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 (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
{/* Animated gradient background (matching landing page) */}
<div className="fixed inset-0 overflow-hidden pointer-events-none">
<div className="absolute top-1/4 -left-1/4 w-96 h-96 bg-purple-600/10 rounded-full blur-3xl animate-pulse"></div>
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
</div>
<div className="relative z-10 flex">
{/* Left Sidebar - Thin, minimal design */}
<aside className="hidden lg:block w-64 border-r border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
{sidebar}
</aside>
{/* Main Content Area - Wide margins for comfortable reading */}
<main className="flex-1 min-w-0">
<div className="max-w-3xl mx-auto px-6 lg:px-12 py-12">
{children}
</div>
</main>
{/* Right TOC - Subtle and unobtrusive */}
<aside className="hidden xl:block w-56 border-l border-white/10 bg-slate-950/30 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
{toc}
</aside>
</div>
</div>
);
};

View File

@ -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<string[]>(['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 (
<nav className="p-6" aria-label="Documentation navigation">
{/* Logo/Title */}
<div className="mb-8">
<h2 className="text-lg font-semibold text-white">Documentation</h2>
<p className="text-xs text-gray-500 mt-1">Variant A: Clean</p>
</div>
{/* Navigation Items */}
<ul className="space-y-1">
{navigationItems.map((item) => {
const hasChildren = item.children && item.children.length > 0;
const expanded = isExpanded(item.label);
const active = isActive(item.href);
return (
<li key={item.label}>
{/* Parent Item */}
<div className="relative">
{active && (
<div className="absolute left-0 top-0 bottom-0 w-0.5 bg-purple-500 rounded-r"></div>
)}
<a
href={item.href}
onClick={
hasChildren
? (e) => {
e.preventDefault();
toggleSection(item.label);
}
: undefined
}
className={`
flex items-center justify-between px-3 py-2 rounded-lg text-sm transition-colors
${active ? 'bg-purple-500/10 text-white font-medium' : 'text-gray-400 hover:text-white hover:bg-white/5'}
`}
>
<span className="flex items-center gap-2">
{item.icon && <span className="text-base">{item.icon}</span>}
<span>{item.label}</span>
</span>
{hasChildren && (
<svg
className={`w-4 h-4 transition-transform ${expanded ? 'rotate-90' : ''}`}
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
)}
</a>
</div>
{/* Children Items */}
{hasChildren && expanded && (
<ul className="ml-6 mt-1 space-y-1 border-l border-slate-800">
{item.children!.map((child) => {
const childActive = isActive(child.href);
return (
<li key={child.label}>
<a
href={child.href}
className={`
block px-3 py-1.5 text-sm rounded-lg transition-colors -ml-px
${childActive ? 'text-white font-medium border-l-2 border-purple-500' : 'text-gray-500 hover:text-gray-300 border-l-2 border-transparent'}
`}
>
{child.label}
</a>
</li>
);
})}
</ul>
)}
</li>
);
})}
</ul>
{/* Bottom Links */}
<div className="mt-12 pt-6 border-t border-slate-800">
<ul className="space-y-2 text-sm">
<li>
<a href="/docs" className="text-gray-500 hover:text-gray-300 transition-colors">
Back to variants
</a>
</li>
</ul>
</div>
</nav>
);
};

View File

@ -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<string>('');
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 (
<nav className="p-6 sticky top-6" aria-label="Table of contents">
<h3 className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-4">
On This Page
</h3>
<ul className="space-y-2.5 text-sm">
{items.map((item) => {
const isActive = activeId === item.id;
const isH3 = item.level === 3;
return (
<li key={item.id} className={isH3 ? 'ml-4' : ''}>
<button
onClick={() => 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 */}
<span
className={`
flex-shrink-0 w-1 h-1 rounded-full mt-2 transition-colors
${isActive ? 'bg-purple-400' : 'bg-gray-600 group-hover:bg-gray-400'}
`}
></span>
<span className="line-clamp-2">{item.text}</span>
</button>
</li>
);
})}
</ul>
</nav>
);
};

View File

@ -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<Language>('curl');
const [apiKey, setApiKey] = useState('');
const [isExecuting, setIsExecuting] = useState(false);
const [viewMode, setViewMode] = useState<ViewMode>('code');
const [response, setResponse] = useState<any>(null);
const [error, setError] = useState<string | null>(null);
// Parameter values
const [paramValues, setParamValues] = useState<Record<string, string>>({});
// Load API key from localStorage
useEffect(() => {
const stored = localStorage.getItem(API_KEY_STORAGE);
if (stored) setApiKey(stored);
// Initialize parameter default values
const defaults: Record<string, string> = {};
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<string, any> = {};
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 (
<div className="my-8 bg-slate-900/50 backdrop-blur-sm border border-slate-700 rounded-2xl overflow-hidden">
{/* Header with API Key Input */}
<div className="p-4 border-b border-slate-700 bg-slate-900/80">
<div className="flex flex-col md:flex-row gap-3 items-start md:items-center justify-between">
<div>
<h3 className="text-sm font-semibold text-white mb-1">Try it out</h3>
<p className="text-xs text-gray-500">{description}</p>
</div>
<div className="flex-shrink-0 w-full md:w-64">
<input
type="password"
value={apiKey}
onChange={(e) => 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"
/>
</div>
</div>
</div>
{/* Language Tabs */}
<div className="flex items-center justify-between bg-slate-950/50 px-4 py-2 border-b border-slate-700">
<div className="flex gap-2">
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => (
<button
key={lang}
onClick={() => 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)}
</button>
))}
</div>
<button
onClick={copyCode}
className="px-3 py-1 text-xs bg-purple-600/20 hover:bg-purple-600/30 text-purple-400 rounded transition-colors"
>
Copy
</button>
</div>
{/* Code Display */}
<div className="p-4 bg-slate-950/50">
<pre className="text-xs text-gray-300 overflow-x-auto">
<code>{generateCode()}</code>
</pre>
</div>
{/* Try It Button */}
<div className="p-4 border-t border-slate-700 bg-slate-900/50">
<button
onClick={executeRequest}
disabled={!apiKey || isExecuting}
className="w-full px-4 py-2.5 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
>
{isExecuting ? 'Executing...' : 'Try It'}
</button>
</div>
{/* Response Section */}
{(response || error) && (
<div className="border-t border-slate-700">
<div className="p-4 bg-slate-900/80">
<h4 className="text-sm font-semibold text-white mb-3">Response</h4>
{error ? (
<div className="p-3 bg-red-500/10 border border-red-500/20 rounded-lg text-red-400 text-xs">
{error}
</div>
) : (
<pre className="p-3 bg-slate-950/50 rounded-lg text-xs text-gray-300 overflow-x-auto">
<code>{JSON.stringify(response, null, 2)}</code>
</pre>
)}
</div>
</div>
)}
</div>
);
};

View File

@ -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 (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
{/* Animated gradient background (matching landing page) */}
<div className="fixed inset-0 overflow-hidden pointer-events-none">
<div className="absolute top-1/4 -left-1/4 w-96 h-96 bg-purple-600/10 rounded-full blur-3xl animate-pulse"></div>
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
</div>
<div className="relative z-10 flex">
{/* Left Sidebar - Wider with nested structure */}
<aside className="hidden lg:block w-72 border-r border-white/10 bg-slate-950/80 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
{sidebar}
</aside>
{/* Main Content Area - Narrower margins for more content */}
<main className="flex-1 min-w-0">
<div className="max-w-4xl mx-auto px-6 lg:px-8 py-10">
{children}
</div>
</main>
{/* Right TOC - Prominent with progress */}
<aside className="hidden xl:block w-60 border-l border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
{toc}
</aside>
</div>
</div>
);
};

View File

@ -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<string[]>(['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 (
<nav className="p-4" aria-label="Documentation navigation">
{/* Header */}
<div className="mb-6 pb-4 border-b border-slate-800">
<h2 className="text-base font-bold text-white mb-1">Documentation</h2>
<p className="text-xs text-gray-500">Variant B: Dense</p>
</div>
{/* Search (placeholder) */}
<div className="mb-4">
<div className="relative">
<input
type="text"
placeholder="Search docs..."
className="w-full px-3 py-2 pl-9 text-sm bg-slate-800/50 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent"
/>
<svg
className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</div>
</div>
{/* Navigation Tree */}
<ul className="space-y-0.5">
{navigationItems.map((item) => {
const hasChildren = item.children && item.children.length > 0;
const expanded = isExpanded(item.label);
const active = isActive(item.href);
return (
<li key={item.label}>
{/* Parent Item */}
<a
href={item.href}
onClick={
hasChildren
? (e) => {
e.preventDefault();
toggleSection(item.label);
}
: undefined
}
className={`
flex items-center justify-between px-3 py-2 rounded-md text-sm transition-colors
${active ? 'bg-purple-500/20 text-white font-semibold' : 'text-gray-400 hover:text-white hover:bg-slate-800/50'}
`}
>
<span className="flex items-center gap-2">
<span className="text-xs font-mono text-gray-500">{item.number}</span>
<span>{item.label}</span>
</span>
{hasChildren && (
<svg
className={`w-3.5 h-3.5 transition-transform ${expanded ? 'rotate-90' : ''}`}
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
)}
</a>
{/* Children Items - Indented */}
{hasChildren && expanded && (
<ul className="ml-6 mt-0.5 space-y-0.5 border-l border-slate-800 pl-2">
{item.children!.map((child) => {
const childActive = isActive(child.href);
return (
<li key={child.label}>
<a
href={child.href}
className={`
flex items-center gap-2 px-3 py-1.5 text-sm rounded-md transition-colors
${childActive ? 'bg-purple-500/20 text-white font-semibold' : 'text-gray-500 hover:text-gray-300 hover:bg-slate-800/30'}
`}
>
<span className="text-xs font-mono text-gray-600">{child.number}</span>
<span>{child.label}</span>
</a>
</li>
);
})}
</ul>
)}
</li>
);
})}
</ul>
{/* Bottom Links */}
<div className="mt-8 pt-4 border-t border-slate-800">
<ul className="space-y-1.5 text-sm">
<li>
<a
href="/docs"
className="flex items-center gap-2 px-3 py-1.5 text-gray-500 hover:text-gray-300 transition-colors"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
<span>All variants</span>
</a>
</li>
</ul>
</div>
</nav>
);
};

View File

@ -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<string>('');
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 (
<nav className="p-5 sticky top-6" aria-label="Table of contents">
{/* Header with Progress */}
<div className="mb-4 pb-4 border-b border-slate-800">
<h3 className="text-xs font-bold text-white uppercase tracking-wider mb-3">
On This Page
</h3>
{/* Progress Bar */}
<div className="relative h-1 bg-slate-800 rounded-full overflow-hidden">
<div
className="absolute top-0 left-0 h-full bg-gradient-to-r from-purple-500 to-cyan-500 transition-all duration-300"
style={{ width: `${scrollProgress}%` }}
></div>
</div>
<p className="text-xs text-gray-500 mt-2">{Math.round(scrollProgress)}% read</p>
</div>
{/* TOC Items with Numbers */}
<ul className="space-y-1.5 text-sm">
{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 (
<li key={item.id} className={isH3 ? 'ml-4' : ''}>
<button
onClick={() => 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 */}
<span className="flex-shrink-0 font-mono text-xs mt-0.5 opacity-60">
{isH3 ? '↳' : number}
</span>
<span className="line-clamp-2">{item.text}</span>
</button>
</li>
);
})}
</ul>
{/* Back to Top Button */}
{scrollProgress > 20 && (
<button
onClick={() => 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"
>
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
</svg>
Back to top
</button>
)}
</nav>
);
};

View File

@ -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<Language>('curl');
const [apiKey, setApiKey] = useState('');
const [isExecuting, setIsExecuting] = useState(false);
const [response, setResponse] = useState<any>(null);
const [error, setError] = useState<string | null>(null);
const [paramValues, setParamValues] = useState<Record<string, string>>({});
// Load API key from localStorage
useEffect(() => {
const stored = localStorage.getItem(API_KEY_STORAGE);
if (stored) setApiKey(stored);
// Initialize parameter default values
const defaults: Record<string, string> = {};
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<string, any> = {};
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 (
<div className="my-6">
{/* API Key Bar - Persistent at top */}
<div className="mb-3 p-3 bg-slate-900/80 backdrop-blur-sm border border-slate-700 rounded-lg">
<div className="flex items-center gap-3">
<label className="text-xs font-semibold text-gray-400 whitespace-nowrap">API Key:</label>
<input
type="password"
value={apiKey}
onChange={(e) => 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"
/>
<span className={`text-xs ${apiKey ? 'text-green-400' : 'text-gray-500'}`}>
{apiKey ? '✓ Set' : 'Not set'}
</span>
</div>
</div>
{/* Main Widget - Two Column Layout */}
<div className="grid md:grid-cols-2 gap-3 bg-slate-900/50 backdrop-blur-sm border border-slate-700 rounded-lg overflow-hidden">
{/* Left Column: Code */}
<div className="border-r border-slate-700">
{/* Language Tabs */}
<div className="flex items-center justify-between bg-slate-950/50 px-3 py-2 border-b border-slate-700">
<div className="flex gap-1.5">
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => (
<button
key={lang}
onClick={() => 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()}
</button>
))}
</div>
<button
onClick={copyCode}
className="px-2 py-1 text-xs bg-purple-600/20 hover:bg-purple-600/30 text-purple-400 rounded transition-colors"
>
Copy
</button>
</div>
{/* Code Display */}
<div className="p-3 bg-slate-950/50 h-64 overflow-auto">
<pre className="text-xs text-gray-300">
<code>{generateCode()}</code>
</pre>
</div>
</div>
{/* Right Column: Response */}
<div>
<div className="bg-slate-950/50 px-3 py-2 border-b border-slate-700">
<h4 className="text-xs font-semibold text-white">Response</h4>
</div>
<div className="p-3 bg-slate-950/50 h-64 overflow-auto">
{error ? (
<div className="p-2 bg-red-500/10 border border-red-500/20 rounded text-red-400 text-xs">
{error}
</div>
) : response ? (
<pre className="text-xs text-gray-300">
<code>{JSON.stringify(response, null, 2)}</code>
</pre>
) : (
<p className="text-xs text-gray-500 italic">
Click "Execute Request" to see the response
</p>
)}
</div>
</div>
</div>
{/* Try It Button - Full Width */}
<button
onClick={executeRequest}
disabled={!apiKey || isExecuting}
className="mt-3 w-full px-4 py-2 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
>
{isExecuting ? 'Executing...' : '▶ Execute Request'}
</button>
<p className="mt-2 text-xs text-gray-500 text-center">{description}</p>
</div>
);
};

View File

@ -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 (
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
{/* Animated gradient background - More colorful */}
<div className="fixed inset-0 overflow-hidden pointer-events-none">
<div className="absolute top-1/4 -left-1/4 w-[600px] h-[600px] bg-purple-600/20 rounded-full blur-3xl animate-pulse"></div>
<div className="absolute bottom-1/4 -right-1/4 w-[600px] h-[600px] bg-cyan-600/20 rounded-full blur-3xl animate-pulse delay-700"></div>
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[400px] h-[400px] bg-amber-600/10 rounded-full blur-3xl animate-pulse delay-1000"></div>
</div>
<div className="relative z-10 flex">
{/* Left Sidebar - Wide with card-style navigation */}
<aside className="hidden lg:block w-80 border-r-2 border-purple-500/20 bg-slate-950/80 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
{sidebar}
</aside>
{/* Main Content Area - Wide with generous padding */}
<main className="flex-1 min-w-0">
<div className="max-w-5xl mx-auto px-8 lg:px-12 py-12">
{children}
</div>
</main>
{/* Right TOC - Floating card with gradient border */}
<aside className="hidden xl:block w-72 border-l-2 border-cyan-500/20 bg-slate-950/60 backdrop-blur-md sticky top-0 h-screen overflow-y-auto">
{toc}
</aside>
</div>
</div>
);
};

View File

@ -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<string[]>(['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 (
<nav className="p-6" aria-label="Documentation navigation">
{/* Header - Colorful */}
<div className="mb-8 pb-6 border-b-2 border-gradient-to-r from-purple-500/30 to-cyan-500/30">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/20 to-cyan-500/20 border-2 border-purple-500/40 mb-3">
<span className="text-xl">📖</span>
<h2 className="text-base font-bold text-white">Documentation</h2>
</div>
<p className="text-xs text-gray-400 mt-2 ml-1">Variant C: Modern & Visual</p>
</div>
{/* Search (placeholder) - Colorful border */}
<div className="mb-6">
<div className="relative">
<input
type="text"
placeholder="Search docs..."
className="w-full px-4 py-3 pl-11 text-sm bg-slate-900/50 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"
/>
<svg
className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-purple-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</div>
</div>
{/* Navigation Cards */}
<ul className="space-y-4">
{navigationItems.map((item) => {
const hasChildren = item.children && item.children.length > 0;
const expanded = isExpanded(item.label);
const active = isActive(item.href);
return (
<li key={item.label}>
{/* Parent Item - Large Card */}
<a
href={item.href}
onClick={
hasChildren
? (e) => {
e.preventDefault();
toggleSection(item.label);
}
: undefined
}
className={`
flex items-center justify-between p-4 rounded-xl transition-all duration-300
${getGradientClasses(item.color, active)}
${active ? 'text-white font-bold' : 'text-gray-300 hover:text-white'}
`}
>
<span className="flex items-center gap-3">
<span className="text-2xl">{item.icon}</span>
<span className="text-base">{item.label}</span>
</span>
{hasChildren && (
<svg
className={`w-5 h-5 transition-transform duration-300 ${expanded ? 'rotate-90' : ''}`}
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
)}
</a>
{/* Children Items - Smaller Cards with Indent */}
{hasChildren && expanded && (
<ul className="ml-6 mt-3 space-y-2 border-l-2 border-purple-500/20 pl-4">
{item.children!.map((child) => {
const childActive = isActive(child.href);
return (
<li key={child.label}>
<a
href={child.href}
className={`
flex items-center gap-3 p-3 rounded-lg transition-all duration-300
${getGradientClasses(child.color, childActive)}
${childActive ? 'text-white font-semibold' : 'text-gray-400 hover:text-white'}
`}
>
<span className="text-xl">{child.icon}</span>
<span className="text-sm">{child.label}</span>
</a>
</li>
);
})}
</ul>
)}
</li>
);
})}
</ul>
{/* Bottom Links - Colorful Card */}
<div className="mt-8 pt-6 border-t-2 border-purple-500/20">
<a
href="/docs"
className="flex items-center gap-3 px-4 py-3 text-sm text-gray-400 hover:text-white transition-colors rounded-xl border-2 border-cyan-500/30 hover:border-cyan-500/50 hover:bg-cyan-500/10"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
<span>View all variants</span>
</a>
</div>
</nav>
);
};

View File

@ -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<string>('');
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 (
<nav className="p-6 sticky top-6" aria-label="Table of contents">
{/* Floating Card with Gradient Border */}
<div className="rounded-2xl border-2 border-purple-500/40 bg-slate-900/60 backdrop-blur-md shadow-xl shadow-purple-500/20 overflow-hidden">
{/* Header with Icon and Progress */}
<div className="p-6 pb-4 border-b-2 border-purple-500/20">
<div className="flex items-center gap-3 mb-4">
<span className="text-2xl">📍</span>
<h3 className="text-sm font-bold text-white uppercase tracking-wider">
On This Page
</h3>
</div>
{/* Rainbow Progress Bar */}
<div className="relative h-2 bg-slate-800 rounded-full overflow-hidden">
<div
className="absolute top-0 left-0 h-full bg-gradient-to-r from-purple-500 via-cyan-500 to-amber-500 transition-all duration-300 shadow-lg"
style={{ width: `${scrollProgress}%` }}
></div>
</div>
<div className="mt-2 flex items-center justify-between">
<p className="text-xs text-gray-400">{Math.round(scrollProgress)}% complete</p>
<span className="text-xs text-purple-400 font-semibold">
{items.findIndex((item) => item.id === activeId) + 1}/{items.length}
</span>
</div>
</div>
{/* TOC Items with Colorful Dots */}
<ul className="p-6 space-y-3">
{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 (
<li key={item.id} className={isH3 ? 'ml-6' : ''}>
<button
onClick={() => 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 */}
<span className="mt-1.5">
{isH3 ? (
<span className="text-gray-600 text-xs ml-0.5"></span>
) : (
<span className={getDotClasses(color, isActive)}></span>
)}
</span>
{/* Text */}
<span className="flex-1 text-base leading-relaxed">{cleanText}</span>
</button>
</li>
);
})}
</ul>
{/* Back to Top Button - Colorful */}
{scrollProgress > 20 && (
<div className="p-6 pt-0">
<button
onClick={() => 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"
>
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
</svg>
<span className="font-semibold">Back to top</span>
</button>
</div>
)}
</div>
{/* Fun Floating Tip Card */}
<div className="mt-6 p-4 rounded-xl bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 shadow-lg">
<div className="flex items-start gap-2">
<span className="text-xl">💡</span>
<p className="text-xs text-amber-300">
<strong>Tip:</strong> Click any item to jump directly to that section!
</p>
</div>
</div>
</nav>
);
};

View File

@ -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<Language>('curl');
const [apiKey, setApiKey] = useState('');
const [isExecuting, setIsExecuting] = useState(false);
const [response, setResponse] = useState<any>(null);
const [error, setError] = useState<string | null>(null);
const [paramValues, setParamValues] = useState<Record<string, string>>({});
const [isExpanded, setIsExpanded] = useState(false);
useEffect(() => {
const stored = localStorage.getItem(API_KEY_STORAGE);
if (stored) setApiKey(stored);
const defaults: Record<string, string> = {};
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<string, any> = {};
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 (
<div className="my-12">
{/* API Key Card - Large and Colorful */}
<div className="mb-6 p-6 bg-gradient-to-br from-purple-500/10 to-cyan-500/10 backdrop-blur-sm border-2 border-purple-500/40 rounded-2xl shadow-xl shadow-purple-500/20">
<div className="flex items-center gap-4 mb-3">
<span className="text-2xl">🔑</span>
<label className="text-sm font-bold text-white">Your API Key</label>
</div>
<div className="flex items-center gap-3">
<input
type="password"
value={apiKey}
onChange={(e) => 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"
/>
<div
className={`px-4 py-3 rounded-xl font-semibold text-sm transition-all ${
apiKey
? 'bg-green-500/20 text-green-400 border-2 border-green-500/40 shadow-lg shadow-green-500/20'
: 'bg-gray-500/20 text-gray-400 border-2 border-gray-500/20'
}`}
>
{apiKey ? '✓ Ready' : '⚠️ Required'}
</div>
</div>
</div>
{/* Main Widget Card - Large Gradient Border */}
<div
className={`bg-gradient-to-br from-slate-900/80 to-slate-950/80 backdrop-blur-sm border-2 border-purple-500/40 rounded-2xl overflow-hidden shadow-2xl shadow-purple-500/30 transition-all duration-500 ${
isExpanded ? 'fixed inset-4 z-50' : ''
}`}
>
{/* Header with Expand Button */}
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b-2 border-purple-500/30">
<div className="flex items-center gap-3">
<div className={`px-3 py-1.5 rounded-lg bg-gradient-to-r ${getMethodColor(method)} text-white text-sm font-bold shadow-lg`}>
{method}
</div>
<span className="text-sm text-gray-400">{endpoint}</span>
</div>
<button
onClick={() => 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'}
</button>
</div>
<div className="grid md:grid-cols-2 gap-6 p-6">
{/* Left: Code Editor */}
<div>
{/* Language Tabs - Colorful Pills */}
<div className="flex items-center gap-2 mb-4">
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => {
const colors = ['purple', 'cyan', 'amber', 'purple'];
const color = colors[idx];
return (
<button
key={lang}
onClick={() => 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()}
</button>
);
})}
</div>
{/* Code Display - Gradient Border */}
<div className="border-2 border-cyan-500/30 rounded-xl overflow-hidden shadow-lg">
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b-2 border-cyan-500/20">
<span className="text-xs text-cyan-400 font-semibold">Code Example</span>
<button
onClick={copyCode}
className="px-3 py-1.5 text-xs bg-purple-600/30 hover:bg-purple-600/50 text-purple-300 rounded-lg transition-all font-semibold"
>
📋 Copy
</button>
</div>
<div className="p-4 bg-slate-950/50 h-80 overflow-auto">
<pre className="text-xs text-gray-300 leading-relaxed">
<code>{generateCode()}</code>
</pre>
</div>
</div>
</div>
{/* Right: Response */}
<div>
<h4 className="text-sm font-bold text-white mb-4 flex items-center gap-2">
<span className="text-xl">📦</span>
Response
</h4>
<div className="border-2 border-purple-500/30 rounded-xl overflow-hidden shadow-lg">
<div className="bg-slate-950/80 px-4 py-3 border-b-2 border-purple-500/20">
{response && (
<span
className={`inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-bold ${
response.success
? 'bg-green-500/20 text-green-400 border-2 border-green-500/40 shadow-lg shadow-green-500/20'
: 'bg-red-500/20 text-red-400 border-2 border-red-500/40 shadow-lg shadow-red-500/20'
}`}
>
{response.success ? '✓ Success' : '✕ Error'}
</span>
)}
</div>
<div className="p-4 bg-slate-950/50 h-80 overflow-auto">
{error ? (
<div className="p-4 bg-red-500/10 border-2 border-red-500/40 rounded-xl text-red-400 text-sm shadow-lg shadow-red-500/20">
<div className="flex items-start gap-2">
<span className="text-xl"></span>
<div>
<p className="font-semibold mb-1">Error</p>
<p className="text-xs">{error}</p>
</div>
</div>
</div>
) : response ? (
<pre className="text-xs text-gray-300 leading-relaxed">
<code>{JSON.stringify(response, null, 2)}</code>
</pre>
) : (
<div className="flex items-center justify-center h-full">
<div className="text-center">
<p className="text-2xl mb-3">🚀</p>
<p className="text-sm text-gray-500">
Click <strong className="text-purple-400">"Test Now"</strong> below to see the response
</p>
</div>
</div>
)}
</div>
</div>
</div>
</div>
{/* Large Test Now Button */}
<div className="px-6 pb-6">
<button
onClick={executeRequest}
disabled={!apiKey || isExecuting}
className="w-full px-8 py-4 rounded-xl bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-base font-bold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-2xl hover:shadow-purple-500/50 hover:scale-105 flex items-center justify-center gap-3 border-2 border-purple-500/50"
>
{isExecuting ? (
<>
<span className="animate-spin"></span>
<span>Executing...</span>
</>
) : (
<>
<span></span>
<span>Test Now</span>
</>
)}
</button>
<p className="mt-3 text-xs text-gray-500 text-center">{description}</p>
</div>
</div>
</div>
);
};

View File

@ -1,119 +0,0 @@
'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):
* <ThreeColumnLayout
* left={<Logo />}
* center={<NavItems />}
* right={<UserMenu />}
* />
*
* 2. Docs Layout (2 columns - left + center):
* <ThreeColumnLayout
* left={<DocsSidebar />}
* center={<DocPage />}
* />
*
* 3. Doc Page (2 columns - center + right):
* <ThreeColumnLayout
* center={<Article />}
* right={<DocsTOC />}
* />
*
* 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 (
<div className={`flex ${containerClassName}`}>
{/* Left Column - w-64 (256px) */}
{left && (
<div className={`${leftHidden} w-64 shrink-0 ${leftClassName}`}>
{left}
</div>
)}
{/* Center Column - flex-1 (flexible) */}
<div className={`flex-1 min-w-0 ${centerClassName}`}>
{center}
</div>
{/* Right Column - w-56 (224px) */}
{right && (
<div className={`${rightHidden} w-56 shrink-0 ${rightClassName}`}>
{right}
</div>
)}
</div>
);
};

View File

@ -9,24 +9,17 @@
* - Active state indicator (purple color)
* - Optional API Key input on the right
* - Responsive (hamburger menu on mobile)
* - 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.
* - Can be reused across landing app sections
*
* Usage:
* <SubsectionNav
* items={[...]}
* currentPath="/docs/final"
* showApiKeyInput={true}
* leftSlot={<Logo />}
* rightSlot={<UserMenu />}
* />
*/
import { useState, useEffect, useRef, ReactNode } from 'react';
import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
import { useState, useEffect, useRef } from 'react';
interface NavItem {
label: string;
@ -40,10 +33,6 @@ 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';
@ -52,8 +41,6 @@ export const SubsectionNav = ({
items,
currentPath,
showApiKeyInput = false,
leftSlot,
rightSlot,
}: SubsectionNavProps) => {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [apiKey, setApiKey] = useState('');
@ -123,8 +110,32 @@ export const SubsectionNav = ({
};
}, []);
// Desktop API Key Input Component
const apiKeyComponent = showApiKeyInput && (
return (
<nav className="sticky top-0 z-40 bg-slate-950/80 backdrop-blur-sm border-b border-white/10">
{/* Main Nav Container */}
<div className="max-w-7xl mx-auto px-6">
<div className="flex items-center justify-between h-12">
{/* Desktop Navigation */}
<div className="hidden md:flex items-center gap-8">
{items.map((item) => {
const active = isActive(item.href);
return (
<a
key={item.href}
href={item.href}
className={`
py-3 text-sm font-medium transition-colors
${active ? 'text-purple-400' : 'text-gray-400 hover:text-white'}
`}
>
{item.label}
</a>
);
})}
</div>
{/* Right Side: API Key Input (Desktop) */}
{showApiKeyInput && (
<div className="hidden md:block relative" ref={dropdownRef}>
<button
onClick={() => setIsApiKeyExpanded(!isApiKeyExpanded)}
@ -241,34 +252,7 @@ export const SubsectionNav = ({
</div>
)}
</div>
);
return (
<nav className="sticky top-0 z-40 bg-slate-950/80 backdrop-blur-sm border-b border-white/10">
{/* Three-Column Layout */}
<ThreeColumnLayout
left={leftSlot}
center={
<div className="max-w-7xl mx-auto px-6">
<div className="flex items-center justify-between h-12">
{/* Desktop Navigation Items */}
<div className="hidden md:flex items-center gap-8">
{items.map((item) => {
const active = isActive(item.href);
return (
<a
key={item.href}
href={item.href}
className={`
py-3 text-sm font-medium transition-colors
${active ? 'text-purple-400' : 'text-gray-400 hover:text-white'}
`}
>
{item.label}
</a>
);
})}
</div>
)}
{/* Mobile Menu Button */}
<div className="md:hidden flex items-center ml-auto">
@ -303,9 +287,6 @@ export const SubsectionNav = ({
</div>
</div>
</div>
}
right={rightSlot || apiKeyComponent}
/>
{/* Decorative Wave Line */}
<div className="absolute bottom-0 left-0 right-0 h-px overflow-hidden">