feat: leave final variant
This commit is contained in:
parent
bd46f63ac8
commit
a272c8d74f
|
|
@ -11,13 +11,13 @@
|
|||
* - Simplified Next Steps
|
||||
*/
|
||||
|
||||
import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal';
|
||||
import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal';
|
||||
import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal';
|
||||
import { DocsLayout } from '@/components/docs/docs/DocsLayout';
|
||||
import { DocsSidebar } from '@/components/docs/docs/DocsSidebar';
|
||||
import { DocsTOC } from '@/components/docs/docs/DocsTOC';
|
||||
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||
import { Table } from '@/components/docs/shared/Table';
|
||||
import { InteractiveAPIWidgetFinal } from '@/components/docs/final/InteractiveAPIWidgetFinal';
|
||||
import { InteractiveAPIWidget } from '@/components/docs/docs/InteractiveAPIWidget';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
|
|
@ -32,9 +32,9 @@ const tocItems = [
|
|||
];
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Documentation', href: '/docs/final' },
|
||||
{ label: 'Documentation', href: '/docs' },
|
||||
{ label: 'Demo', href: '/demo' },
|
||||
{ label: 'Examples', href: '/docs/final/examples' },
|
||||
{ label: 'Examples', href: '/docs/examples' },
|
||||
];
|
||||
|
||||
const parameters = [
|
||||
|
|
@ -50,18 +50,18 @@ export default function TextToImageAPIPage() {
|
|||
{/* Subsection Navigation with API Key Input */}
|
||||
<SubsectionNav
|
||||
items={navItems}
|
||||
currentPath="/docs/final/api/text-to-image"
|
||||
currentPath="/docs/api/text-to-image"
|
||||
showApiKeyInput={true}
|
||||
/>
|
||||
|
||||
<DocsLayoutFinal
|
||||
sidebar={<DocsSidebarFinal currentPath="/docs/final/api/text-to-image" />}
|
||||
toc={<DocsTOCFinal items={tocItems} />}
|
||||
<DocsLayout
|
||||
sidebar={<DocsSidebar currentPath="/docs/api/text-to-image" />}
|
||||
toc={<DocsTOC items={tocItems} />}
|
||||
>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{ label: 'Documentation', href: '/docs' },
|
||||
{ label: 'API Reference', href: '/docs/final/api' },
|
||||
{ label: 'API Reference', href: '/docs/api' },
|
||||
{ label: 'Text to Image' },
|
||||
]}
|
||||
/>
|
||||
|
|
@ -210,7 +210,7 @@ export default function TextToImageAPIPage() {
|
|||
Test the API directly from this page. Enter your API key and customize the parameters below.
|
||||
</p>
|
||||
|
||||
<InteractiveAPIWidgetFinal
|
||||
<InteractiveAPIWidget
|
||||
endpoint="/api/text-to-image"
|
||||
method="POST"
|
||||
description="Generate an image from a text prompt"
|
||||
|
|
@ -224,7 +224,7 @@ export default function TextToImageAPIPage() {
|
|||
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<a
|
||||
href="/docs/final/api/upload"
|
||||
href="/docs/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">
|
||||
|
|
@ -236,7 +236,7 @@ export default function TextToImageAPIPage() {
|
|||
</a>
|
||||
|
||||
<a
|
||||
href="/docs/final/guides/error-handling"
|
||||
href="/docs/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">
|
||||
|
|
@ -248,7 +248,7 @@ export default function TextToImageAPIPage() {
|
|||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</DocsLayoutFinal>
|
||||
</DocsLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Getting Started Page - Final Variant
|
||||
*
|
||||
* Production-ready documentation landing page
|
||||
* Features:
|
||||
* - SubsectionNav at top
|
||||
* - Both TipBox styles (compact + prominent)
|
||||
* - Enhanced tables
|
||||
* - Simplified Next Steps (2 cards only)
|
||||
* - Clean, accessible design
|
||||
*/
|
||||
|
||||
import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal';
|
||||
import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal';
|
||||
import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal';
|
||||
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||
import { Table } from '@/components/docs/shared/Table';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||
{ id: 'installation', text: 'Installation', level: 3 },
|
||||
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||
];
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Documentation', href: '/docs/final' },
|
||||
{ label: 'Demo', href: '/demo' },
|
||||
{ label: 'Examples', href: '/docs/final/examples' },
|
||||
];
|
||||
|
||||
export default function GettingStartedPageFinal() {
|
||||
return (
|
||||
<>
|
||||
{/* Subsection Navigation */}
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -11,9 +11,9 @@
|
|||
* - Simplified Next Steps
|
||||
*/
|
||||
|
||||
import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal';
|
||||
import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal';
|
||||
import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal';
|
||||
import { DocsLayout } from '@/components/docs/docs/DocsLayout';
|
||||
import { DocsSidebar } from '@/components/docs/docs/DocsSidebar';
|
||||
import { DocsTOC } from '@/components/docs/docs/DocsTOC';
|
||||
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||
import { Table } from '@/components/docs/shared/Table';
|
||||
|
|
@ -32,9 +32,9 @@ const tocItems = [
|
|||
];
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Documentation', href: '/docs/final' },
|
||||
{ label: 'Documentation', href: '/docs' },
|
||||
{ label: 'Demo', href: '/demo' },
|
||||
{ label: 'Examples', href: '/docs/final/examples' },
|
||||
{ label: 'Examples', href: '/docs/examples' },
|
||||
];
|
||||
|
||||
export default function AuthenticationGuidePage() {
|
||||
|
|
@ -43,19 +43,19 @@ export default function AuthenticationGuidePage() {
|
|||
{/* Subsection Navigation */}
|
||||
<SubsectionNav
|
||||
items={navItems}
|
||||
currentPath="/docs/final/guides/authentication"
|
||||
currentPath="/docs/guides/authentication"
|
||||
ctaText="Join Beta"
|
||||
ctaHref="/signup"
|
||||
/>
|
||||
|
||||
<DocsLayoutFinal
|
||||
sidebar={<DocsSidebarFinal currentPath="/docs/final/guides/authentication" />}
|
||||
toc={<DocsTOCFinal items={tocItems} />}
|
||||
<DocsLayout
|
||||
sidebar={<DocsSidebar currentPath="/docs/guides/authentication" />}
|
||||
toc={<DocsTOC items={tocItems} />}
|
||||
>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{ label: 'Documentation', href: '/docs' },
|
||||
{ label: 'Guides', href: '/docs/final/guides' },
|
||||
{ label: 'Guides', href: '/docs/guides' },
|
||||
{ label: 'Authentication' },
|
||||
]}
|
||||
/>
|
||||
|
|
@ -330,7 +330,7 @@ curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\
|
|||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</DocsLayoutFinal>
|
||||
</DocsLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,376 +1,224 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Variants Comparison Page
|
||||
* Getting Started Page - Production Documentation
|
||||
*
|
||||
* Landing page that introduces users to the three documentation design variants.
|
||||
* Helps users choose the variant that best suits their preferences.
|
||||
*
|
||||
* Three Variants:
|
||||
* - Variant A: Clean & Minimal (Vercel-inspired)
|
||||
* - Variant B: Dense & Information-Rich (Next.js docs-inspired)
|
||||
* - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design:
|
||||
* - Hero section explaining the concept
|
||||
* - Three large gradient-bordered cards
|
||||
* - Visual preview descriptions
|
||||
* - Clear CTAs to each variant
|
||||
* Main entry point for documentation
|
||||
* Features:
|
||||
* - SubsectionNav at top
|
||||
* - Both TipBox styles (compact + prominent)
|
||||
* - Enhanced tables
|
||||
* - Simplified Next Steps (2 cards only)
|
||||
* - Clean, accessible design
|
||||
*/
|
||||
|
||||
export default function DocsIndexPage() {
|
||||
import { DocsLayout } from '@/components/docs/docs/DocsLayout';
|
||||
import { DocsSidebar } from '@/components/docs/docs/DocsSidebar';
|
||||
import { DocsTOC } from '@/components/docs/docs/DocsTOC';
|
||||
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||
{ id: 'installation', text: 'Installation', level: 3 },
|
||||
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||
];
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Documentation', href: '/docs' },
|
||||
{ label: 'Demo', href: '/demo' },
|
||||
{ label: 'Examples', href: '/docs/examples' },
|
||||
];
|
||||
|
||||
export default function GettingStartedPage() {
|
||||
return (
|
||||
<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>
|
||||
<>
|
||||
{/* Subsection Navigation */}
|
||||
<SubsectionNav
|
||||
items={navItems}
|
||||
currentPath="/docs"
|
||||
ctaText="Join Beta"
|
||||
ctaHref="/signup"
|
||||
/>
|
||||
|
||||
<DocsLayout
|
||||
sidebar={<DocsSidebar currentPath="/docs" />}
|
||||
toc={<DocsTOC items={tocItems} />}
|
||||
>
|
||||
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
|
||||
|
||||
<div className="max-w-7xl mx-auto px-6 py-16">
|
||||
{/* Hero Section */}
|
||||
<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
|
||||
you—same content, different presentation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 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
|
||||
<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/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>
|
||||
<h2 className="text-2xl font-bold text-white">Production-Ready Design</h2>
|
||||
</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"
|
||||
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]"
|
||||
href="/docs/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"
|
||||
>
|
||||
<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 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
|
||||
API Reference
|
||||
</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 className="text-sm text-gray-400">
|
||||
Explore all available endpoints, parameters, and response formats.
|
||||
</p>
|
||||
|
||||
<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>
|
||||
|
||||
<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"
|
||||
href="/docs/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"
|
||||
>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
|
||||
Authentication Guide
|
||||
</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
|
||||
Learn about API keys, rate limits, and security best practices.
|
||||
</p>
|
||||
</a>
|
||||
</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 content—pick your preferred reading experience.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</DocsLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,299 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* API Reference: Text to Image - Variant A: Clean & Minimal
|
||||
*
|
||||
* This page demonstrates the interactive API reference design with live code execution.
|
||||
* Features placeholder content and a fully functional API widget.
|
||||
*/
|
||||
|
||||
import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA';
|
||||
import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA';
|
||||
import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { InteractiveAPIWidgetA } from '@/components/docs/variant-a/InteractiveAPIWidgetA';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'overview', text: 'Overview', level: 2 },
|
||||
{ id: 'endpoint', text: 'Endpoint', level: 2 },
|
||||
{ id: 'request', text: 'Request', level: 2 },
|
||||
{ id: 'headers', text: 'Headers', level: 3 },
|
||||
{ id: 'body', text: 'Body Parameters', level: 3 },
|
||||
{ id: 'response', text: 'Response', level: 2 },
|
||||
{ id: 'examples', text: 'Examples', level: 2 },
|
||||
{ id: 'errors', text: 'Error Codes', level: 2 },
|
||||
];
|
||||
|
||||
export default function TextToImageAPIPageA() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,300 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Guide: Authentication - Variant A: Clean & Minimal
|
||||
*
|
||||
* This page demonstrates a guide/tutorial style page with step-by-step instructions.
|
||||
* Features placeholder content focused on authentication concepts.
|
||||
*/
|
||||
|
||||
import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA';
|
||||
import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA';
|
||||
import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'overview', text: 'Overview', level: 2 },
|
||||
{ id: 'api-keys', text: 'API Keys', level: 2 },
|
||||
{ id: 'key-types', text: 'Key Types', level: 3 },
|
||||
{ id: 'creating-keys', text: 'Creating Keys', level: 3 },
|
||||
{ id: 'using-keys', text: 'Using API Keys', level: 2 },
|
||||
{ id: 'security', text: 'Security Best Practices', level: 2 },
|
||||
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
|
||||
];
|
||||
|
||||
export default function AuthenticationGuidePageA() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Getting Started Page - Variant A: Clean & Minimal
|
||||
*
|
||||
* This is the main landing page for the documentation.
|
||||
* Features placeholder content to demonstrate the layout and design.
|
||||
*/
|
||||
|
||||
import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA';
|
||||
import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA';
|
||||
import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||
{ id: 'installation', text: 'Installation', level: 3 },
|
||||
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||
];
|
||||
|
||||
export default function GettingStartedPageA() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,304 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* API Reference: Text to Image - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Design Philosophy: Compact, information-dense layout with section numbers
|
||||
*
|
||||
* Key Differences from Variant A:
|
||||
* - Section numbers in all headings (1., 1.1, 1.2, etc.)
|
||||
* - More compact spacing (mb-6 vs mb-12, p-3 vs p-4)
|
||||
* - Smaller text sizes throughout
|
||||
* - Denser tables and narrower content
|
||||
*/
|
||||
|
||||
import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB';
|
||||
import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB';
|
||||
import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { InteractiveAPIWidgetB } from '@/components/docs/variant-b/InteractiveAPIWidgetB';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'overview', text: '1. Overview', level: 2 },
|
||||
{ id: 'endpoint', text: '2. Endpoint', level: 2 },
|
||||
{ id: 'request', text: '3. Request', level: 2 },
|
||||
{ id: 'headers', text: '3.1 Headers', level: 3 },
|
||||
{ id: 'body', text: '3.2 Body Parameters', level: 3 },
|
||||
{ id: 'response', text: '4. Response', level: 2 },
|
||||
{ id: 'examples', text: '5. Examples', level: 2 },
|
||||
{ id: 'errors', text: '6. Error Codes', level: 2 },
|
||||
];
|
||||
|
||||
export default function TextToImageAPIPageB() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Guide: Authentication - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Design Philosophy: Compact, information-dense layout with section numbers
|
||||
*
|
||||
* Key Differences from Variant A:
|
||||
* - Section numbers in all headings (1., 2., 2.1, etc.)
|
||||
* - More compact spacing (mb-6 vs mb-12, p-3 vs p-4)
|
||||
* - Smaller text sizes throughout (text-xs, text-sm)
|
||||
* - Denser layout with narrower content area
|
||||
*/
|
||||
|
||||
import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB';
|
||||
import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB';
|
||||
import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'overview', text: '1. Overview', level: 2 },
|
||||
{ id: 'api-keys', text: '2. API Keys', level: 2 },
|
||||
{ id: 'key-types', text: '2.1 Key Types', level: 3 },
|
||||
{ id: 'creating-keys', text: '2.2 Creating Keys', level: 3 },
|
||||
{ id: 'using-keys', text: '3. Using API Keys', level: 2 },
|
||||
{ id: 'security', text: '4. Security Best Practices', level: 2 },
|
||||
{ id: 'rate-limits', text: '5. Rate Limits', level: 2 },
|
||||
];
|
||||
|
||||
export default function AuthenticationGuidePageB() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Getting Started Page - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Same content as Variant A but with Variant B styling:
|
||||
* - Compact spacing (py-10 vs py-12, p-4 vs p-6)
|
||||
* - Narrower max-width (max-w-4xl)
|
||||
* - Section numbers in headings where appropriate
|
||||
* - Denser tables and lists
|
||||
*/
|
||||
|
||||
import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB';
|
||||
import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB';
|
||||
import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'introduction', text: '1. Introduction', level: 2 },
|
||||
{ id: 'quick-start', text: '2. Quick Start', level: 2 },
|
||||
{ id: 'installation', text: '2.1 Installation', level: 3 },
|
||||
{ id: 'authentication', text: '2.2 Authentication', level: 3 },
|
||||
{ id: 'first-request', text: '3. Your First Request', level: 2 },
|
||||
{ id: 'next-steps', text: '4. Next Steps', level: 2 },
|
||||
];
|
||||
|
||||
export default function GettingStartedPageB() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,369 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* API Reference: Text to Image - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Colorful, card-based, engaging visual design
|
||||
*
|
||||
* Key Characteristics:
|
||||
* - NO section numbers (more visual/playful)
|
||||
* - Large emoji icons (text-3xl)
|
||||
* - Gradient borders everywhere
|
||||
* - Colorful method badge (large, gradient)
|
||||
* - Visual cards for parameter tables
|
||||
* - Generous spacing (mb-12, p-6)
|
||||
*/
|
||||
|
||||
import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC';
|
||||
import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC';
|
||||
import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { InteractiveAPIWidgetC } from '@/components/docs/variant-c/InteractiveAPIWidgetC';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'overview', text: 'Overview', level: 2 },
|
||||
{ id: 'endpoint', text: 'Endpoint', level: 2 },
|
||||
{ id: 'request', text: 'Request', level: 2 },
|
||||
{ id: 'headers', text: 'Headers', level: 3 },
|
||||
{ id: 'body', text: 'Body Parameters', level: 3 },
|
||||
{ id: 'response', text: 'Response', level: 2 },
|
||||
{ id: 'examples', text: 'Examples', level: 2 },
|
||||
{ id: 'errors', text: 'Error Codes', level: 2 },
|
||||
];
|
||||
|
||||
export default function TextToImageAPIPageC() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,370 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Guide: Authentication - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Colorful, card-based, playful visual design
|
||||
*
|
||||
* Key Characteristics:
|
||||
* - NO section numbers (more visual/playful)
|
||||
* - Security best practices as large visual cards
|
||||
* - Emoji icons prominent (text-3xl)
|
||||
* - Gradient borders everywhere
|
||||
* - Generous spacing and padding
|
||||
*/
|
||||
|
||||
import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC';
|
||||
import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC';
|
||||
import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'overview', text: 'Overview', level: 2 },
|
||||
{ id: 'api-keys', text: 'API Keys', level: 2 },
|
||||
{ id: 'key-types', text: 'Key Types', level: 3 },
|
||||
{ id: 'creating-keys', text: 'Creating Keys', level: 3 },
|
||||
{ id: 'using-keys', text: 'Using API Keys', level: 2 },
|
||||
{ id: 'security', text: 'Security Best Practices', level: 2 },
|
||||
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
|
||||
];
|
||||
|
||||
export default function AuthenticationGuidePageC() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Getting Started Page - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Colorful, card-based, playful visual design
|
||||
*
|
||||
* Key Characteristics:
|
||||
* - NO section numbers (more visual/playful)
|
||||
* - Large emoji icons throughout (text-3xl)
|
||||
* - Gradient borders on all callout boxes
|
||||
* - More colorful design (purple/cyan/amber accents)
|
||||
* - Generous spacing (mb-12, p-6)
|
||||
* - Larger padding and gaps throughout
|
||||
* - Card-based sections with shadows
|
||||
* - Floating visual effects
|
||||
*/
|
||||
|
||||
import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC';
|
||||
import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC';
|
||||
import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC';
|
||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||
|
||||
const tocItems = [
|
||||
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||
{ id: 'installation', text: 'Installation', level: 3 },
|
||||
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||
];
|
||||
|
||||
export default function GettingStartedPageC() {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Layout - Final Variant
|
||||
* Documentation Layout - Production Version
|
||||
*
|
||||
* Based on Variant A: Clean & Minimal with enhancements
|
||||
* This is the production-ready version combining the best aspects
|
||||
|
|
@ -26,13 +26,13 @@
|
|||
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface DocsLayoutFinalProps {
|
||||
interface DocsLayoutProps {
|
||||
sidebar: ReactNode;
|
||||
children: ReactNode;
|
||||
toc: ReactNode;
|
||||
}
|
||||
|
||||
export const DocsLayoutFinal = ({ sidebar, children, toc }: DocsLayoutFinalProps) => {
|
||||
export const DocsLayout = ({ sidebar, children, toc }: DocsLayoutProps) => {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
||||
{/* Animated gradient background (matching landing page) */}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Sidebar - Final Variant
|
||||
* Documentation Sidebar - Production Version
|
||||
*
|
||||
* Based on Variant A with FIXED active states
|
||||
*
|
||||
|
|
@ -33,44 +33,44 @@ interface NavItem {
|
|||
children?: NavItem[];
|
||||
}
|
||||
|
||||
interface DocsSidebarFinalProps {
|
||||
interface DocsSidebarProps {
|
||||
currentPath: string;
|
||||
}
|
||||
|
||||
const navigationItems: NavItem[] = [
|
||||
{
|
||||
label: 'Getting Started',
|
||||
href: '/docs/final',
|
||||
href: '/docs',
|
||||
icon: '🚀',
|
||||
},
|
||||
{
|
||||
label: 'API Reference',
|
||||
href: '/docs/final/api',
|
||||
href: '/docs/api',
|
||||
icon: '📚',
|
||||
children: [
|
||||
{ label: 'Text to Image', href: '/docs/final/api/text-to-image' },
|
||||
{ label: 'Upload', href: '/docs/final/api/upload' },
|
||||
{ label: 'Images', href: '/docs/final/api/images' },
|
||||
{ label: 'Text to Image', href: '/docs/api/text-to-image' },
|
||||
{ label: 'Upload', href: '/docs/api/upload' },
|
||||
{ label: 'Images', href: '/docs/api/images' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Guides',
|
||||
href: '/docs/final/guides',
|
||||
href: '/docs/guides',
|
||||
icon: '📖',
|
||||
children: [
|
||||
{ label: 'Authentication', href: '/docs/final/guides/authentication' },
|
||||
{ label: 'Error Handling', href: '/docs/final/guides/error-handling' },
|
||||
{ label: 'Rate Limits', href: '/docs/final/guides/rate-limits' },
|
||||
{ label: 'Authentication', href: '/docs/guides/authentication' },
|
||||
{ label: 'Error Handling', href: '/docs/guides/error-handling' },
|
||||
{ label: 'Rate Limits', href: '/docs/guides/rate-limits' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Examples',
|
||||
href: '/docs/final/examples',
|
||||
href: '/docs/examples',
|
||||
icon: '💡',
|
||||
},
|
||||
];
|
||||
|
||||
export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => {
|
||||
export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
|
||||
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
|
||||
|
||||
const toggleSection = (label: string) => {
|
||||
|
|
@ -87,7 +87,7 @@ export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => {
|
|||
{/* 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">Final: Production</p>
|
||||
<p className="text-xs text-gray-500 mt-1">API Reference</p>
|
||||
</div>
|
||||
|
||||
{/* Navigation Items */}
|
||||
|
|
@ -170,8 +170,8 @@ export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => {
|
|||
<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 href="/" className="text-gray-500 hover:text-gray-300 transition-colors">
|
||||
← Back to home
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Table of Contents - Final Variant
|
||||
* Table of Contents - Production Version
|
||||
*
|
||||
* Based on Variant A: Clean & Minimal (no changes needed)
|
||||
*
|
||||
|
|
@ -26,11 +26,11 @@ interface TocItem {
|
|||
level: number;
|
||||
}
|
||||
|
||||
interface DocsTOCFinalProps {
|
||||
interface DocsTOCProps {
|
||||
items: TocItem[];
|
||||
}
|
||||
|
||||
export const DocsTOCFinal = ({ items }: DocsTOCFinalProps) => {
|
||||
export const DocsTOC = ({ items }: DocsTOCProps) => {
|
||||
const [activeId, setActiveId] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Interactive API Widget - Final Variant (Redesigned)
|
||||
* Interactive API Widget - Production Version
|
||||
*
|
||||
* Minimized layout inspired by Variant C with Final variant design system:
|
||||
* Minimized layout with clean design system:
|
||||
* - No inline API key input (uses DocsApiKeyInput component)
|
||||
* - Clean header with method badge, endpoint, and expand button
|
||||
* - Full-width code snippet area
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface InteractiveAPIWidgetFinalProps {
|
||||
interface InteractiveAPIWidgetProps {
|
||||
endpoint: string;
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||
description: string;
|
||||
|
|
@ -46,12 +46,12 @@ const getMethodBadgeStyle = (method: string): string => {
|
|||
}
|
||||
};
|
||||
|
||||
export const InteractiveAPIWidgetFinal = ({
|
||||
export const InteractiveAPIWidget = ({
|
||||
endpoint,
|
||||
method,
|
||||
description,
|
||||
parameters = [],
|
||||
}: InteractiveAPIWidgetFinalProps) => {
|
||||
}: InteractiveAPIWidgetProps) => {
|
||||
const [language, setLanguage] = useState<Language>('curl');
|
||||
const [apiKey, setApiKey] = useState('');
|
||||
const [isExecuting, setIsExecuting] = useState(false);
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Layout - Variant A: Clean & Minimal
|
||||
*
|
||||
* Design Philosophy: Vercel-inspired spacious, focused reading experience
|
||||
*
|
||||
* Layout Structure:
|
||||
* - Left Sidebar: Thin (256px) with minimal design
|
||||
* - Content Area: Wide margins (max-w-3xl) for comfortable reading
|
||||
* - Right TOC: Subtle and unobtrusive (224px)
|
||||
*
|
||||
* Responsive Behavior:
|
||||
* - Mobile (<768px): Single column, sidebars become overlays
|
||||
* - Tablet (768px-1024px): Content + TOC only
|
||||
* - Desktop (>1024px): Full three-column layout
|
||||
*
|
||||
* Design Characteristics:
|
||||
* - Generous whitespace
|
||||
* - Subtle borders and shadows
|
||||
* - Focus on content clarity
|
||||
* - Minimal visual noise
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface DocsLayoutAProps {
|
||||
sidebar: ReactNode;
|
||||
children: ReactNode;
|
||||
toc: ReactNode;
|
||||
}
|
||||
|
||||
export const DocsLayoutA = ({ sidebar, children, toc }: DocsLayoutAProps) => {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,178 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Sidebar - Variant A: Clean & Minimal
|
||||
*
|
||||
* Design Philosophy: Vercel-inspired minimal navigation
|
||||
*
|
||||
* Features:
|
||||
* - Thin sidebar with subtle hover states
|
||||
* - Collapsible section groups
|
||||
* - Active state: Purple left border + text
|
||||
* - Minimal icons (chevron for expandable items)
|
||||
* - Clean, uncluttered appearance
|
||||
*
|
||||
* Navigation Structure:
|
||||
* - Getting Started
|
||||
* - API Reference (collapsible)
|
||||
* - Text to Image
|
||||
* - Upload
|
||||
* - Images
|
||||
* - Guides (collapsible)
|
||||
* - Authentication
|
||||
* - Error Handling
|
||||
* - Rate Limits
|
||||
* - Examples
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
interface NavItem {
|
||||
label: string;
|
||||
href: string;
|
||||
icon?: string;
|
||||
children?: NavItem[];
|
||||
}
|
||||
|
||||
interface DocsSidebarAProps {
|
||||
currentPath: string;
|
||||
}
|
||||
|
||||
const navigationItems: NavItem[] = [
|
||||
{
|
||||
label: 'Getting Started',
|
||||
href: '/docs/variant-a',
|
||||
icon: '🚀',
|
||||
},
|
||||
{
|
||||
label: 'API Reference',
|
||||
href: '/docs/variant-a/api',
|
||||
icon: '📚',
|
||||
children: [
|
||||
{ label: 'Text to Image', href: '/docs/variant-a/api/text-to-image' },
|
||||
{ label: 'Upload', href: '/docs/variant-a/api/upload' },
|
||||
{ label: 'Images', href: '/docs/variant-a/api/images' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Guides',
|
||||
href: '/docs/variant-a/guides',
|
||||
icon: '📖',
|
||||
children: [
|
||||
{ label: 'Authentication', href: '/docs/variant-a/guides/authentication' },
|
||||
{ label: 'Error Handling', href: '/docs/variant-a/guides/error-handling' },
|
||||
{ label: 'Rate Limits', href: '/docs/variant-a/guides/rate-limits' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Examples',
|
||||
href: '/docs/variant-a/examples',
|
||||
icon: '💡',
|
||||
},
|
||||
];
|
||||
|
||||
export const DocsSidebarA = ({ currentPath }: DocsSidebarAProps) => {
|
||||
const [expandedSections, setExpandedSections] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Table of Contents - Variant A: Clean & Minimal
|
||||
*
|
||||
* Design Philosophy: Subtle, unobtrusive TOC
|
||||
*
|
||||
* Features:
|
||||
* - Small indicator dots for section levels
|
||||
* - Smooth scroll to section
|
||||
* - Active section highlighting (purple text)
|
||||
* - Sticky positioning
|
||||
* - Minimal visual weight
|
||||
*
|
||||
* Behavior:
|
||||
* - Extracts H2 and H3 headings from content
|
||||
* - Tracks scroll position to highlight active section
|
||||
* - Click to smooth scroll to section
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface TocItem {
|
||||
id: string;
|
||||
text: string;
|
||||
level: number;
|
||||
}
|
||||
|
||||
interface DocsTOCAProps {
|
||||
items: TocItem[];
|
||||
}
|
||||
|
||||
export const DocsTOCA = ({ items }: DocsTOCAProps) => {
|
||||
const [activeId, setActiveId] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,293 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Interactive API Widget - Variant A: Clean & Minimal
|
||||
*
|
||||
* Design Philosophy: Inline playground with tabbed interface
|
||||
*
|
||||
* Features:
|
||||
* - Multi-language code tabs (curl, JavaScript, Python, Go)
|
||||
* - API key input field (persists via localStorage)
|
||||
* - "Try It" button to execute live requests
|
||||
* - Response viewer with syntax highlighting
|
||||
* - Request/Response tabs
|
||||
* - Error state handling
|
||||
* - Clean, focused design
|
||||
*
|
||||
* Layout:
|
||||
* - Top: Language tabs + Copy button
|
||||
* - Middle: Code preview OR Request params
|
||||
* - Bottom: Try It button
|
||||
* - Response: Expandable section below
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface InteractiveAPIWidgetAProps {
|
||||
endpoint: string;
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||
description: string;
|
||||
parameters?: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
description: string;
|
||||
defaultValue?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||
type ViewMode = 'code' | 'response';
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||
|
||||
export const InteractiveAPIWidgetA = ({
|
||||
endpoint,
|
||||
method,
|
||||
description,
|
||||
parameters = [],
|
||||
}: InteractiveAPIWidgetAProps) => {
|
||||
const [language, setLanguage] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Layout - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Design Philosophy: Next.js-inspired dense, hierarchical layout
|
||||
*
|
||||
* Layout Structure:
|
||||
* - Left Sidebar: Wider (280px) with nested tree structure
|
||||
* - Content Area: Narrower margins to show more content
|
||||
* - Right TOC: Prominent with progress indicator (240px)
|
||||
*
|
||||
* Responsive Behavior:
|
||||
* - Mobile (<768px): Bottom sheet navigation
|
||||
* - Tablet (768px-1024px): Collapsible sidebar + TOC
|
||||
* - Desktop (>1024px): Full three-column layout
|
||||
*
|
||||
* Design Characteristics:
|
||||
* - Compact spacing
|
||||
* - More content per screen
|
||||
* - Nested navigation tree
|
||||
* - Section numbers throughout
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface DocsLayoutBProps {
|
||||
sidebar: ReactNode;
|
||||
children: ReactNode;
|
||||
toc: ReactNode;
|
||||
}
|
||||
|
||||
export const DocsLayoutB = ({ sidebar, children, toc }: DocsLayoutBProps) => {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Sidebar - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Design Philosophy: Next.js-inspired nested tree structure
|
||||
*
|
||||
* Features:
|
||||
* - Wider sidebar with deep nesting
|
||||
* - Section numbers for all items
|
||||
* - Compact spacing (more items visible)
|
||||
* - Indent levels for hierarchy
|
||||
* - Active state: Purple background + bold
|
||||
* - Expand/collapse all button
|
||||
*
|
||||
* Navigation Structure with numbers:
|
||||
* 1. Getting Started
|
||||
* 2. API Reference
|
||||
* 2.1 Text to Image
|
||||
* 2.2 Upload
|
||||
* 2.3 Images
|
||||
* 3. Guides
|
||||
* 3.1 Authentication
|
||||
* 3.2 Error Handling
|
||||
* 3.3 Rate Limits
|
||||
* 4. Examples
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
interface NavItem {
|
||||
label: string;
|
||||
href: string;
|
||||
number?: string;
|
||||
children?: NavItem[];
|
||||
}
|
||||
|
||||
interface DocsSidebarBProps {
|
||||
currentPath: string;
|
||||
}
|
||||
|
||||
const navigationItems: NavItem[] = [
|
||||
{
|
||||
label: 'Getting Started',
|
||||
href: '/docs/variant-b',
|
||||
number: '1',
|
||||
},
|
||||
{
|
||||
label: 'API Reference',
|
||||
href: '/docs/variant-b/api',
|
||||
number: '2',
|
||||
children: [
|
||||
{ label: 'Text to Image', href: '/docs/variant-b/api/text-to-image', number: '2.1' },
|
||||
{ label: 'Upload', href: '/docs/variant-b/api/upload', number: '2.2' },
|
||||
{ label: 'Images', href: '/docs/variant-b/api/images', number: '2.3' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Guides',
|
||||
href: '/docs/variant-b/guides',
|
||||
number: '3',
|
||||
children: [
|
||||
{ label: 'Authentication', href: '/docs/variant-b/guides/authentication', number: '3.1' },
|
||||
{ label: 'Error Handling', href: '/docs/variant-b/guides/error-handling', number: '3.2' },
|
||||
{ label: 'Rate Limits', href: '/docs/variant-b/guides/rate-limits', number: '3.3' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Examples',
|
||||
href: '/docs/variant-b/examples',
|
||||
number: '4',
|
||||
},
|
||||
];
|
||||
|
||||
export const DocsSidebarB = ({ currentPath }: DocsSidebarBProps) => {
|
||||
const [expandedSections, setExpandedSections] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Table of Contents - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Design Philosophy: Prominent TOC with progress indicator
|
||||
*
|
||||
* Features:
|
||||
* - Section numbers matching content
|
||||
* - Progress bar showing read percentage
|
||||
* - Larger, more prominent design
|
||||
* - Active section with purple highlight
|
||||
* - Sticky positioning with scroll progress
|
||||
*
|
||||
* Behavior:
|
||||
* - Extracts H2 and H3 headings with numbers
|
||||
* - Shows reading progress percentage
|
||||
* - Click to smooth scroll to section
|
||||
* - Visual progress bar
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface TocItem {
|
||||
id: string;
|
||||
text: string;
|
||||
level: number;
|
||||
}
|
||||
|
||||
interface DocsTOCBProps {
|
||||
items: TocItem[];
|
||||
}
|
||||
|
||||
export const DocsTOCB = ({ items }: DocsTOCBProps) => {
|
||||
const [activeId, setActiveId] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,291 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Interactive API Widget - Variant B: Dense & Information-Rich
|
||||
*
|
||||
* Design Philosophy: Side-by-side code editor with persistent API key bar
|
||||
*
|
||||
* Features:
|
||||
* - Persistent API key bar at the top of page (sticky)
|
||||
* - Side-by-side code and response layout
|
||||
* - Multi-language tabs (curl, JavaScript, Python, Go)
|
||||
* - Live request execution
|
||||
* - Compact, information-dense design
|
||||
* - Parameter form on the left
|
||||
* - Response on the right
|
||||
*
|
||||
* Layout:
|
||||
* - Top: Sticky API key bar (global for page)
|
||||
* - Left: Code + Parameters
|
||||
* - Right: Response viewer
|
||||
* - Bottom: Try It button
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface InteractiveAPIWidgetBProps {
|
||||
endpoint: string;
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||
description: string;
|
||||
parameters?: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
description: string;
|
||||
defaultValue?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||
|
||||
export const InteractiveAPIWidgetB = ({
|
||||
endpoint,
|
||||
method,
|
||||
description,
|
||||
parameters = [],
|
||||
}: InteractiveAPIWidgetBProps) => {
|
||||
const [language, setLanguage] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Layout - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Colorful, card-based, engaging visual layout
|
||||
*
|
||||
* Layout Structure:
|
||||
* - Left Sidebar: Wide (320px) with large card-style navigation
|
||||
* - Content Area: Generous padding (p-12) with wide max-width (max-w-5xl)
|
||||
* - Right TOC: Floating card with gradient borders (280px)
|
||||
*
|
||||
* Design Characteristics:
|
||||
* - Colorful gradient borders everywhere (purple/cyan)
|
||||
* - Card-based design with shadows
|
||||
* - Large, generous spacing (p-6, gap-6, mb-12)
|
||||
* - Playful and engaging visual style
|
||||
* - NO section numbers (more visual/intuitive)
|
||||
* - Large emoji icons throughout
|
||||
* - Floating shadow effects
|
||||
*
|
||||
* Responsive Behavior:
|
||||
* - Mobile (<768px): Single column, cards stack
|
||||
* - Tablet (768px-1024px): Content + floating TOC
|
||||
* - Desktop (>1024px): Full three-column card layout
|
||||
*
|
||||
* Color Palette:
|
||||
* - Purple gradients: from-purple-500/30 to-purple-600/20
|
||||
* - Cyan gradients: from-cyan-500/30 to-cyan-600/20
|
||||
* - Amber accents: amber-500, amber-600
|
||||
* - Background: slate-950, slate-900
|
||||
* - Borders: purple-500/40, cyan-500/40, slate-700
|
||||
* - Shadows: shadow-lg shadow-purple-500/20
|
||||
*/
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface DocsLayoutCProps {
|
||||
sidebar: ReactNode;
|
||||
children: ReactNode;
|
||||
toc: ReactNode;
|
||||
}
|
||||
|
||||
export const DocsLayoutC = ({ sidebar, children, toc }: DocsLayoutCProps) => {
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Documentation Sidebar - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Card-based navigation with large colorful visual elements
|
||||
*
|
||||
* Features:
|
||||
* - Navigation items as large gradient-bordered cards
|
||||
* - Large emoji icons (text-2xl) for visual hierarchy
|
||||
* - Alternating purple/cyan gradient accents
|
||||
* - Generous spacing (gap-4, p-4 per item)
|
||||
* - Touch-friendly minimum heights (min-h-12)
|
||||
* - NO section numbers (more playful/intuitive)
|
||||
* - Hover effects with shadow and scale
|
||||
* - Active state with prominent gradient background
|
||||
*
|
||||
* Navigation Structure (NO numbers):
|
||||
* - 🚀 Getting Started
|
||||
* - 📚 API Reference
|
||||
* - 🎨 Text to Image
|
||||
* - 📤 Upload
|
||||
* - 🖼️ Images
|
||||
* - 🔐 Guides
|
||||
* - 🔑 Authentication
|
||||
* - ⚠️ Error Handling
|
||||
* - ⏱️ Rate Limits
|
||||
* - 💡 Examples
|
||||
*
|
||||
* Color Palette:
|
||||
* - Purple: from-purple-500/30 to-purple-600/20
|
||||
* - Cyan: from-cyan-500/30 to-cyan-600/20
|
||||
* - Active: bg-gradient-to-br from-purple-500/30 to-cyan-500/30
|
||||
* - Hover: shadow-lg shadow-purple-500/20, scale-102
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
interface NavItem {
|
||||
label: string;
|
||||
href: string;
|
||||
icon: string;
|
||||
color: 'purple' | 'cyan' | 'amber';
|
||||
children?: NavItem[];
|
||||
}
|
||||
|
||||
interface DocsSidebarCProps {
|
||||
currentPath: string;
|
||||
}
|
||||
|
||||
const navigationItems: NavItem[] = [
|
||||
{
|
||||
label: 'Getting Started',
|
||||
href: '/docs/variant-c',
|
||||
icon: '🚀',
|
||||
color: 'purple',
|
||||
},
|
||||
{
|
||||
label: 'API Reference',
|
||||
href: '/docs/variant-c/api',
|
||||
icon: '📚',
|
||||
color: 'cyan',
|
||||
children: [
|
||||
{ label: 'Text to Image', href: '/docs/variant-c/api/text-to-image', icon: '🎨', color: 'purple' },
|
||||
{ label: 'Upload', href: '/docs/variant-c/api/upload', icon: '📤', color: 'cyan' },
|
||||
{ label: 'Images', href: '/docs/variant-c/api/images', icon: '🖼️', color: 'purple' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Guides',
|
||||
href: '/docs/variant-c/guides',
|
||||
icon: '🔐',
|
||||
color: 'purple',
|
||||
children: [
|
||||
{ label: 'Authentication', href: '/docs/variant-c/guides/authentication', icon: '🔑', color: 'cyan' },
|
||||
{ label: 'Error Handling', href: '/docs/variant-c/guides/error-handling', icon: '⚠️', color: 'purple' },
|
||||
{ label: 'Rate Limits', href: '/docs/variant-c/guides/rate-limits', icon: '⏱️', color: 'cyan' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Examples',
|
||||
href: '/docs/variant-c/examples',
|
||||
icon: '💡',
|
||||
color: 'amber',
|
||||
},
|
||||
];
|
||||
|
||||
const getGradientClasses = (color: 'purple' | 'cyan' | 'amber', active: boolean) => {
|
||||
if (active) {
|
||||
return 'bg-gradient-to-br from-purple-500/30 to-cyan-500/30 border-purple-500/60 shadow-lg shadow-purple-500/30';
|
||||
}
|
||||
|
||||
const baseClasses = 'border-2 hover:shadow-lg transition-all duration-300 hover:scale-[1.02]';
|
||||
|
||||
switch (color) {
|
||||
case 'purple':
|
||||
return `${baseClasses} border-purple-500/30 hover:border-purple-500/50 hover:shadow-purple-500/20 hover:bg-purple-500/10`;
|
||||
case 'cyan':
|
||||
return `${baseClasses} border-cyan-500/30 hover:border-cyan-500/50 hover:shadow-cyan-500/20 hover:bg-cyan-500/10`;
|
||||
case 'amber':
|
||||
return `${baseClasses} border-amber-500/30 hover:border-amber-500/50 hover:shadow-amber-500/20 hover:bg-amber-500/10`;
|
||||
default:
|
||||
return baseClasses;
|
||||
}
|
||||
};
|
||||
|
||||
export const DocsSidebarC = ({ currentPath }: DocsSidebarCProps) => {
|
||||
const [expandedSections, setExpandedSections] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Table of Contents - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Floating card with colorful visual indicators
|
||||
*
|
||||
* Features:
|
||||
* - Wrapped in large gradient-bordered card
|
||||
* - Colorful dot indicators (alternating purple/cyan/amber)
|
||||
* - Large text sizes (text-base for items)
|
||||
* - Generous spacing (p-6, gap-4)
|
||||
* - Floating shadow effect with colored glow
|
||||
* - NO section numbers (more visual/playful)
|
||||
* - Active state with gradient background
|
||||
* - Smooth hover animations with scale
|
||||
* - Fun, engaging design with emoji header
|
||||
*
|
||||
* Visual Elements:
|
||||
* - Large colored dots instead of numbers
|
||||
* - Gradient progress bar with rainbow colors
|
||||
* - Active item with gradient highlight
|
||||
* - Hover effects with shadow and scale
|
||||
*
|
||||
* Behavior:
|
||||
* - Extracts H2 and H3 headings (no numbers)
|
||||
* - Shows reading progress with colorful bar
|
||||
* - Click to smooth scroll to section
|
||||
* - Visual feedback with animations
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface TocItem {
|
||||
id: string;
|
||||
text: string;
|
||||
level: number;
|
||||
}
|
||||
|
||||
interface DocsTOCCProps {
|
||||
items: TocItem[];
|
||||
}
|
||||
|
||||
const getColorForIndex = (index: number): string => {
|
||||
const colors = ['purple', 'cyan', 'amber'];
|
||||
return colors[index % colors.length];
|
||||
};
|
||||
|
||||
const getDotClasses = (color: string, isActive: boolean): string => {
|
||||
const baseClasses = 'w-2.5 h-2.5 rounded-full flex-shrink-0 transition-all duration-300';
|
||||
|
||||
if (isActive) {
|
||||
return `${baseClasses} shadow-lg ${
|
||||
color === 'purple'
|
||||
? 'bg-purple-500 shadow-purple-500/50'
|
||||
: color === 'cyan'
|
||||
? 'bg-cyan-500 shadow-cyan-500/50'
|
||||
: 'bg-amber-500 shadow-amber-500/50'
|
||||
}`;
|
||||
}
|
||||
|
||||
return `${baseClasses} ${
|
||||
color === 'purple'
|
||||
? 'bg-purple-500/40'
|
||||
: color === 'cyan'
|
||||
? 'bg-cyan-500/40'
|
||||
: 'bg-amber-500/40'
|
||||
}`;
|
||||
};
|
||||
|
||||
export const DocsTOCC = ({ items }: DocsTOCCProps) => {
|
||||
const [activeId, setActiveId] = useState<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>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,393 +0,0 @@
|
|||
'use client';
|
||||
|
||||
/**
|
||||
* Interactive API Widget - Variant C: Modern & Visual (Shopify-inspired)
|
||||
*
|
||||
* Design Philosophy: Floating, expandable card with colorful visual feedback
|
||||
*
|
||||
* Features:
|
||||
* - Full-screen expandable mode toggle button
|
||||
* - Large gradient-bordered card with shadow glow
|
||||
* - Prominent "Test Now ⚡" button (larger, more visual)
|
||||
* - Response in colorful gradient-bordered card
|
||||
* - Success/error states with vibrant colored badges
|
||||
* - More visual feedback and animations
|
||||
* - Large emoji icons throughout
|
||||
* - Colorful code syntax highlighting hints
|
||||
* - Floating shadow effects
|
||||
*
|
||||
* Layout:
|
||||
* - Top: Large colorful API key input card
|
||||
* - Main: Expandable code editor with rainbow gradient border
|
||||
* - Language tabs as colorful pills
|
||||
* - Large prominent "Test Now" button with gradient
|
||||
* - Response card with colored status indicators
|
||||
*
|
||||
* Visual Elements:
|
||||
* - Purple/cyan/amber gradients everywhere
|
||||
* - Large shadows with colored glows
|
||||
* - Scale and hover animations
|
||||
* - Success: Green gradient with glow
|
||||
* - Error: Red gradient with glow
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface InteractiveAPIWidgetCProps {
|
||||
endpoint: string;
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||
description: string;
|
||||
parameters?: Array<{
|
||||
name: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
description: string;
|
||||
defaultValue?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||
|
||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||
|
||||
const getMethodColor = (method: string): string => {
|
||||
switch (method) {
|
||||
case 'GET':
|
||||
return 'from-cyan-500 to-cyan-600';
|
||||
case 'POST':
|
||||
return 'from-purple-500 to-purple-600';
|
||||
case 'PUT':
|
||||
return 'from-amber-500 to-amber-600';
|
||||
case 'DELETE':
|
||||
return 'from-red-500 to-red-600';
|
||||
default:
|
||||
return 'from-purple-500 to-cyan-500';
|
||||
}
|
||||
};
|
||||
|
||||
export const InteractiveAPIWidgetC = ({
|
||||
endpoint,
|
||||
method,
|
||||
description,
|
||||
parameters = [],
|
||||
}: InteractiveAPIWidgetCProps) => {
|
||||
const [language, setLanguage] = useState<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>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in New Issue