Compare commits
No commits in common. "da6887d41c6dbaaee6368455e09776144a737b89" and "7368d287e9edf9bf0a30928f9f6fb3cd791bc55b" have entirely different histories.
da6887d41c
...
7368d287e9
|
|
@ -33,14 +33,11 @@
|
||||||
"DATABASE_URI": "postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db"
|
"DATABASE_URI": "postgresql://banatie_user:banatie_secure_password@localhost:5460/banatie_db"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"perplexity": {
|
"mastra": {
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
"command": "npx",
|
"command": "npx",
|
||||||
"args": ["-y", "perplexity-mcp"],
|
"args": ["@mastra/mcp-docs-server@latest"],
|
||||||
"env": {
|
"env": {}
|
||||||
"PERPLEXITY_API_KEY": "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",
|
|
||||||
"PERPLEXITY_TIMEOUT_MS": "600000"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"browsermcp": {
|
"browsermcp": {
|
||||||
"type": "stdio",
|
"type": "stdio",
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@
|
||||||
"dev": "next dev -p 3010",
|
"dev": "next dev -p 3010",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"deploy": "cp -r out/* /var/www/banatie.app/",
|
"deploy": "cp -r out/* /var/www/banatie.app/"
|
||||||
"typecheck": "tsc --noEmit"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API Reference: Text to Image
|
* API Reference: Text to Image - Final Variant
|
||||||
*
|
*
|
||||||
* Refactored to use DocPage component for consistent layout
|
* Features:
|
||||||
* Layout handles SubsectionNav and Left Sidebar
|
* - SubsectionNav at top
|
||||||
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
|
* - InteractiveAPIWidgetFinal with expand + success styling
|
||||||
* This page provides only the content (Hero + sections)
|
* - Enhanced tables for parameters and error codes
|
||||||
|
* - Compact TipBox for parameter descriptions
|
||||||
|
* - Simplified Next Steps
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal';
|
||||||
|
import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal';
|
||||||
|
import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal';
|
||||||
|
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||||
import { Table } from '@/components/docs/shared/Table';
|
import { Table } from '@/components/docs/shared/Table';
|
||||||
|
import { InteractiveAPIWidgetFinal } from '@/components/docs/final/InteractiveAPIWidgetFinal';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
import { DocPage } from '@/components/docs/layout/DocPage';
|
|
||||||
import { InteractiveAPIWidget } from '@/components/docs/blocks/InteractiveAPIWidget';
|
|
||||||
import {
|
|
||||||
Hero,
|
|
||||||
SectionHeader,
|
|
||||||
InlineCode,
|
|
||||||
EndpointCard,
|
|
||||||
} from '@/components/docs/blocks';
|
|
||||||
|
|
||||||
const tocItems = [
|
const tocItems = [
|
||||||
{ id: 'overview', text: 'Overview', level: 2 },
|
{ id: 'overview', text: 'Overview', level: 2 },
|
||||||
|
|
@ -31,6 +31,12 @@ const tocItems = [
|
||||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ label: 'Documentation', href: '/docs/final' },
|
||||||
|
{ label: 'Demo', href: '/demo' },
|
||||||
|
{ label: 'Examples', href: '/docs/final/examples' },
|
||||||
|
];
|
||||||
|
|
||||||
const parameters = [
|
const parameters = [
|
||||||
{ name: 'prompt', type: 'string', required: true, description: 'Text description of the image to generate' },
|
{ name: 'prompt', type: 'string', required: true, description: 'Text description of the image to generate' },
|
||||||
{ name: 'filename', type: 'string', required: false, description: 'Output filename (without extension)' },
|
{ name: 'filename', type: 'string', required: false, description: 'Output filename (without extension)' },
|
||||||
|
|
@ -40,70 +46,67 @@ const parameters = [
|
||||||
|
|
||||||
export default function TextToImageAPIPage() {
|
export default function TextToImageAPIPage() {
|
||||||
return (
|
return (
|
||||||
<DocPage
|
<>
|
||||||
breadcrumbItems={[
|
{/* Subsection Navigation with API Key Input */}
|
||||||
{ label: 'Documentation', href: '/docs' },
|
<SubsectionNav
|
||||||
{ label: 'API Reference', href: '/docs/api' },
|
items={navItems}
|
||||||
{ label: 'Text to Image' },
|
currentPath="/docs/final/api/text-to-image"
|
||||||
]}
|
showApiKeyInput={true}
|
||||||
tocItems={tocItems}
|
/>
|
||||||
nextSteps={{
|
|
||||||
links: [
|
<DocsLayoutFinal
|
||||||
{
|
sidebar={<DocsSidebarFinal currentPath="/docs/final/api/text-to-image" />}
|
||||||
href: '/docs/api/upload',
|
toc={<DocsTOCFinal items={tocItems} />}
|
||||||
title: 'Upload API',
|
>
|
||||||
description: 'Learn how to upload reference images for image-to-image generation.',
|
<Breadcrumb
|
||||||
accent: 'primary',
|
items={[
|
||||||
},
|
{ label: 'Documentation', href: '/docs' },
|
||||||
{
|
{ label: 'API Reference', href: '/docs/final/api' },
|
||||||
href: '/docs/guides/error-handling',
|
{ label: 'Text to Image' },
|
||||||
title: 'Error Handling',
|
]}
|
||||||
description: 'Best practices for handling errors and retries in production.',
|
/>
|
||||||
accent: 'secondary',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<Hero
|
<div className="mb-12">
|
||||||
title="Text to Image"
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Text to Image</h1>
|
||||||
subtitle="Generate high-quality images from text prompts using AI-powered models."
|
<p className="text-xl text-gray-400 leading-relaxed">
|
||||||
/>
|
Generate high-quality images from text prompts using AI-powered models.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Overview */}
|
{/* Overview */}
|
||||||
<section id="overview" className="mb-12">
|
<section id="overview" className="mb-12">
|
||||||
<SectionHeader level={2} id="overview">
|
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
|
||||||
Overview
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
The Text to Image endpoint allows you to generate images from natural language descriptions.
|
The Text to Image endpoint allows you to generate images from natural language descriptions.
|
||||||
Powered by Google Gemini 2.5 Flash and Imagen 4.0, it produces photorealistic images
|
Powered by Google Gemini 2.5 Flash and Imagen 4.0, it produces photorealistic images
|
||||||
optimized for your specified requirements.
|
optimized for your specified requirements.
|
||||||
</p>
|
</p>
|
||||||
<TipBox variant="compact" type="info">
|
<TipBox variant="compact" type="info">
|
||||||
<strong>Tip:</strong> Enable <InlineCode>autoEnhance</InlineCode>
|
<strong>Tip:</strong> Enable <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">autoEnhance</code>
|
||||||
to let AI improve your prompts for better image quality.
|
to let AI improve your prompts for better image quality.
|
||||||
</TipBox>
|
</TipBox>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Endpoint */}
|
{/* Endpoint */}
|
||||||
<section id="endpoint" className="mb-12">
|
<section id="endpoint" className="mb-12">
|
||||||
<SectionHeader level={2} id="endpoint">
|
<h2 className="text-3xl font-bold text-white mb-4">Endpoint</h2>
|
||||||
Endpoint
|
<div className="p-4 bg-slate-900/50 border border-slate-700 rounded-xl">
|
||||||
</SectionHeader>
|
<div className="flex items-center gap-3 mb-2">
|
||||||
<EndpointCard
|
<span className="px-3 py-1 bg-green-600/20 text-green-400 text-xs font-bold rounded">
|
||||||
method="POST"
|
POST
|
||||||
endpoint="/api/text-to-image"
|
</span>
|
||||||
baseUrl="https://api.banatie.com"
|
<code className="text-sm text-white">/api/text-to-image</code>
|
||||||
/>
|
</div>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Base URL: <code className="text-purple-400">https://api.banatie.com</code>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Parameters */}
|
{/* Parameters */}
|
||||||
<section id="parameters" className="mb-12">
|
<section id="parameters" className="mb-12">
|
||||||
<SectionHeader level={2} id="parameters" className="mb-6">
|
<h2 className="text-3xl font-bold text-white mb-6">Parameters</h2>
|
||||||
Parameters
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
All parameters should be sent in the request body as JSON.
|
All parameters should be sent in the request body as JSON.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -111,7 +114,7 @@ export default function TextToImageAPIPage() {
|
||||||
<Table
|
<Table
|
||||||
headers={['Parameter', 'Type', 'Required', 'Description']}
|
headers={['Parameter', 'Type', 'Required', 'Description']}
|
||||||
rows={parameters.map((param) => [
|
rows={parameters.map((param) => [
|
||||||
<InlineCode key="name">{param.name}</InlineCode>,
|
<code key="name" className="text-purple-400">{param.name}</code>,
|
||||||
<span key="type" className="text-cyan-400">{param.type}</span>,
|
<span key="type" className="text-cyan-400">{param.type}</span>,
|
||||||
<span key="required" className={param.required ? 'text-green-400' : 'text-gray-500'}>
|
<span key="required" className={param.required ? 'text-green-400' : 'text-gray-500'}>
|
||||||
{param.required ? 'Yes' : 'No'}
|
{param.required ? 'Yes' : 'No'}
|
||||||
|
|
@ -122,18 +125,16 @@ export default function TextToImageAPIPage() {
|
||||||
|
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<TipBox variant="compact" type="info">
|
<TipBox variant="compact" type="info">
|
||||||
<strong>Default Values:</strong> If not specified, <InlineCode>filename</InlineCode> is
|
<strong>Default Values:</strong> If not specified, <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">filename</code> is
|
||||||
auto-generated, <InlineCode>aspectRatio</InlineCode> defaults
|
auto-generated, <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">aspectRatio</code> defaults
|
||||||
to "1:1", and <InlineCode>autoEnhance</InlineCode> is false.
|
to "1:1", and <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">autoEnhance</code> is false.
|
||||||
</TipBox>
|
</TipBox>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Response */}
|
{/* Response */}
|
||||||
<section id="response" className="mb-12">
|
<section id="response" className="mb-12">
|
||||||
<SectionHeader level={2} id="response" className="mb-4">
|
<h2 className="text-3xl font-bold text-white mb-4">Response</h2>
|
||||||
Response
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
On success, the API returns a JSON object containing the generated image URL and metadata.
|
On success, the API returns a JSON object containing the generated image URL and metadata.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -163,9 +164,7 @@ export default function TextToImageAPIPage() {
|
||||||
|
|
||||||
{/* Error Codes */}
|
{/* Error Codes */}
|
||||||
<section id="error-codes" className="mb-12">
|
<section id="error-codes" className="mb-12">
|
||||||
<SectionHeader level={2} id="error-codes" className="mb-6">
|
<h2 className="text-3xl font-bold text-white mb-6">Error Codes</h2>
|
||||||
Error Codes
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
The API uses standard HTTP status codes and returns descriptive error messages.
|
The API uses standard HTTP status codes and returns descriptive error messages.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -174,22 +173,22 @@ export default function TextToImageAPIPage() {
|
||||||
headers={['Status Code', 'Error Type', 'Description']}
|
headers={['Status Code', 'Error Type', 'Description']}
|
||||||
rows={[
|
rows={[
|
||||||
[
|
[
|
||||||
<InlineCode key="code" color="error">400</InlineCode>,
|
<code key="code" className="text-red-400">400</code>,
|
||||||
'Bad Request',
|
'Bad Request',
|
||||||
'Missing or invalid parameters in the request body',
|
'Missing or invalid parameters in the request body',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<InlineCode key="code" color="error">401</InlineCode>,
|
<code key="code" className="text-red-400">401</code>,
|
||||||
'Unauthorized',
|
'Unauthorized',
|
||||||
'Missing or invalid API key in X-API-Key header',
|
'Missing or invalid API key in X-API-Key header',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<InlineCode key="code" color="error">429</InlineCode>,
|
<code key="code" className="text-red-400">429</code>,
|
||||||
'Rate Limit',
|
'Rate Limit',
|
||||||
'Too many requests. Check rate limit headers for retry timing',
|
'Too many requests. Check rate limit headers for retry timing',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<InlineCode key="code" color="error">500</InlineCode>,
|
<code key="code" className="text-red-400">500</code>,
|
||||||
'Server Error',
|
'Server Error',
|
||||||
'Internal server error. Contact support if persists',
|
'Internal server error. Contact support if persists',
|
||||||
],
|
],
|
||||||
|
|
@ -206,14 +205,12 @@ export default function TextToImageAPIPage() {
|
||||||
|
|
||||||
{/* Interactive Widget */}
|
{/* Interactive Widget */}
|
||||||
<section id="interactive" className="mb-12">
|
<section id="interactive" className="mb-12">
|
||||||
<SectionHeader level={2} id="interactive" className="mb-4">
|
<h2 className="text-3xl font-bold text-white mb-4">Try It Live</h2>
|
||||||
Try It Live
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
Test the API directly from this page. Enter your API key and customize the parameters below.
|
Test the API directly from this page. Enter your API key and customize the parameters below.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<InteractiveAPIWidget
|
<InteractiveAPIWidgetFinal
|
||||||
endpoint="/api/text-to-image"
|
endpoint="/api/text-to-image"
|
||||||
method="POST"
|
method="POST"
|
||||||
description="Generate an image from a text prompt"
|
description="Generate an image from a text prompt"
|
||||||
|
|
@ -221,6 +218,37 @@ export default function TextToImageAPIPage() {
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</DocPage>
|
{/* Next Steps */}
|
||||||
|
<section id="next-steps" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<a
|
||||||
|
href="/docs/final/api/upload"
|
||||||
|
className="p-5 bg-gradient-to-br from-purple-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
|
||||||
|
Upload API
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Learn how to upload reference images for image-to-image generation.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/final/guides/error-handling"
|
||||||
|
className="p-5 bg-gradient-to-br from-cyan-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Error Handling
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Best practices for handling errors and retries in production.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutFinal>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,23 +1,24 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication Guide
|
* Authentication Guide - Final Variant
|
||||||
*
|
*
|
||||||
* Refactored to use DocPage component for consistent layout
|
* Features:
|
||||||
* Layout handles SubsectionNav and Left Sidebar
|
* - SubsectionNav at top
|
||||||
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
|
* - Prominent TipBox for security warnings
|
||||||
* This page provides only the content (Hero + sections)
|
* - Compact TipBox for general tips
|
||||||
|
* - Enhanced tables for rate limits and key types
|
||||||
|
* - Simplified Next Steps
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal';
|
||||||
|
import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal';
|
||||||
|
import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal';
|
||||||
|
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||||
import { Table } from '@/components/docs/shared/Table';
|
import { Table } from '@/components/docs/shared/Table';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
import { DocPage } from '@/components/docs/layout/DocPage';
|
|
||||||
import {
|
|
||||||
Hero,
|
|
||||||
SectionHeader,
|
|
||||||
InlineCode,
|
|
||||||
} from '@/components/docs/blocks';
|
|
||||||
|
|
||||||
const tocItems = [
|
const tocItems = [
|
||||||
{ id: 'overview', text: 'Overview', level: 2 },
|
{ id: 'overview', text: 'Overview', level: 2 },
|
||||||
|
|
@ -30,53 +31,56 @@ const tocItems = [
|
||||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ label: 'Documentation', href: '/docs/final' },
|
||||||
|
{ label: 'Demo', href: '/demo' },
|
||||||
|
{ label: 'Examples', href: '/docs/final/examples' },
|
||||||
|
];
|
||||||
|
|
||||||
export default function AuthenticationGuidePage() {
|
export default function AuthenticationGuidePage() {
|
||||||
return (
|
return (
|
||||||
<DocPage
|
<>
|
||||||
breadcrumbItems={[
|
{/* Subsection Navigation */}
|
||||||
{ label: 'Documentation', href: '/docs' },
|
<SubsectionNav
|
||||||
{ label: 'Guides', href: '/docs/guides' },
|
items={navItems}
|
||||||
{ label: 'Authentication' },
|
currentPath="/docs/final/guides/authentication"
|
||||||
]}
|
ctaText="Join Beta"
|
||||||
tocItems={tocItems}
|
ctaHref="/signup"
|
||||||
nextSteps={{
|
/>
|
||||||
links: [
|
|
||||||
{
|
<DocsLayoutFinal
|
||||||
href: '/docs/api/text-to-image',
|
sidebar={<DocsSidebarFinal currentPath="/docs/final/guides/authentication" />}
|
||||||
title: 'Start Generating Images',
|
toc={<DocsTOCFinal items={tocItems} />}
|
||||||
description: 'Explore the Text to Image API and start building your integration.',
|
>
|
||||||
accent: 'primary',
|
<Breadcrumb
|
||||||
},
|
items={[
|
||||||
{
|
{ label: 'Documentation', href: '/docs' },
|
||||||
href: '/docs/guides/error-handling',
|
{ label: 'Guides', href: '/docs/final/guides' },
|
||||||
title: 'Error Handling Guide',
|
{ label: 'Authentication' },
|
||||||
description: 'Learn how to handle authentication errors and implement retry logic.',
|
]}
|
||||||
accent: 'secondary',
|
/>
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<Hero
|
<div className="mb-12">
|
||||||
title="Authentication"
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Authentication</h1>
|
||||||
subtitle="Learn how to authenticate with the Banatie API using API keys, manage rate limits, and implement security best practices."
|
<p className="text-xl text-gray-400 leading-relaxed">
|
||||||
/>
|
Learn how to authenticate with the Banatie API using API keys, manage rate limits, and
|
||||||
|
implement security best practices.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Overview */}
|
{/* Overview */}
|
||||||
<section id="overview" className="mb-12">
|
<section id="overview" className="mb-12">
|
||||||
<SectionHeader level={2} id="overview" className="mb-4">
|
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
|
||||||
Overview
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
Banatie uses API keys to authenticate requests. All API endpoints require authentication
|
Banatie uses API keys to authenticate requests. All API endpoints require authentication
|
||||||
via the <InlineCode>X-API-Key</InlineCode> header.
|
via the <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">X-API-Key</code> header.
|
||||||
API keys are tied to organizations and projects, providing fine-grained access control.
|
API keys are tied to organizations and projects, providing fine-grained access control.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<TipBox variant="compact" type="info">
|
<TipBox variant="compact" type="info">
|
||||||
<strong>Quick Start:</strong> New to API authentication? Check out our{' '}
|
<strong>Quick Start:</strong> New to API authentication? Check out our{' '}
|
||||||
<a href="/docs" className="text-purple-400 hover:underline">
|
<a href="/docs/final" className="text-purple-400 hover:underline">
|
||||||
Getting Started guide
|
Getting Started guide
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
for a step-by-step walkthrough.
|
for a step-by-step walkthrough.
|
||||||
|
|
@ -85,14 +89,10 @@ export default function AuthenticationGuidePage() {
|
||||||
|
|
||||||
{/* API Keys */}
|
{/* API Keys */}
|
||||||
<section id="api-keys" className="mb-12">
|
<section id="api-keys" className="mb-12">
|
||||||
<SectionHeader level={2} id="api-keys" className="mb-6">
|
<h2 className="text-3xl font-bold text-white mb-6">API Keys</h2>
|
||||||
API Keys
|
|
||||||
</SectionHeader>
|
|
||||||
|
|
||||||
<div id="key-types" className="mb-8">
|
<div id="key-types" className="mb-8">
|
||||||
<SectionHeader level={3} id="key-types" className="mb-4">
|
<h3 className="text-xl font-semibold text-white mb-4">Key Types</h3>
|
||||||
Key Types
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
Banatie supports two types of API keys, each with different permissions and use cases:
|
Banatie supports two types of API keys, each with different permissions and use cases:
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -101,13 +101,13 @@ export default function AuthenticationGuidePage() {
|
||||||
headers={['Key Type', 'Permissions', 'Expiration', 'Use Case']}
|
headers={['Key Type', 'Permissions', 'Expiration', 'Use Case']}
|
||||||
rows={[
|
rows={[
|
||||||
[
|
[
|
||||||
<InlineCode key="type">Master Key</InlineCode>,
|
<code key="type" className="text-purple-400">Master Key</code>,
|
||||||
'Full admin access, can create/revoke keys',
|
'Full admin access, can create/revoke keys',
|
||||||
<span key="exp" className="text-green-400">Never expires</span>,
|
<span key="exp" className="text-green-400">Never expires</span>,
|
||||||
'Server-side admin operations, key management',
|
'Server-side admin operations, key management',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<InlineCode key="type" color="success">Project Key</InlineCode>,
|
<code key="type" className="text-cyan-400">Project Key</code>,
|
||||||
'Image generation only',
|
'Image generation only',
|
||||||
<span key="exp" className="text-amber-400">90 days</span>,
|
<span key="exp" className="text-amber-400">90 days</span>,
|
||||||
'Application integration, API requests',
|
'Application integration, API requests',
|
||||||
|
|
@ -126,9 +126,7 @@ export default function AuthenticationGuidePage() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="creating-keys" className="mb-8">
|
<div id="creating-keys" className="mb-8">
|
||||||
<SectionHeader level={3} id="creating-keys" className="mb-4">
|
<h3 className="text-xl font-semibold text-white mb-4">Creating Keys</h3>
|
||||||
Creating Keys
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
For first-time setup, use the bootstrap endpoint to create your initial master key:
|
For first-time setup, use the bootstrap endpoint to create your initial master key:
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -183,11 +181,9 @@ curl -X POST https://api.banatie.com/api/admin/keys \\
|
||||||
|
|
||||||
{/* Using API Keys */}
|
{/* Using API Keys */}
|
||||||
<section id="using-keys" className="mb-12">
|
<section id="using-keys" className="mb-12">
|
||||||
<SectionHeader level={2} id="using-keys" className="mb-4">
|
<h2 className="text-3xl font-bold text-white mb-4">Using API Keys</h2>
|
||||||
Using API Keys
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
Include your API key in the <InlineCode>X-API-Key</InlineCode> header
|
Include your API key in the <code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">X-API-Key</code> header
|
||||||
with every request:
|
with every request:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -208,16 +204,14 @@ curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
<TipBox variant="compact" type="info">
|
<TipBox variant="compact" type="info">
|
||||||
<strong>Environment Variables:</strong> Store API keys in environment variables, not
|
<strong>Environment Variables:</strong> Store API keys in environment variables, not
|
||||||
hardcoded in your application. Example:{' '}
|
hardcoded in your application. Example:{' '}
|
||||||
<InlineCode>BANATIE_API_KEY</InlineCode>
|
<code className="px-1.5 py-0.5 bg-slate-800 rounded text-purple-400">BANATIE_API_KEY</code>
|
||||||
</TipBox>
|
</TipBox>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Rate Limits */}
|
{/* Rate Limits */}
|
||||||
<section id="rate-limits" className="mb-12">
|
<section id="rate-limits" className="mb-12">
|
||||||
<SectionHeader level={2} id="rate-limits" className="mb-6">
|
<h2 className="text-3xl font-bold text-white mb-6">Rate Limits</h2>
|
||||||
Rate Limits
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
API keys are subject to rate limits to ensure fair usage and system stability. Limits
|
API keys are subject to rate limits to ensure fair usage and system stability. Limits
|
||||||
vary by key type and plan tier:
|
vary by key type and plan tier:
|
||||||
|
|
@ -227,19 +221,19 @@ curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
headers={['Key Type', 'Rate Limit', 'Reset Window', 'Upgrade Available']}
|
headers={['Key Type', 'Rate Limit', 'Reset Window', 'Upgrade Available']}
|
||||||
rows={[
|
rows={[
|
||||||
[
|
[
|
||||||
<InlineCode key="type">Master Key</InlineCode>,
|
<code key="type" className="text-purple-400">Master Key</code>,
|
||||||
<span key="limit" className="text-green-400">Unlimited</span>,
|
<span key="limit" className="text-green-400">Unlimited</span>,
|
||||||
'N/A',
|
'N/A',
|
||||||
'N/A',
|
'N/A',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<InlineCode key="type" color="success">Project Key (Free)</InlineCode>,
|
<code key="type" className="text-cyan-400">Project Key (Free)</code>,
|
||||||
<span key="limit" className="text-amber-400">100 requests/hour</span>,
|
<span key="limit" className="text-amber-400">100 requests/hour</span>,
|
||||||
'1 hour rolling',
|
'1 hour rolling',
|
||||||
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
|
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
<InlineCode key="type" color="success">Project Key (Pro)</InlineCode>,
|
<code key="type" className="text-cyan-400">Project Key (Pro)</code>,
|
||||||
<span key="limit" className="text-green-400">1,000 requests/hour</span>,
|
<span key="limit" className="text-green-400">1,000 requests/hour</span>,
|
||||||
'1 hour rolling',
|
'1 hour rolling',
|
||||||
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
|
<a key="upgrade" href="/pricing" className="text-purple-400 hover:underline">Yes</a>,
|
||||||
|
|
@ -249,7 +243,7 @@ curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
When you exceed rate limits, the API returns a <InlineCode color="error">429 Too Many Requests</InlineCode> status.
|
When you exceed rate limits, the API returns a <code className="px-1.5 py-0.5 bg-slate-800 rounded text-red-400">429 Too Many Requests</code> status.
|
||||||
Check the response headers for retry timing:
|
Check the response headers for retry timing:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -272,9 +266,7 @@ X-RateLimit-Reset: 1704153600
|
||||||
|
|
||||||
{/* Security Best Practices */}
|
{/* Security Best Practices */}
|
||||||
<section id="security" className="mb-12">
|
<section id="security" className="mb-12">
|
||||||
<SectionHeader level={2} id="security" className="mb-6">
|
<h2 className="text-3xl font-bold text-white mb-6">Security Best Practices</h2>
|
||||||
Security Best Practices
|
|
||||||
</SectionHeader>
|
|
||||||
|
|
||||||
<TipBox variant="prominent" type="warning">
|
<TipBox variant="prominent" type="warning">
|
||||||
<strong className="text-amber-300">Critical Security Guidelines:</strong>
|
<strong className="text-amber-300">Critical Security Guidelines:</strong>
|
||||||
|
|
@ -308,6 +300,37 @@ curl -X DELETE https://api.banatie.com/api/admin/keys/OLD_KEY_ID \\
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</DocPage>
|
{/* Next Steps */}
|
||||||
|
<section id="next-steps" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<a
|
||||||
|
href="/docs/final/api/text-to-image"
|
||||||
|
className="p-5 bg-gradient-to-br from-purple-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
|
||||||
|
Start Generating Images
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Explore the Text to Image API and start building your integration.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/final/guides/error-handling"
|
||||||
|
className="p-5 bg-gradient-to-br from-cyan-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Error Handling Guide
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Learn how to handle authentication errors and implement retry logic.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutFinal>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,225 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting Started Page - Final Variant
|
||||||
|
*
|
||||||
|
* Production-ready documentation landing page
|
||||||
|
* Features:
|
||||||
|
* - SubsectionNav at top
|
||||||
|
* - Both TipBox styles (compact + prominent)
|
||||||
|
* - Enhanced tables
|
||||||
|
* - Simplified Next Steps (2 cards only)
|
||||||
|
* - Clean, accessible design
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutFinal } from '@/components/docs/final/DocsLayoutFinal';
|
||||||
|
import { DocsSidebarFinal } from '@/components/docs/final/DocsSidebarFinal';
|
||||||
|
import { DocsTOCFinal } from '@/components/docs/final/DocsTOCFinal';
|
||||||
|
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
||||||
|
import { TipBox } from '@/components/docs/shared/TipBox';
|
||||||
|
import { Table } from '@/components/docs/shared/Table';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||||
|
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||||
|
{ id: 'installation', text: 'Installation', level: 3 },
|
||||||
|
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||||
|
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||||
|
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ label: 'Documentation', href: '/docs/final' },
|
||||||
|
{ label: 'Demo', href: '/demo' },
|
||||||
|
{ label: 'Examples', href: '/docs/final/examples' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function GettingStartedPageFinal() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Subsection Navigation */}
|
||||||
|
<SubsectionNav
|
||||||
|
items={navItems}
|
||||||
|
currentPath="/docs/final"
|
||||||
|
ctaText="Join Beta"
|
||||||
|
ctaHref="/signup"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DocsLayoutFinal
|
||||||
|
sidebar={<DocsSidebarFinal currentPath="/docs/final" />}
|
||||||
|
toc={<DocsTOCFinal items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Getting Started</h1>
|
||||||
|
<p className="text-xl text-gray-400 leading-relaxed">
|
||||||
|
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
|
||||||
|
generation into your applications in minutes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Introduction */}
|
||||||
|
<section id="introduction" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Introduction</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini
|
||||||
|
2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into
|
||||||
|
production-ready visuals.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Whether you are building a content creation platform, e-commerce site, or creative tool,
|
||||||
|
Banatie provides the infrastructure you need to generate high-quality images at scale.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Compact Tip Box */}
|
||||||
|
<TipBox variant="compact" type="info">
|
||||||
|
<strong>New to API integration?</strong> Start with our{' '}
|
||||||
|
<a href="/docs/final/examples" className="text-purple-400 hover:underline">
|
||||||
|
code examples
|
||||||
|
</a>{' '}
|
||||||
|
to see common use cases in action.
|
||||||
|
</TipBox>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Quick Start */}
|
||||||
|
<section id="quick-start" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Quick Start</h2>
|
||||||
|
|
||||||
|
<div id="installation" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-3">Installation</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie is a REST API, so you do not need to install any libraries. However, we provide
|
||||||
|
SDKs for popular languages to make integration easier.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using npm (JavaScript/TypeScript)
|
||||||
|
npm install @banatie/sdk
|
||||||
|
|
||||||
|
# Using pip (Python)
|
||||||
|
pip install banatie
|
||||||
|
|
||||||
|
# Using Go
|
||||||
|
go get github.com/banatie/sdk-go`}
|
||||||
|
language="bash"
|
||||||
|
filename="Installation"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="authentication" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-3">Authentication</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
All API requests require an API key. You can create an API key from your dashboard or
|
||||||
|
using the bootstrap endpoint for initial setup.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Prominent Tip Box for Security Warning */}
|
||||||
|
<div className="mb-6">
|
||||||
|
<TipBox variant="prominent" type="warning">
|
||||||
|
<strong className="text-amber-300">Security Best Practice:</strong> Keep your API keys secure.
|
||||||
|
Never commit them to public repositories or expose them in client-side code. Use environment
|
||||||
|
variables and server-side implementations for production applications.
|
||||||
|
</TipBox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Create your first API key (one-time bootstrap)
|
||||||
|
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Save the returned key securely
|
||||||
|
export BANATIE_API_KEY="bnt_your_key_here"`}
|
||||||
|
language="bash"
|
||||||
|
filename="Get API Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* First Request */}
|
||||||
|
<section id="first-request" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Your First Request</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Let's generate your first image! This example uses curl, but you can use any HTTP client
|
||||||
|
or our SDKs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_API_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a serene mountain landscape at sunset",
|
||||||
|
"filename": "mountain_sunset",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
"autoEnhance": true
|
||||||
|
}'`}
|
||||||
|
language="bash"
|
||||||
|
filename="Generate Image"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt-6">
|
||||||
|
<p className="text-sm font-semibold text-gray-300 mb-3">Expected Response:</p>
|
||||||
|
<div className="relative p-4 bg-green-500/5 border border-green-500/30 rounded-xl shadow-lg shadow-green-500/10">
|
||||||
|
<div className="absolute top-3 right-3">
|
||||||
|
<span className="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded-full">
|
||||||
|
✓ 200 Success
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto mt-6">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"enhancedPrompt": "A breathtaking mountain landscape..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Next Steps - Simplified to 2 Cards */}
|
||||||
|
<section id="next-steps" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Now that you have generated your first image, explore these resources to build more advanced integrations:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<a
|
||||||
|
href="/docs/final/api/text-to-image"
|
||||||
|
className="p-5 bg-gradient-to-br from-purple-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
|
||||||
|
API Reference
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Explore all available endpoints, parameters, and response formats.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/final/guides/authentication"
|
||||||
|
className="p-5 bg-gradient-to-br from-cyan-500/10 to-transparent border border-slate-700/50 rounded-xl hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Authentication Guide
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Learn about API keys, rate limits, and security best practices.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutFinal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,48 +1,22 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { usePathname } from 'next/navigation';
|
|
||||||
import { SubsectionNav } from '@/components/shared/SubsectionNav';
|
|
||||||
import { DocsSidebar } from '@/components/docs/layout/DocsSidebar';
|
|
||||||
import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root Documentation Layout
|
* Root Documentation Layout
|
||||||
*
|
*
|
||||||
* Provides shared layout elements for all documentation pages:
|
* Simple wrapper for all documentation pages.
|
||||||
* - SubsectionNav at the top
|
* Each variant handles its own layout/navigation.
|
||||||
* - Three-column layout (left sidebar + content + right TOC via DocPage)
|
|
||||||
* - Background gradients
|
|
||||||
*
|
|
||||||
* Uses ThreeColumnLayout for consistent column structure:
|
|
||||||
* - Left: DocsSidebar (w-64, hidden lg:block)
|
|
||||||
* - Center: Page content (flex-1)
|
|
||||||
* - Right: Handled by DocPage component
|
|
||||||
*
|
|
||||||
* Pages handle their own:
|
|
||||||
* - Breadcrumbs (manually specified)
|
|
||||||
* - Article content
|
|
||||||
* - TOC sidebar (on the right via DocPage)
|
|
||||||
*
|
*
|
||||||
* Features:
|
* Features:
|
||||||
* - Animated gradient background matching landing page
|
* - Consistent background gradient matching landing page
|
||||||
* - Automatic active page detection via pathname
|
* - No navigation/sidebars at this level
|
||||||
* - Responsive layout (mobile → tablet → desktop)
|
* - Children render their own layouts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface DocsRootLayoutProps {
|
interface DocsRootLayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const navItems = [
|
|
||||||
{ label: 'Documentation', href: '/docs' },
|
|
||||||
{ label: 'Demo', href: '/demo' },
|
|
||||||
{ label: 'Examples', href: '/docs/examples' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
|
export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
|
||||||
const pathname = usePathname();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
||||||
{/* Animated gradient background (matching landing page) */}
|
{/* Animated gradient background (matching landing page) */}
|
||||||
|
|
@ -51,25 +25,8 @@ export default function DocsRootLayout({ children }: DocsRootLayoutProps) {
|
||||||
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
|
<div 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>
|
||||||
|
|
||||||
{/* Subsection Navigation */}
|
{/* Content */}
|
||||||
<SubsectionNav
|
<div className="relative z-10">{children}</div>
|
||||||
items={navItems}
|
|
||||||
currentPath={pathname}
|
|
||||||
ctaText="Join Beta"
|
|
||||||
ctaHref="/signup"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Three-column Documentation Layout */}
|
|
||||||
<div className="relative z-10">
|
|
||||||
<ThreeColumnLayout
|
|
||||||
left={
|
|
||||||
<div className="border-r border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
|
|
||||||
<DocsSidebar currentPath={pathname} />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
center={children}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,196 +1,376 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getting Started Page - Production Documentation
|
* Documentation Variants Comparison Page
|
||||||
*
|
*
|
||||||
* Refactored to use DocPage component for consistent layout
|
* Landing page that introduces users to the three documentation design variants.
|
||||||
* Layout handles SubsectionNav and Left Sidebar
|
* Helps users choose the variant that best suits their preferences.
|
||||||
* DocPage handles Breadcrumb, Article structure, Next Steps, and TOC
|
*
|
||||||
* This page provides only the content (Hero + sections)
|
* Three Variants:
|
||||||
|
* - Variant A: Clean & Minimal (Vercel-inspired)
|
||||||
|
* - Variant B: Dense & Information-Rich (Next.js docs-inspired)
|
||||||
|
* - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design:
|
||||||
|
* - Hero section explaining the concept
|
||||||
|
* - Three large gradient-bordered cards
|
||||||
|
* - Visual preview descriptions
|
||||||
|
* - Clear CTAs to each variant
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { TipBox } from '@/components/docs/shared/TipBox';
|
export default function DocsIndexPage() {
|
||||||
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
|
||||||
import { DocPage } from '@/components/docs/layout/DocPage';
|
|
||||||
import {
|
|
||||||
Hero,
|
|
||||||
SectionHeader,
|
|
||||||
ResponseBlock,
|
|
||||||
} from '@/components/docs/blocks';
|
|
||||||
|
|
||||||
const tocItems = [
|
|
||||||
{ id: 'introduction', text: 'Introduction', level: 2 },
|
|
||||||
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
|
||||||
{ id: 'installation', text: 'Installation', level: 3 },
|
|
||||||
{ id: 'authentication', text: 'Authentication', level: 3 },
|
|
||||||
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
|
||||||
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function GettingStartedPage() {
|
|
||||||
return (
|
return (
|
||||||
<DocPage
|
<div className="min-h-screen">
|
||||||
breadcrumbItems={[
|
{/* Header with back to home */}
|
||||||
{ label: 'Documentation', href: '/docs' },
|
<div className="border-b border-white/10 bg-slate-950/80 backdrop-blur-sm">
|
||||||
{ label: 'Getting Started' },
|
<div className="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
|
||||||
]}
|
<a
|
||||||
tocItems={tocItems}
|
href="/"
|
||||||
nextSteps={{
|
className="flex items-center gap-2 text-gray-400 hover:text-white transition-colors"
|
||||||
description:
|
>
|
||||||
'Now that you have generated your first image, explore these resources to build more advanced integrations:',
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
links: [
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
{
|
</svg>
|
||||||
href: '/docs/api/text-to-image',
|
<span className="text-sm">Back to Home</span>
|
||||||
title: 'API Reference',
|
</a>
|
||||||
description: 'Explore all available endpoints, parameters, and response formats.',
|
<div className="text-sm text-gray-500">Choose Your Documentation Style</div>
|
||||||
accent: 'primary',
|
</div>
|
||||||
},
|
</div>
|
||||||
{
|
|
||||||
href: '/docs/guides/authentication',
|
|
||||||
title: 'Authentication Guide',
|
|
||||||
description: 'Learn about API keys, rate limits, and security best practices.',
|
|
||||||
accent: 'secondary',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
|
<div className="max-w-7xl mx-auto px-6 py-16">
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<Hero
|
<div className="text-center mb-16">
|
||||||
title="Getting Started"
|
<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">
|
||||||
subtitle="Welcome to the Banatie API documentation. Learn how to integrate AI-powered image generation into your applications in minutes."
|
<span className="text-2xl">📚</span>
|
||||||
/>
|
<span className="text-sm font-bold text-white">DOCUMENTATION</span>
|
||||||
|
|
||||||
{/* Introduction */}
|
|
||||||
<section id="introduction" className="mb-12">
|
|
||||||
<SectionHeader level={2} id="introduction">
|
|
||||||
Introduction
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
|
||||||
Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini
|
|
||||||
2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into
|
|
||||||
production-ready visuals.
|
|
||||||
</p>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
|
||||||
Whether you are building a content creation platform, e-commerce site, or creative tool,
|
|
||||||
Banatie provides the infrastructure you need to generate high-quality images at scale.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Compact Tip Box */}
|
|
||||||
<TipBox variant="compact" type="info">
|
|
||||||
<strong>New to API integration?</strong> Start with our{' '}
|
|
||||||
<a href="/docs/examples" className="text-purple-400 hover:underline">
|
|
||||||
code examples
|
|
||||||
</a>{' '}
|
|
||||||
to see common use cases in action.
|
|
||||||
</TipBox>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Quick Start */}
|
|
||||||
<section id="quick-start" className="mb-12">
|
|
||||||
<SectionHeader level={2} id="quick-start" className="mb-6">
|
|
||||||
Quick Start
|
|
||||||
</SectionHeader>
|
|
||||||
|
|
||||||
<div id="installation" className="mb-8">
|
|
||||||
<SectionHeader level={3} id="installation">
|
|
||||||
Installation
|
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
|
||||||
Banatie is a REST API, so you do not need to install any libraries. However, we provide
|
|
||||||
SDKs for popular languages to make integration easier.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<CodeBlock
|
|
||||||
code={`# Using npm (JavaScript/TypeScript)
|
|
||||||
npm install @banatie/sdk
|
|
||||||
|
|
||||||
# Using pip (Python)
|
|
||||||
pip install banatie
|
|
||||||
|
|
||||||
# Using Go
|
|
||||||
go get github.com/banatie/sdk-go`}
|
|
||||||
language="bash"
|
|
||||||
filename="Installation"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<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>
|
||||||
|
|
||||||
<div id="authentication" className="mb-8">
|
{/* Final Variant - Recommended */}
|
||||||
<SectionHeader level={3} id="authentication">
|
<div className="mb-12">
|
||||||
Authentication
|
<div className="text-center mb-6">
|
||||||
</SectionHeader>
|
<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">
|
||||||
<p className="text-gray-300 leading-relaxed mb-4">
|
⭐ RECOMMENDED
|
||||||
All API requests require an API key. You can create an API key from your dashboard or
|
</span>
|
||||||
using the bootstrap endpoint for initial setup.
|
<h2 className="text-2xl font-bold text-white">Production-Ready Design</h2>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href="/docs/final"
|
||||||
|
className="group block p-10 bg-gradient-to-br from-purple-500/20 via-cyan-500/20 to-purple-500/20 border-4 border-purple-500/50 rounded-3xl hover:border-purple-500/80 transition-all duration-300 shadow-2xl hover:shadow-purple-500/40 hover:scale-[1.02]"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col md:flex-row items-center gap-8">
|
||||||
|
<div className="flex-shrink-0 text-6xl">✨</div>
|
||||||
|
<div className="flex-1 text-center md:text-left">
|
||||||
|
<h3 className="text-3xl font-bold text-white mb-3 group-hover:text-purple-300 transition-colors">
|
||||||
|
Final Variant
|
||||||
|
</h3>
|
||||||
|
<h4 className="text-xl font-semibold text-purple-300 mb-4">
|
||||||
|
Best of All Worlds - Clean, Enhanced & Production-Ready
|
||||||
|
</h4>
|
||||||
|
<p className="text-base text-gray-300 mb-6 leading-relaxed max-w-3xl">
|
||||||
|
The perfect combination: Variant A's clean aesthetic enhanced with expandable code blocks, success/error response styling, clickable image URLs, two tip box styles, enhanced tables, and simplified navigation. This is the variant we recommend for production use.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<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"
|
||||||
|
>
|
||||||
|
<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>
|
</p>
|
||||||
|
|
||||||
{/* Prominent Tip Box for Security Warning */}
|
<div className="space-y-3 mb-6">
|
||||||
<div className="mb-6">
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
<TipBox variant="prominent" type="warning">
|
<svg className="w-4 h-4 text-purple-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<strong className="text-amber-300">Security Best Practice:</strong> Keep your API keys secure.
|
<path
|
||||||
Never commit them to public repositories or expose them in client-side code. Use environment
|
fillRule="evenodd"
|
||||||
variables and server-side implementations for production applications.
|
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"
|
||||||
</TipBox>
|
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>
|
||||||
|
|
||||||
<CodeBlock
|
<div className="flex items-center gap-2 text-purple-400 font-semibold group-hover:gap-3 transition-all">
|
||||||
code={`# Create your first API key (one-time bootstrap)
|
<span>Explore Variant A</span>
|
||||||
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
<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>
|
||||||
|
|
||||||
# Save the returned key securely
|
{/* Variant B: Dense & Information-Rich */}
|
||||||
export BANATIE_API_KEY="bnt_your_key_here"`}
|
<a
|
||||||
language="bash"
|
href="/docs/variant-b"
|
||||||
filename="Get API Key"
|
className="group p-8 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl hover:border-cyan-500/60 transition-all duration-300 shadow-xl hover:shadow-cyan-500/30 hover:scale-105"
|
||||||
/>
|
>
|
||||||
|
<div className="text-4xl mb-6">📊</div>
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-4 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Variant B
|
||||||
|
</h2>
|
||||||
|
<h3 className="text-lg font-semibold text-cyan-400 mb-4">Dense & Information-Rich</h3>
|
||||||
|
<p className="text-sm text-gray-400 mb-6 leading-relaxed">
|
||||||
|
Next.js docs-inspired compact layout with section numbers, nested navigation, and
|
||||||
|
maximum information density per screen.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-3 mb-6">
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<svg className="w-4 h-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Compact spacing, more content visible</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<svg className="w-4 h-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Section numbers (1., 2.1, etc.)</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<svg className="w-4 h-4 text-cyan-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Hierarchical nested tree navigation</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2 text-cyan-400 font-semibold group-hover:gap-3 transition-all">
|
||||||
|
<span>Explore Variant B</span>
|
||||||
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* Variant C: Modern & Visual */}
|
||||||
|
<a
|
||||||
|
href="/docs/variant-c"
|
||||||
|
className="group p-8 bg-gradient-to-br from-amber-500/10 via-purple-500/10 to-cyan-500/10 border-2 border-amber-500/30 rounded-2xl hover:border-amber-500/60 transition-all duration-300 shadow-xl hover:shadow-amber-500/30 hover:scale-105"
|
||||||
|
>
|
||||||
|
<div className="text-4xl mb-6">🎨</div>
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-4 group-hover:text-amber-400 transition-colors">
|
||||||
|
Variant C
|
||||||
|
</h2>
|
||||||
|
<h3 className="text-lg font-semibold text-amber-400 mb-4">Modern & Visual</h3>
|
||||||
|
<p className="text-sm text-gray-400 mb-6 leading-relaxed">
|
||||||
|
Shopify-inspired colorful card-based design with large emoji icons, gradient borders,
|
||||||
|
and playful engaging visual style.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-3 mb-6">
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<svg className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Colorful gradient borders everywhere</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<svg className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Large emoji icons and visual elements</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||||
|
<svg className="w-4 h-4 text-amber-400" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>Fun, engaging, playful design</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2 text-amber-400 font-semibold group-hover:gap-3 transition-all">
|
||||||
|
<span>Explore Variant C</span>
|
||||||
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Feature Comparison */}
|
||||||
|
<div className="p-8 bg-slate-900/50 border-2 border-slate-700 rounded-2xl backdrop-blur-sm">
|
||||||
|
<h3 className="text-2xl font-bold text-white mb-6 text-center">
|
||||||
|
All Variants Include
|
||||||
|
</h3>
|
||||||
|
<div className="grid md:grid-cols-3 gap-6">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-3xl mb-3">📚</div>
|
||||||
|
<h4 className="text-base font-semibold text-white mb-2">Same Content</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Identical API documentation, just styled differently
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-3xl mb-3">⚡</div>
|
||||||
|
<h4 className="text-base font-semibold text-white mb-2">Interactive Widgets</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Live API testing with your own keys
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-3xl mb-3">🔍</div>
|
||||||
|
<h4 className="text-base font-semibold text-white mb-2">Navigation & Search</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Sidebar, TOC, and breadcrumb navigation
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
|
|
||||||
{/* First Request */}
|
{/* Footer CTA */}
|
||||||
<section id="first-request" className="mb-12">
|
<div className="mt-16 text-center">
|
||||||
<SectionHeader level={2} id="first-request">
|
<p className="text-gray-400 mb-4">
|
||||||
Your First Request
|
Not sure which to choose? Try all three and see which feels right!
|
||||||
</SectionHeader>
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
|
||||||
Let's generate your first image! This example uses curl, but you can use any HTTP client
|
|
||||||
or our SDKs.
|
|
||||||
</p>
|
</p>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
<CodeBlock
|
Each variant links to the same API content—pick your preferred reading experience.
|
||||||
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
|
</p>
|
||||||
-H "X-API-Key: YOUR_API_KEY" \\
|
</div>
|
||||||
-H "Content-Type: application/json" \\
|
</div>
|
||||||
-d '{
|
</div>
|
||||||
"prompt": "a serene mountain landscape at sunset",
|
|
||||||
"filename": "mountain_sunset",
|
|
||||||
"aspectRatio": "16:9",
|
|
||||||
"autoEnhance": true
|
|
||||||
}'`}
|
|
||||||
language="bash"
|
|
||||||
filename="Generate Image"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="mt-6">
|
|
||||||
<p className="text-sm font-semibold text-gray-300 mb-3">Expected Response:</p>
|
|
||||||
<ResponseBlock
|
|
||||||
status="success"
|
|
||||||
statusCode={200}
|
|
||||||
statusLabel="✓ 200 Success"
|
|
||||||
content={`{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
|
|
||||||
"filepath": "org/project/generated/2025-01/mountain_sunset.png",
|
|
||||||
"width": 1920,
|
|
||||||
"height": 1080,
|
|
||||||
"promptEnhancement": {
|
|
||||||
"enhancedPrompt": "A breathtaking mountain landscape..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</DocPage>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API Reference: Text to Image - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* This page demonstrates the interactive API reference design with live code execution.
|
||||||
|
* Features placeholder content and a fully functional API widget.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA';
|
||||||
|
import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA';
|
||||||
|
import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { InteractiveAPIWidgetA } from '@/components/docs/variant-a/InteractiveAPIWidgetA';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'overview', text: 'Overview', level: 2 },
|
||||||
|
{ id: 'endpoint', text: 'Endpoint', level: 2 },
|
||||||
|
{ id: 'request', text: 'Request', level: 2 },
|
||||||
|
{ id: 'headers', text: 'Headers', level: 3 },
|
||||||
|
{ id: 'body', text: 'Body Parameters', level: 3 },
|
||||||
|
{ id: 'response', text: 'Response', level: 2 },
|
||||||
|
{ id: 'examples', text: 'Examples', level: 2 },
|
||||||
|
{ id: 'errors', text: 'Error Codes', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function TextToImageAPIPageA() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutA
|
||||||
|
sidebar={<DocsSidebarA currentPath="/docs/variant-a/api/text-to-image" />}
|
||||||
|
toc={<DocsTOCA items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/docs' },
|
||||||
|
{ label: 'API Reference', href: '/docs/variant-a/api' },
|
||||||
|
{ label: 'Text to Image' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<div className="inline-block px-3 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-300 text-xs font-medium mb-4">
|
||||||
|
POST
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Text to Image</h1>
|
||||||
|
<p className="text-xl text-gray-400 leading-relaxed">
|
||||||
|
Generate high-quality images from text prompts using AI-powered models.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overview */}
|
||||||
|
<section id="overview" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
The Text to Image endpoint generates images from text descriptions. It supports various
|
||||||
|
aspect ratios, automatic prompt enhancement, and optional reference images for style
|
||||||
|
matching.
|
||||||
|
</p>
|
||||||
|
<div className="p-4 bg-cyan-500/10 border border-cyan-500/20 rounded-xl">
|
||||||
|
<p className="text-sm text-cyan-300">
|
||||||
|
<strong>Tip:</strong> Enable autoEnhance for better results. The AI will optimize your
|
||||||
|
prompt for higher quality outputs while preserving your intent.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Endpoint */}
|
||||||
|
<section id="endpoint" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Endpoint</h2>
|
||||||
|
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<code className="text-purple-400">POST</code>
|
||||||
|
<code className="ml-3 text-gray-300">https://api.banatie.com/api/text-to-image</code>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Request */}
|
||||||
|
<section id="request" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Request</h2>
|
||||||
|
|
||||||
|
<div id="headers" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-4">Headers</h3>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Header</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Value</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Required</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">X-API-Key</td>
|
||||||
|
<td className="py-3 px-4">Your project API key</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">Content-Type</td>
|
||||||
|
<td className="py-3 px-4">application/json</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="body" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-4">Body Parameters</h3>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Parameter</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Type</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Description</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Required</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">prompt</td>
|
||||||
|
<td className="py-3 px-4">string</td>
|
||||||
|
<td className="py-3 px-4">Text description of the image to generate</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">filename</td>
|
||||||
|
<td className="py-3 px-4">string</td>
|
||||||
|
<td className="py-3 px-4">Name for the generated image file</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">aspectRatio</td>
|
||||||
|
<td className="py-3 px-4">string</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">autoEnhance</td>
|
||||||
|
<td className="py-3 px-4">boolean</td>
|
||||||
|
<td className="py-3 px-4">Enable automatic prompt enhancement (default: true)</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-purple-400">enhancementOptions</td>
|
||||||
|
<td className="py-3 px-4">object</td>
|
||||||
|
<td className="py-3 px-4">Template and enhancement settings</td>
|
||||||
|
<td className="py-3 px-4">
|
||||||
|
<span className="px-2 py-1 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Interactive API Widget */}
|
||||||
|
<InteractiveAPIWidgetA
|
||||||
|
endpoint="/api/text-to-image"
|
||||||
|
method="POST"
|
||||||
|
description="Try generating an image with your own API key"
|
||||||
|
parameters={[
|
||||||
|
{
|
||||||
|
name: 'prompt',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Image description',
|
||||||
|
defaultValue: 'a futuristic city at sunset',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'filename',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Output filename',
|
||||||
|
defaultValue: 'city',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'aspectRatio',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: 'Aspect ratio',
|
||||||
|
defaultValue: '16:9',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Response */}
|
||||||
|
<section id="response" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Response</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Returns a JSON object with the generated image URL and metadata.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/city.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"originalPrompt": "a futuristic city at sunset",
|
||||||
|
"enhancedPrompt": "A breathtaking futuristic cityscape...",
|
||||||
|
"template": "photorealistic"
|
||||||
|
},
|
||||||
|
"generatedAt": "2025-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Examples */}
|
||||||
|
<section id="examples" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Examples</h2>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<h4 className="text-lg font-semibold text-white mb-3">Basic Image Generation</h4>
|
||||||
|
<p className="text-sm text-gray-400 mb-3">Generate a simple image with default settings</p>
|
||||||
|
<div className="p-4 bg-slate-950/50 border border-slate-700 rounded-xl">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"prompt": "a serene mountain landscape",
|
||||||
|
"filename": "mountain"
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 className="text-lg font-semibold text-white mb-3">Custom Aspect Ratio</h4>
|
||||||
|
<p className="text-sm text-gray-400 mb-3">Generate a widescreen image</p>
|
||||||
|
<div className="p-4 bg-slate-950/50 border border-slate-700 rounded-xl">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"prompt": "cinematic space battle scene",
|
||||||
|
"filename": "space_battle",
|
||||||
|
"aspectRatio": "21:9"
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Error Codes */}
|
||||||
|
<section id="errors" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Error Codes</h2>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Code</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-red-400">400</td>
|
||||||
|
<td className="py-3 px-4">Invalid request parameters</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-red-400">401</td>
|
||||||
|
<td className="py-3 px-4">Missing or invalid API key</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-red-400">429</td>
|
||||||
|
<td className="py-3 px-4">Rate limit exceeded</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4 font-mono text-red-400">500</td>
|
||||||
|
<td className="py-3 px-4">Internal server error</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutA>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guide: Authentication - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* This page demonstrates a guide/tutorial style page with step-by-step instructions.
|
||||||
|
* Features placeholder content focused on authentication concepts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA';
|
||||||
|
import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA';
|
||||||
|
import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'overview', text: 'Overview', level: 2 },
|
||||||
|
{ id: 'api-keys', text: 'API Keys', level: 2 },
|
||||||
|
{ id: 'key-types', text: 'Key Types', level: 3 },
|
||||||
|
{ id: 'creating-keys', text: 'Creating Keys', level: 3 },
|
||||||
|
{ id: 'using-keys', text: 'Using API Keys', level: 2 },
|
||||||
|
{ id: 'security', text: 'Security Best Practices', level: 2 },
|
||||||
|
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function AuthenticationGuidePageA() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutA
|
||||||
|
sidebar={<DocsSidebarA currentPath="/docs/variant-a/guides/authentication" />}
|
||||||
|
toc={<DocsTOCA items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/docs' },
|
||||||
|
{ label: 'Guides', href: '/docs/variant-a/guides' },
|
||||||
|
{ label: 'Authentication' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<div className="inline-block px-3 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-300 text-xs font-medium mb-4">
|
||||||
|
GUIDE
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Authentication</h1>
|
||||||
|
<p className="text-xl text-gray-400 leading-relaxed">
|
||||||
|
Learn how to authenticate your requests and manage API keys securely.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overview */}
|
||||||
|
<section id="overview" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Overview</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie uses API keys to authenticate requests. Each request must include a valid API key
|
||||||
|
in the X-API-Key header. API keys are tied to your organization and project, providing
|
||||||
|
secure, isolated access to resources.
|
||||||
|
</p>
|
||||||
|
<div className="p-4 bg-purple-500/10 border border-purple-500/20 rounded-xl">
|
||||||
|
<p className="text-sm text-purple-300">
|
||||||
|
<strong>Security First:</strong> Never expose your API keys in client-side code, public
|
||||||
|
repositories, or logs. Treat them like passwords.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* API Keys */}
|
||||||
|
<section id="api-keys" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">API Keys</h2>
|
||||||
|
|
||||||
|
<div id="key-types" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-4">Key Types</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Banatie provides two types of API keys, each with different permissions and use cases:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="p-6 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="flex-shrink-0 w-10 h-10 rounded-lg bg-purple-500/20 flex items-center justify-center text-xl">
|
||||||
|
🔑
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="text-lg font-semibold text-white mb-2">Master Keys</h4>
|
||||||
|
<p className="text-sm text-gray-400 mb-3">
|
||||||
|
Full administrative access to your organization. Can create and revoke other
|
||||||
|
keys, access all projects, and manage settings.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-gray-400 space-y-1">
|
||||||
|
<li>• Never expire</li>
|
||||||
|
<li>• Full API access</li>
|
||||||
|
<li>• One per organization (initially)</li>
|
||||||
|
<li>• Should be kept extremely secure</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="flex-shrink-0 w-10 h-10 rounded-lg bg-cyan-500/20 flex items-center justify-center text-xl">
|
||||||
|
🎫
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="text-lg font-semibold text-white mb-2">Project Keys</h4>
|
||||||
|
<p className="text-sm text-gray-400 mb-3">
|
||||||
|
Scoped to a specific project. Used for image generation and resource access
|
||||||
|
within that project only.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-gray-400 space-y-1">
|
||||||
|
<li>• Expire after 90 days</li>
|
||||||
|
<li>• Project-specific access</li>
|
||||||
|
<li>• Rate limited</li>
|
||||||
|
<li>• Safe for production use</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="creating-keys" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-4">Creating Keys</h3>
|
||||||
|
|
||||||
|
<div className="mb-6">
|
||||||
|
<h4 className="text-base font-semibold text-white mb-3">Bootstrap Your First Key</h4>
|
||||||
|
<p className="text-gray-300 text-sm leading-relaxed mb-3">
|
||||||
|
When setting up Banatie for the first time, create your initial master key using the
|
||||||
|
bootstrap endpoint:
|
||||||
|
</p>
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Response
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"key": "bnt_master_abc123...",
|
||||||
|
"message": "Master key created successfully"
|
||||||
|
}`}
|
||||||
|
language="bash"
|
||||||
|
filename="Create Master Key"
|
||||||
|
/>
|
||||||
|
<div className="mt-3 p-3 bg-amber-500/10 border border-amber-500/20 rounded-lg">
|
||||||
|
<p className="text-xs text-amber-300">
|
||||||
|
<strong>Important:</strong> This endpoint can only be used once. Save the returned
|
||||||
|
key immediately - it will never be shown again.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-6">
|
||||||
|
<h4 className="text-base font-semibold text-white mb-3">Create Project Keys</h4>
|
||||||
|
<p className="text-gray-300 text-sm leading-relaxed mb-3">
|
||||||
|
Use your master key to create project-specific keys:
|
||||||
|
</p>
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/admin/keys \\
|
||||||
|
-H "X-API-Key: YOUR_MASTER_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"type": "project",
|
||||||
|
"projectId": "my-project",
|
||||||
|
"name": "Production Key"
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Response
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"key": "bnt_project_xyz789...",
|
||||||
|
"keyId": "key_abc123",
|
||||||
|
"expiresAt": "2025-04-15T10:30:00Z"
|
||||||
|
}`}
|
||||||
|
language="bash"
|
||||||
|
filename="Create Project Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Using Keys */}
|
||||||
|
<section id="using-keys" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Using API Keys</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Include your API key in every request using the X-API-Key header:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using curl
|
||||||
|
curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_PROJECT_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{"prompt": "sunset", "filename": "test"}'
|
||||||
|
|
||||||
|
# Using JavaScript fetch
|
||||||
|
const response = await fetch('https://api.banatie.com/api/text-to-image', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': 'YOUR_PROJECT_KEY',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: 'sunset',
|
||||||
|
filename: 'test'
|
||||||
|
})
|
||||||
|
});`}
|
||||||
|
language="bash"
|
||||||
|
filename="API Request Example"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Security */}
|
||||||
|
<section id="security" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Security Best Practices</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<div className="flex-shrink-0 text-2xl">🔒</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-1">Never Commit Keys</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Use environment variables or secret management tools. Never commit keys to version
|
||||||
|
control.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<div className="flex-shrink-0 text-2xl">🔄</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-1">Rotate Keys Regularly</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Project keys expire after 90 days. Plan for rotation and implement graceful
|
||||||
|
handling.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<div className="flex-shrink-0 text-2xl">🚫</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-1">Server-Side Only</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Never use API keys in client-side code. Always make requests from your backend.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-4 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<div className="flex-shrink-0 text-2xl">👁️</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-1">Monitor Usage</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Track API key usage patterns. Unusual activity may indicate a compromised key.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Rate Limits */}
|
||||||
|
<section id="rate-limits" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Rate Limits</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
To ensure fair usage and system stability, all API keys are subject to rate limits:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Key Type</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Limit</th>
|
||||||
|
<th className="text-left py-3 px-4 text-gray-400 font-medium">Window</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4">Master Key</td>
|
||||||
|
<td className="py-3 px-4 font-mono">500 requests</td>
|
||||||
|
<td className="py-3 px-4">per hour</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-3 px-4">Project Key</td>
|
||||||
|
<td className="py-3 px-4 font-mono">100 requests</td>
|
||||||
|
<td className="py-3 px-4">per hour</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 p-4 bg-cyan-500/10 border border-cyan-500/20 rounded-xl">
|
||||||
|
<p className="text-sm text-cyan-300">
|
||||||
|
<strong>Need Higher Limits?</strong> Contact our sales team to discuss enterprise plans
|
||||||
|
with custom rate limits.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutA>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,208 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting Started Page - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* This is the main landing page for the documentation.
|
||||||
|
* Features placeholder content to demonstrate the layout and design.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutA } from '@/components/docs/variant-a/DocsLayoutA';
|
||||||
|
import { DocsSidebarA } from '@/components/docs/variant-a/DocsSidebarA';
|
||||||
|
import { DocsTOCA } from '@/components/docs/variant-a/DocsTOCA';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||||
|
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||||
|
{ id: 'installation', text: 'Installation', level: 3 },
|
||||||
|
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||||
|
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||||
|
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function GettingStartedPageA() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutA
|
||||||
|
sidebar={<DocsSidebarA currentPath="/docs/variant-a" />}
|
||||||
|
toc={<DocsTOCA items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">Getting Started</h1>
|
||||||
|
<p className="text-xl text-gray-400 leading-relaxed">
|
||||||
|
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
|
||||||
|
generation into your applications in minutes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Introduction */}
|
||||||
|
<section id="introduction" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Introduction</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini
|
||||||
|
2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into
|
||||||
|
production-ready visuals.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-300 leading-relaxed">
|
||||||
|
Whether you're building a content creation platform, e-commerce site, or creative tool,
|
||||||
|
Banatie provides the infrastructure you need to generate high-quality images at scale.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Quick Start */}
|
||||||
|
<section id="quick-start" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Quick Start</h2>
|
||||||
|
|
||||||
|
<div id="installation" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-3">Installation</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie is a REST API, so you don't need to install any libraries. However, we provide
|
||||||
|
SDKs for popular languages to make integration easier.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using npm (JavaScript/TypeScript)
|
||||||
|
npm install @banatie/sdk
|
||||||
|
|
||||||
|
# Using pip (Python)
|
||||||
|
pip install banatie
|
||||||
|
|
||||||
|
# Using Go
|
||||||
|
go get github.com/banatie/sdk-go`}
|
||||||
|
language="bash"
|
||||||
|
filename="Installation"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="authentication" className="mb-8">
|
||||||
|
<h3 className="text-xl font-semibold text-white mb-3">Authentication</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
All API requests require an API key. You can create an API key from your dashboard or
|
||||||
|
using the bootstrap endpoint for initial setup.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="p-4 bg-purple-500/10 border border-purple-500/20 rounded-xl mb-4">
|
||||||
|
<p className="text-sm text-purple-300">
|
||||||
|
<strong>Note:</strong> Keep your API keys secure. Never commit them to public
|
||||||
|
repositories or expose them in client-side code.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Create your first API key (one-time bootstrap)
|
||||||
|
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Save the returned key securely
|
||||||
|
export BANATIE_API_KEY="bnt_your_key_here"`}
|
||||||
|
language="bash"
|
||||||
|
filename="Get API Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* First Request */}
|
||||||
|
<section id="first-request" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Your First Request</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Let's generate your first image! This example uses curl, but you can use any HTTP client
|
||||||
|
or our SDKs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_API_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a serene mountain landscape at sunset",
|
||||||
|
"filename": "mountain_sunset",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
"autoEnhance": true
|
||||||
|
}'`}
|
||||||
|
language="bash"
|
||||||
|
filename="Generate Image"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt-6 p-4 bg-slate-800/50 border border-slate-700 rounded-xl">
|
||||||
|
<p className="text-sm font-semibold text-gray-300 mb-2">Response:</p>
|
||||||
|
<pre className="text-xs text-gray-400 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"enhancedPrompt": "A breathtaking mountain landscape..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Next Steps */}
|
||||||
|
<section id="next-steps" className="mb-12">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-6">Next Steps</h2>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<a
|
||||||
|
href="/docs/variant-a/api/text-to-image"
|
||||||
|
className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-xl hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-2xl mb-3">📚</div>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
|
||||||
|
API Reference
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Explore all available endpoints, parameters, and response formats.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-a/guides/authentication"
|
||||||
|
className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-xl hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-2xl mb-3">🔐</div>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Authentication Guide
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Learn about API keys, rate limits, and security best practices.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-a/examples"
|
||||||
|
className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-xl hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-2xl mb-3">💡</div>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-purple-400 transition-colors">
|
||||||
|
Examples
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Browse code examples and use cases for common scenarios.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-a/guides/error-handling"
|
||||||
|
className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-xl hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-2xl mb-3">⚠️</div>
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Error Handling
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Understand error codes and how to handle failures gracefully.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutA>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,304 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API Reference: Text to Image - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Design Philosophy: Compact, information-dense layout with section numbers
|
||||||
|
*
|
||||||
|
* Key Differences from Variant A:
|
||||||
|
* - Section numbers in all headings (1., 1.1, 1.2, etc.)
|
||||||
|
* - More compact spacing (mb-6 vs mb-12, p-3 vs p-4)
|
||||||
|
* - Smaller text sizes throughout
|
||||||
|
* - Denser tables and narrower content
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB';
|
||||||
|
import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB';
|
||||||
|
import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { InteractiveAPIWidgetB } from '@/components/docs/variant-b/InteractiveAPIWidgetB';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'overview', text: '1. Overview', level: 2 },
|
||||||
|
{ id: 'endpoint', text: '2. Endpoint', level: 2 },
|
||||||
|
{ id: 'request', text: '3. Request', level: 2 },
|
||||||
|
{ id: 'headers', text: '3.1 Headers', level: 3 },
|
||||||
|
{ id: 'body', text: '3.2 Body Parameters', level: 3 },
|
||||||
|
{ id: 'response', text: '4. Response', level: 2 },
|
||||||
|
{ id: 'examples', text: '5. Examples', level: 2 },
|
||||||
|
{ id: 'errors', text: '6. Error Codes', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function TextToImageAPIPageB() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutB
|
||||||
|
sidebar={<DocsSidebarB currentPath="/docs/variant-b/api/text-to-image" />}
|
||||||
|
toc={<DocsTOCB items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/docs' },
|
||||||
|
{ label: 'API Reference', href: '/docs/variant-b/api' },
|
||||||
|
{ label: 'Text to Image' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hero Section - More compact */}
|
||||||
|
<div className="mb-10">
|
||||||
|
<div className="inline-block px-2.5 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-300 text-xs font-medium mb-3">
|
||||||
|
POST
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-3">Text to Image</h1>
|
||||||
|
<p className="text-lg text-gray-400 leading-relaxed">
|
||||||
|
Generate high-quality images from text prompts using AI-powered models.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overview */}
|
||||||
|
<section id="overview" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">1. Overview</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
|
||||||
|
The Text to Image endpoint generates images from text descriptions. It supports various
|
||||||
|
aspect ratios, automatic prompt enhancement, and optional reference images for style
|
||||||
|
matching.
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-cyan-500/10 border border-cyan-500/20 rounded-lg">
|
||||||
|
<p className="text-xs text-cyan-300">
|
||||||
|
<strong>Tip:</strong> Enable autoEnhance for better results. The AI will optimize your
|
||||||
|
prompt for higher quality outputs while preserving your intent.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Endpoint */}
|
||||||
|
<section id="endpoint" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">2. Endpoint</h2>
|
||||||
|
<div className="p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<code className="text-purple-400 text-sm">POST</code>
|
||||||
|
<code className="ml-3 text-gray-300 text-sm">https://api.banatie.com/api/text-to-image</code>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Request */}
|
||||||
|
<section id="request" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-5">3. Request</h2>
|
||||||
|
|
||||||
|
<div id="headers" className="mb-6">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">3.1 Headers</h3>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-xs">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Header</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Value</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Required</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">X-API-Key</td>
|
||||||
|
<td className="py-2 px-3">Your project API key</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">Content-Type</td>
|
||||||
|
<td className="py-2 px-3">application/json</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="body" className="mb-6">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">3.2 Body Parameters</h3>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-xs">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Parameter</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Type</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Description</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Required</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">prompt</td>
|
||||||
|
<td className="py-2 px-3">string</td>
|
||||||
|
<td className="py-2 px-3">Text description of the image to generate</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">filename</td>
|
||||||
|
<td className="py-2 px-3">string</td>
|
||||||
|
<td className="py-2 px-3">Name for the generated image file</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-red-500/20 text-red-400 rounded text-xs">Yes</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">aspectRatio</td>
|
||||||
|
<td className="py-2 px-3">string</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
|
||||||
|
</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">autoEnhance</td>
|
||||||
|
<td className="py-2 px-3">boolean</td>
|
||||||
|
<td className="py-2 px-3">Enable automatic prompt enhancement (default: true)</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-purple-400">enhancementOptions</td>
|
||||||
|
<td className="py-2 px-3">object</td>
|
||||||
|
<td className="py-2 px-3">Template and enhancement settings</td>
|
||||||
|
<td className="py-2 px-3">
|
||||||
|
<span className="px-1.5 py-0.5 bg-gray-500/20 text-gray-400 rounded text-xs">No</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Interactive API Widget */}
|
||||||
|
<InteractiveAPIWidgetB
|
||||||
|
endpoint="/api/text-to-image"
|
||||||
|
method="POST"
|
||||||
|
description="Try generating an image with your own API key"
|
||||||
|
parameters={[
|
||||||
|
{
|
||||||
|
name: 'prompt',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Image description',
|
||||||
|
defaultValue: 'a futuristic city at sunset',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'filename',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Output filename',
|
||||||
|
defaultValue: 'city',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'aspectRatio',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: 'Aspect ratio',
|
||||||
|
defaultValue: '16:9',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Response */}
|
||||||
|
<section id="response" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">4. Response</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
|
||||||
|
Returns a JSON object with the generated image URL and metadata.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/city.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"originalPrompt": "a futuristic city at sunset",
|
||||||
|
"enhancedPrompt": "A breathtaking futuristic cityscape...",
|
||||||
|
"template": "photorealistic"
|
||||||
|
},
|
||||||
|
"generatedAt": "2025-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Examples */}
|
||||||
|
<section id="examples" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-5">5. Examples</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<h4 className="text-base font-semibold text-white mb-2">5.1 Basic Image Generation</h4>
|
||||||
|
<p className="text-xs text-gray-400 mb-2">Generate a simple image with default settings</p>
|
||||||
|
<div className="p-3 bg-slate-950/50 border border-slate-700 rounded-lg">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"prompt": "a serene mountain landscape",
|
||||||
|
"filename": "mountain"
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 className="text-base font-semibold text-white mb-2">5.2 Custom Aspect Ratio</h4>
|
||||||
|
<p className="text-xs text-gray-400 mb-2">Generate a widescreen image</p>
|
||||||
|
<div className="p-3 bg-slate-950/50 border border-slate-700 rounded-lg">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"prompt": "cinematic space battle scene",
|
||||||
|
"filename": "space_battle",
|
||||||
|
"aspectRatio": "21:9"
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Error Codes */}
|
||||||
|
<section id="errors" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">6. Error Codes</h2>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-xs">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Code</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-red-400">400</td>
|
||||||
|
<td className="py-2 px-3">Invalid request parameters</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-red-400">401</td>
|
||||||
|
<td className="py-2 px-3">Missing or invalid API key</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-red-400">429</td>
|
||||||
|
<td className="py-2 px-3">Rate limit exceeded</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3 font-mono text-red-400">500</td>
|
||||||
|
<td className="py-2 px-3">Internal server error</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutB>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,305 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guide: Authentication - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Design Philosophy: Compact, information-dense layout with section numbers
|
||||||
|
*
|
||||||
|
* Key Differences from Variant A:
|
||||||
|
* - Section numbers in all headings (1., 2., 2.1, etc.)
|
||||||
|
* - More compact spacing (mb-6 vs mb-12, p-3 vs p-4)
|
||||||
|
* - Smaller text sizes throughout (text-xs, text-sm)
|
||||||
|
* - Denser layout with narrower content area
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB';
|
||||||
|
import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB';
|
||||||
|
import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'overview', text: '1. Overview', level: 2 },
|
||||||
|
{ id: 'api-keys', text: '2. API Keys', level: 2 },
|
||||||
|
{ id: 'key-types', text: '2.1 Key Types', level: 3 },
|
||||||
|
{ id: 'creating-keys', text: '2.2 Creating Keys', level: 3 },
|
||||||
|
{ id: 'using-keys', text: '3. Using API Keys', level: 2 },
|
||||||
|
{ id: 'security', text: '4. Security Best Practices', level: 2 },
|
||||||
|
{ id: 'rate-limits', text: '5. Rate Limits', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function AuthenticationGuidePageB() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutB
|
||||||
|
sidebar={<DocsSidebarB currentPath="/docs/variant-b/guides/authentication" />}
|
||||||
|
toc={<DocsTOCB items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/docs' },
|
||||||
|
{ label: 'Guides', href: '/docs/variant-b/guides' },
|
||||||
|
{ label: 'Authentication' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hero Section - More compact */}
|
||||||
|
<div className="mb-10">
|
||||||
|
<div className="inline-block px-2.5 py-1 rounded-full bg-cyan-500/10 border border-cyan-500/20 text-cyan-300 text-xs font-medium mb-3">
|
||||||
|
GUIDE
|
||||||
|
</div>
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-3">Authentication</h1>
|
||||||
|
<p className="text-lg text-gray-400 leading-relaxed">
|
||||||
|
Learn how to authenticate your requests and manage API keys securely.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overview */}
|
||||||
|
<section id="overview" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">1. Overview</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
|
||||||
|
Banatie uses API keys to authenticate requests. Each request must include a valid API key
|
||||||
|
in the X-API-Key header. API keys are tied to your organization and project, providing
|
||||||
|
secure, isolated access to resources.
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg">
|
||||||
|
<p className="text-xs text-purple-300">
|
||||||
|
<strong>Security First:</strong> Never expose your API keys in client-side code, public
|
||||||
|
repositories, or logs. Treat them like passwords.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* API Keys */}
|
||||||
|
<section id="api-keys" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-5">2. API Keys</h2>
|
||||||
|
|
||||||
|
<div id="key-types" className="mb-6">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">2.1 Key Types</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
|
||||||
|
Banatie provides two types of API keys, each with different permissions and use cases:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="flex-shrink-0 w-8 h-8 rounded-lg bg-purple-500/20 flex items-center justify-center text-lg">
|
||||||
|
🔑
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="text-base font-semibold text-white mb-1.5">Master Keys</h4>
|
||||||
|
<p className="text-xs text-gray-400 mb-2">
|
||||||
|
Full administrative access to your organization. Can create and revoke other
|
||||||
|
keys, access all projects, and manage settings.
|
||||||
|
</p>
|
||||||
|
<ul className="text-xs text-gray-400 space-y-0.5">
|
||||||
|
<li>• Never expire</li>
|
||||||
|
<li>• Full API access</li>
|
||||||
|
<li>• One per organization (initially)</li>
|
||||||
|
<li>• Should be kept extremely secure</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<div className="flex-shrink-0 w-8 h-8 rounded-lg bg-cyan-500/20 flex items-center justify-center text-lg">
|
||||||
|
🎫
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="text-base font-semibold text-white mb-1.5">Project Keys</h4>
|
||||||
|
<p className="text-xs text-gray-400 mb-2">
|
||||||
|
Scoped to a specific project. Used for image generation and resource access
|
||||||
|
within that project only.
|
||||||
|
</p>
|
||||||
|
<ul className="text-xs text-gray-400 space-y-0.5">
|
||||||
|
<li>• Expire after 90 days</li>
|
||||||
|
<li>• Project-specific access</li>
|
||||||
|
<li>• Rate limited</li>
|
||||||
|
<li>• Safe for production use</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="creating-keys" className="mb-6">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-3">2.2 Creating Keys</h3>
|
||||||
|
|
||||||
|
<div className="mb-5">
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-2">2.2.1 Bootstrap Your First Key</h4>
|
||||||
|
<p className="text-gray-300 text-xs leading-relaxed mb-2">
|
||||||
|
When setting up Banatie for the first time, create your initial master key using the
|
||||||
|
bootstrap endpoint:
|
||||||
|
</p>
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Response
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"key": "bnt_master_abc123...",
|
||||||
|
"message": "Master key created successfully"
|
||||||
|
}`}
|
||||||
|
language="bash"
|
||||||
|
filename="Create Master Key"
|
||||||
|
/>
|
||||||
|
<div className="mt-2 p-2.5 bg-amber-500/10 border border-amber-500/20 rounded-lg">
|
||||||
|
<p className="text-xs text-amber-300">
|
||||||
|
<strong>Important:</strong> This endpoint can only be used once. Save the returned
|
||||||
|
key immediately - it will never be shown again.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-5">
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-2">2.2.2 Create Project Keys</h4>
|
||||||
|
<p className="text-gray-300 text-xs leading-relaxed mb-2">
|
||||||
|
Use your master key to create project-specific keys:
|
||||||
|
</p>
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/admin/keys \\
|
||||||
|
-H "X-API-Key: YOUR_MASTER_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"type": "project",
|
||||||
|
"projectId": "my-project",
|
||||||
|
"name": "Production Key"
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Response
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"key": "bnt_project_xyz789...",
|
||||||
|
"keyId": "key_abc123",
|
||||||
|
"expiresAt": "2025-04-15T10:30:00Z"
|
||||||
|
}`}
|
||||||
|
language="bash"
|
||||||
|
filename="Create Project Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Using Keys */}
|
||||||
|
<section id="using-keys" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">3. Using API Keys</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
|
||||||
|
Include your API key in every request using the X-API-Key header:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using curl
|
||||||
|
curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_PROJECT_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{"prompt": "sunset", "filename": "test"}'
|
||||||
|
|
||||||
|
# Using JavaScript fetch
|
||||||
|
const response = await fetch('https://api.banatie.com/api/text-to-image', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': 'YOUR_PROJECT_KEY',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: 'sunset',
|
||||||
|
filename: 'test'
|
||||||
|
})
|
||||||
|
});`}
|
||||||
|
language="bash"
|
||||||
|
filename="API Request Example"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Security */}
|
||||||
|
<section id="security" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-5">4. Security Best Practices</h2>
|
||||||
|
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex-shrink-0 text-xl">🔒</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-xs font-semibold text-white mb-0.5">Never Commit Keys</h4>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Use environment variables or secret management tools. Never commit keys to version
|
||||||
|
control.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex-shrink-0 text-xl">🔄</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-xs font-semibold text-white mb-0.5">Rotate Keys Regularly</h4>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Project keys expire after 90 days. Plan for rotation and implement graceful
|
||||||
|
handling.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex-shrink-0 text-xl">🚫</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-xs font-semibold text-white mb-0.5">Server-Side Only</h4>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Never use API keys in client-side code. Always make requests from your backend.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-3 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex-shrink-0 text-xl">👁️</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-xs font-semibold text-white mb-0.5">Monitor Usage</h4>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Track API key usage patterns. Unusual activity may indicate a compromised key.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Rate Limits */}
|
||||||
|
<section id="rate-limits" className="mb-8">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">5. Rate Limits</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
|
||||||
|
To ensure fair usage and system stability, all API keys are subject to rate limits:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-xs">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-slate-700">
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Key Type</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Limit</th>
|
||||||
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Window</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3">Master Key</td>
|
||||||
|
<td className="py-2 px-3 font-mono">500 requests</td>
|
||||||
|
<td className="py-2 px-3">per hour</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-2 px-3">Project Key</td>
|
||||||
|
<td className="py-2 px-3 font-mono">100 requests</td>
|
||||||
|
<td className="py-2 px-3">per hour</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4 p-3 bg-cyan-500/10 border border-cyan-500/20 rounded-lg">
|
||||||
|
<p className="text-xs text-cyan-300">
|
||||||
|
<strong>Need Higher Limits?</strong> Contact our sales team to discuss enterprise plans
|
||||||
|
with custom rate limits.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutB>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,211 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting Started Page - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Same content as Variant A but with Variant B styling:
|
||||||
|
* - Compact spacing (py-10 vs py-12, p-4 vs p-6)
|
||||||
|
* - Narrower max-width (max-w-4xl)
|
||||||
|
* - Section numbers in headings where appropriate
|
||||||
|
* - Denser tables and lists
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutB } from '@/components/docs/variant-b/DocsLayoutB';
|
||||||
|
import { DocsSidebarB } from '@/components/docs/variant-b/DocsSidebarB';
|
||||||
|
import { DocsTOCB } from '@/components/docs/variant-b/DocsTOCB';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'introduction', text: '1. Introduction', level: 2 },
|
||||||
|
{ id: 'quick-start', text: '2. Quick Start', level: 2 },
|
||||||
|
{ id: 'installation', text: '2.1 Installation', level: 3 },
|
||||||
|
{ id: 'authentication', text: '2.2 Authentication', level: 3 },
|
||||||
|
{ id: 'first-request', text: '3. Your First Request', level: 2 },
|
||||||
|
{ id: 'next-steps', text: '4. Next Steps', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function GettingStartedPageB() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutB
|
||||||
|
sidebar={<DocsSidebarB currentPath="/docs/variant-b" />}
|
||||||
|
toc={<DocsTOCB items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
|
||||||
|
|
||||||
|
{/* Hero Section - More compact */}
|
||||||
|
<div className="mb-10">
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-white mb-3">Getting Started</h1>
|
||||||
|
<p className="text-lg text-gray-400 leading-relaxed">
|
||||||
|
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
|
||||||
|
generation into your applications in minutes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Introduction */}
|
||||||
|
<section id="introduction" className="mb-10">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">1. Introduction</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-3">
|
||||||
|
Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini
|
||||||
|
2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into
|
||||||
|
production-ready visuals.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-300 leading-relaxed">
|
||||||
|
Whether you're building a content creation platform, e-commerce site, or creative tool,
|
||||||
|
Banatie provides the infrastructure you need to generate high-quality images at scale.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Quick Start */}
|
||||||
|
<section id="quick-start" className="mb-10">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-5">2. Quick Start</h2>
|
||||||
|
|
||||||
|
<div id="installation" className="mb-6">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2">2.1 Installation</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
|
||||||
|
Banatie is a REST API, so you don't need to install any libraries. However, we provide
|
||||||
|
SDKs for popular languages to make integration easier.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using npm (JavaScript/TypeScript)
|
||||||
|
npm install @banatie/sdk
|
||||||
|
|
||||||
|
# Using pip (Python)
|
||||||
|
pip install banatie
|
||||||
|
|
||||||
|
# Using Go
|
||||||
|
go get github.com/banatie/sdk-go`}
|
||||||
|
language="bash"
|
||||||
|
filename="Installation"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="authentication" className="mb-6">
|
||||||
|
<h3 className="text-lg font-semibold text-white mb-2">2.2 Authentication</h3>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-3 text-sm">
|
||||||
|
All API requests require an API key. You can create an API key from your dashboard or
|
||||||
|
using the bootstrap endpoint for initial setup.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="p-3 bg-purple-500/10 border border-purple-500/20 rounded-lg mb-3">
|
||||||
|
<p className="text-xs text-purple-300">
|
||||||
|
<strong>Note:</strong> Keep your API keys secure. Never commit them to public
|
||||||
|
repositories or expose them in client-side code.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Create your first API key (one-time bootstrap)
|
||||||
|
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Save the returned key securely
|
||||||
|
export BANATIE_API_KEY="bnt_your_key_here"`}
|
||||||
|
language="bash"
|
||||||
|
filename="Get API Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* First Request */}
|
||||||
|
<section id="first-request" className="mb-10">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-3">3. Your First Request</h2>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4 text-sm">
|
||||||
|
Let's generate your first image! This example uses curl, but you can use any HTTP client
|
||||||
|
or our SDKs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_API_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a serene mountain landscape at sunset",
|
||||||
|
"filename": "mountain_sunset",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
"autoEnhance": true
|
||||||
|
}'`}
|
||||||
|
language="bash"
|
||||||
|
filename="Generate Image"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt-4 p-3 bg-slate-800/50 border border-slate-700 rounded-lg">
|
||||||
|
<p className="text-xs font-semibold text-gray-300 mb-2">Response:</p>
|
||||||
|
<pre className="text-xs text-gray-400 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"enhancedPrompt": "A breathtaking mountain landscape..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Next Steps */}
|
||||||
|
<section id="next-steps" className="mb-10">
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-5">4. Next Steps</h2>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-3">
|
||||||
|
<a
|
||||||
|
href="/docs/variant-b/api/text-to-image"
|
||||||
|
className="p-4 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-lg hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-xl mb-2">📚</div>
|
||||||
|
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-purple-400 transition-colors">
|
||||||
|
API Reference
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Explore all available endpoints, parameters, and response formats.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-b/guides/authentication"
|
||||||
|
className="p-4 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-lg hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-xl mb-2">🔐</div>
|
||||||
|
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Authentication Guide
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Learn about API keys, rate limits, and security best practices.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-b/examples"
|
||||||
|
className="p-4 bg-gradient-to-br from-purple-500/10 to-transparent border border-purple-500/20 rounded-lg hover:border-purple-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-xl mb-2">💡</div>
|
||||||
|
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-purple-400 transition-colors">
|
||||||
|
Examples
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Browse code examples and use cases for common scenarios.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-b/guides/error-handling"
|
||||||
|
className="p-4 bg-gradient-to-br from-cyan-500/10 to-transparent border border-cyan-500/20 rounded-lg hover:border-cyan-500/40 transition-colors group"
|
||||||
|
>
|
||||||
|
<div className="text-xl mb-2">⚠️</div>
|
||||||
|
<h3 className="text-base font-semibold text-white mb-1 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Error Handling
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-gray-400">
|
||||||
|
Understand error codes and how to handle failures gracefully.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutB>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,369 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API Reference: Text to Image - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Colorful, card-based, engaging visual design
|
||||||
|
*
|
||||||
|
* Key Characteristics:
|
||||||
|
* - NO section numbers (more visual/playful)
|
||||||
|
* - Large emoji icons (text-3xl)
|
||||||
|
* - Gradient borders everywhere
|
||||||
|
* - Colorful method badge (large, gradient)
|
||||||
|
* - Visual cards for parameter tables
|
||||||
|
* - Generous spacing (mb-12, p-6)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC';
|
||||||
|
import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC';
|
||||||
|
import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { InteractiveAPIWidgetC } from '@/components/docs/variant-c/InteractiveAPIWidgetC';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'overview', text: 'Overview', level: 2 },
|
||||||
|
{ id: 'endpoint', text: 'Endpoint', level: 2 },
|
||||||
|
{ id: 'request', text: 'Request', level: 2 },
|
||||||
|
{ id: 'headers', text: 'Headers', level: 3 },
|
||||||
|
{ id: 'body', text: 'Body Parameters', level: 3 },
|
||||||
|
{ id: 'response', text: 'Response', level: 2 },
|
||||||
|
{ id: 'examples', text: 'Examples', level: 2 },
|
||||||
|
{ id: 'errors', text: 'Error Codes', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function TextToImageAPIPageC() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutC
|
||||||
|
sidebar={<DocsSidebarC currentPath="/docs/variant-c/api/text-to-image" />}
|
||||||
|
toc={<DocsTOCC items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/docs' },
|
||||||
|
{ label: 'API Reference', href: '/docs/variant-c/api' },
|
||||||
|
{ label: 'Text to Image' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hero Section - Large and Colorful */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/30 to-purple-600/30 border-2 border-purple-500/50 shadow-lg shadow-purple-500/30 mb-6">
|
||||||
|
<span className="text-lg font-bold text-white">POST</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 bg-gradient-to-r from-purple-400 to-cyan-400 bg-clip-text text-transparent">
|
||||||
|
Text to Image
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-300 leading-relaxed">
|
||||||
|
Generate high-quality images from text prompts using AI-powered models.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overview */}
|
||||||
|
<section id="overview" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">📖</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Overview</h2>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
The Text to Image endpoint generates images from text descriptions. It supports various
|
||||||
|
aspect ratios, automatic prompt enhancement, and optional reference images for style
|
||||||
|
matching.
|
||||||
|
</p>
|
||||||
|
<div className="p-4 bg-cyan-500/10 border-2 border-cyan-500/30 rounded-xl">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<span className="text-2xl">💡</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-bold text-cyan-300 mb-1">Pro Tip</p>
|
||||||
|
<p className="text-sm text-cyan-200">
|
||||||
|
Enable autoEnhance for better results. The AI will optimize your prompt for higher
|
||||||
|
quality outputs while preserving your intent.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Endpoint */}
|
||||||
|
<section id="endpoint" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">🔗</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Endpoint</h2>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 bg-gradient-to-br from-slate-900/80 to-slate-950/80 border-2 border-purple-500/30 rounded-2xl shadow-xl">
|
||||||
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
|
<span className="px-3 py-1.5 bg-gradient-to-r from-purple-500 to-purple-600 text-white rounded-lg font-bold text-sm shadow-lg">
|
||||||
|
POST
|
||||||
|
</span>
|
||||||
|
<code className="text-purple-400 font-mono">https://api.banatie.com/api/text-to-image</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Request */}
|
||||||
|
<section id="request" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<span className="text-3xl">📤</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Request</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="headers" className="mb-8">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="text-2xl">🏷️</span>
|
||||||
|
<h3 className="text-2xl font-semibold text-white">Headers</h3>
|
||||||
|
</div>
|
||||||
|
<div className="overflow-hidden border-2 border-cyan-500/30 rounded-2xl shadow-lg">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-slate-950/80 border-b-2 border-cyan-500/20">
|
||||||
|
<th className="text-left py-4 px-6 text-cyan-400 font-bold text-sm">Header</th>
|
||||||
|
<th className="text-left py-4 px-6 text-cyan-400 font-bold text-sm">Value</th>
|
||||||
|
<th className="text-left py-4 px-6 text-cyan-400 font-bold text-sm">Required</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300 bg-slate-900/50">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-purple-400 font-semibold">X-API-Key</td>
|
||||||
|
<td className="py-4 px-6">Your project API key</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
|
||||||
|
Required
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-purple-400 font-semibold">Content-Type</td>
|
||||||
|
<td className="py-4 px-6">application/json</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
|
||||||
|
Required
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="body" className="mb-8">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="text-2xl">⚙️</span>
|
||||||
|
<h3 className="text-2xl font-semibold text-white">Body Parameters</h3>
|
||||||
|
</div>
|
||||||
|
<div className="overflow-hidden border-2 border-purple-500/30 rounded-2xl shadow-lg">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-slate-950/80 border-b-2 border-purple-500/20">
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Parameter</th>
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Type</th>
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Description</th>
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold text-sm">Required</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300 bg-slate-900/50">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">prompt</td>
|
||||||
|
<td className="py-4 px-6 text-sm">string</td>
|
||||||
|
<td className="py-4 px-6 text-sm">Text description of the image to generate</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
|
||||||
|
Required
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">filename</td>
|
||||||
|
<td className="py-4 px-6 text-sm">string</td>
|
||||||
|
<td className="py-4 px-6 text-sm">Name for the generated image file</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-red-500/20 text-red-400 rounded-lg text-xs font-bold border-2 border-red-500/40">
|
||||||
|
Required
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">aspectRatio</td>
|
||||||
|
<td className="py-4 px-6 text-sm">string</td>
|
||||||
|
<td className="py-4 px-6 text-sm">
|
||||||
|
Image aspect ratio. Options: 1:1, 3:4, 4:3, 9:16, 16:9, 21:9
|
||||||
|
</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-gray-500/20 text-gray-400 rounded-lg text-xs font-bold border-2 border-gray-500/30">
|
||||||
|
Optional
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">autoEnhance</td>
|
||||||
|
<td className="py-4 px-6 text-sm">boolean</td>
|
||||||
|
<td className="py-4 px-6 text-sm">Enable automatic prompt enhancement (default: true)</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-gray-500/20 text-gray-400 rounded-lg text-xs font-bold border-2 border-gray-500/30">
|
||||||
|
Optional
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-cyan-400 font-semibold">enhancementOptions</td>
|
||||||
|
<td className="py-4 px-6 text-sm">object</td>
|
||||||
|
<td className="py-4 px-6 text-sm">Template and enhancement settings</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-gray-500/20 text-gray-400 rounded-lg text-xs font-bold border-2 border-gray-500/30">
|
||||||
|
Optional
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Interactive API Widget */}
|
||||||
|
<InteractiveAPIWidgetC
|
||||||
|
endpoint="/api/text-to-image"
|
||||||
|
method="POST"
|
||||||
|
description="Try generating an image with your own API key"
|
||||||
|
parameters={[
|
||||||
|
{
|
||||||
|
name: 'prompt',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Image description',
|
||||||
|
defaultValue: 'a futuristic city at sunset',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'filename',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Output filename',
|
||||||
|
defaultValue: 'city',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'aspectRatio',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: 'Aspect ratio',
|
||||||
|
defaultValue: '16:9',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Response */}
|
||||||
|
<section id="response" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">📦</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Response</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Returns a JSON object with the generated image URL and metadata.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-slate-900/80 to-slate-950/80 border-2 border-green-500/30 rounded-2xl shadow-xl shadow-green-500/20">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="px-3 py-1.5 bg-green-500/20 text-green-400 rounded-lg text-xs font-bold border-2 border-green-500/40">
|
||||||
|
✓ 200 Success
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<pre className="text-sm text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/city.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/city.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"originalPrompt": "a futuristic city at sunset",
|
||||||
|
"enhancedPrompt": "A breathtaking futuristic cityscape...",
|
||||||
|
"template": "photorealistic"
|
||||||
|
},
|
||||||
|
"generatedAt": "2025-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Examples */}
|
||||||
|
<section id="examples" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<span className="text-3xl">💡</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Examples</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-lg">
|
||||||
|
<div className="flex items-center gap-2 mb-3">
|
||||||
|
<span className="text-xl">🎨</span>
|
||||||
|
<h4 className="text-xl font-bold text-white">Basic Image Generation</h4>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-gray-400 mb-4">Generate a simple image with default settings</p>
|
||||||
|
<div className="p-4 bg-slate-950/50 border-2 border-purple-500/20 rounded-xl">
|
||||||
|
<pre className="text-sm text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"prompt": "a serene mountain landscape",
|
||||||
|
"filename": "mountain"
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-lg">
|
||||||
|
<div className="flex items-center gap-2 mb-3">
|
||||||
|
<span className="text-xl">🎬</span>
|
||||||
|
<h4 className="text-xl font-bold text-white">Custom Aspect Ratio</h4>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-gray-400 mb-4">Generate a widescreen image</p>
|
||||||
|
<div className="p-4 bg-slate-950/50 border-2 border-cyan-500/20 rounded-xl">
|
||||||
|
<pre className="text-sm text-gray-300 overflow-x-auto">
|
||||||
|
<code>{`{
|
||||||
|
"prompt": "cinematic space battle scene",
|
||||||
|
"filename": "space_battle",
|
||||||
|
"aspectRatio": "21:9"
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Error Codes */}
|
||||||
|
<section id="errors" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">⚠️</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Error Codes</h2>
|
||||||
|
</div>
|
||||||
|
<div className="overflow-hidden border-2 border-red-500/30 rounded-2xl shadow-xl shadow-red-500/20">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-slate-950/80 border-b-2 border-red-500/20">
|
||||||
|
<th className="text-left py-4 px-6 text-red-400 font-bold text-sm">Code</th>
|
||||||
|
<th className="text-left py-4 px-6 text-red-400 font-bold text-sm">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300 bg-slate-900/50">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">400</td>
|
||||||
|
<td className="py-4 px-6">Invalid request parameters</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">401</td>
|
||||||
|
<td className="py-4 px-6">Missing or invalid API key</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">429</td>
|
||||||
|
<td className="py-4 px-6">Rate limit exceeded</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-mono text-red-400 font-bold text-lg">500</td>
|
||||||
|
<td className="py-4 px-6">Internal server error</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutC>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,370 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guide: Authentication - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Colorful, card-based, playful visual design
|
||||||
|
*
|
||||||
|
* Key Characteristics:
|
||||||
|
* - NO section numbers (more visual/playful)
|
||||||
|
* - Security best practices as large visual cards
|
||||||
|
* - Emoji icons prominent (text-3xl)
|
||||||
|
* - Gradient borders everywhere
|
||||||
|
* - Generous spacing and padding
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC';
|
||||||
|
import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC';
|
||||||
|
import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'overview', text: 'Overview', level: 2 },
|
||||||
|
{ id: 'api-keys', text: 'API Keys', level: 2 },
|
||||||
|
{ id: 'key-types', text: 'Key Types', level: 3 },
|
||||||
|
{ id: 'creating-keys', text: 'Creating Keys', level: 3 },
|
||||||
|
{ id: 'using-keys', text: 'Using API Keys', level: 2 },
|
||||||
|
{ id: 'security', text: 'Security Best Practices', level: 2 },
|
||||||
|
{ id: 'rate-limits', text: 'Rate Limits', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function AuthenticationGuidePageC() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutC
|
||||||
|
sidebar={<DocsSidebarC currentPath="/docs/variant-c/guides/authentication" />}
|
||||||
|
toc={<DocsTOCC items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb
|
||||||
|
items={[
|
||||||
|
{ label: 'Documentation', href: '/docs' },
|
||||||
|
{ label: 'Guides', href: '/docs/variant-c/guides' },
|
||||||
|
{ label: 'Authentication' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Hero Section - Large and Colorful */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-cyan-500/20 to-cyan-600/20 border-2 border-cyan-500/50 shadow-lg shadow-cyan-500/30 mb-6">
|
||||||
|
<span className="text-2xl">📚</span>
|
||||||
|
<span className="text-sm font-bold text-white">GUIDE</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 bg-gradient-to-r from-cyan-400 to-purple-400 bg-clip-text text-transparent">
|
||||||
|
Authentication
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-300 leading-relaxed">
|
||||||
|
Learn how to authenticate your requests and manage API keys securely.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Overview */}
|
||||||
|
<section id="overview" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">🔐</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Overview</h2>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie uses API keys to authenticate requests. Each request must include a valid API key
|
||||||
|
in the X-API-Key header. API keys are tied to your organization and project, providing
|
||||||
|
secure, isolated access to resources.
|
||||||
|
</p>
|
||||||
|
<div className="p-4 bg-red-500/10 border-2 border-red-500/30 rounded-xl">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<span className="text-2xl">🛡️</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-bold text-red-300 mb-1">Security First</p>
|
||||||
|
<p className="text-sm text-red-200">
|
||||||
|
Never expose your API keys in client-side code, public repositories, or logs. Treat
|
||||||
|
them like passwords.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* API Keys */}
|
||||||
|
<section id="api-keys" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<span className="text-3xl">🔑</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">API Keys</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="key-types" className="mb-8">
|
||||||
|
<div className="flex items-center gap-2 mb-6">
|
||||||
|
<span className="text-2xl">🏷️</span>
|
||||||
|
<h3 className="text-2xl font-semibold text-white">Key Types</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Banatie provides two types of API keys, each with different permissions and use cases:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20 hover:scale-105 transition-transform duration-300">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="flex-shrink-0 w-16 h-16 rounded-2xl bg-gradient-to-br from-purple-500/30 to-purple-600/30 border-2 border-purple-500/50 flex items-center justify-center text-3xl shadow-lg">
|
||||||
|
🔑
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="text-2xl font-bold text-white mb-3">Master Keys</h4>
|
||||||
|
<p className="text-sm text-gray-400 mb-4">
|
||||||
|
Full administrative access to your organization. Can create and revoke other
|
||||||
|
keys, access all projects, and manage settings.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-gray-400 space-y-2">
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-purple-400">✓</span> Never expire
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-purple-400">✓</span> Full API access
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-purple-400">✓</span> One per organization (initially)
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-purple-400">✓</span> Should be kept extremely secure
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-xl shadow-cyan-500/20 hover:scale-105 transition-transform duration-300">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="flex-shrink-0 w-16 h-16 rounded-2xl bg-gradient-to-br from-cyan-500/30 to-cyan-600/30 border-2 border-cyan-500/50 flex items-center justify-center text-3xl shadow-lg">
|
||||||
|
🎫
|
||||||
|
</div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="text-2xl font-bold text-white mb-3">Project Keys</h4>
|
||||||
|
<p className="text-sm text-gray-400 mb-4">
|
||||||
|
Scoped to a specific project. Used for image generation and resource access
|
||||||
|
within that project only.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-gray-400 space-y-2">
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-cyan-400">✓</span> Expire after 90 days
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-cyan-400">✓</span> Project-specific access
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-cyan-400">✓</span> Rate limited
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<span className="text-cyan-400">✓</span> Safe for production use
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="creating-keys" className="mb-8">
|
||||||
|
<div className="flex items-center gap-2 mb-6">
|
||||||
|
<span className="text-2xl">⚡</span>
|
||||||
|
<h3 className="text-2xl font-semibold text-white">Creating Keys</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-8 p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 rounded-2xl shadow-xl shadow-amber-500/20">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="text-2xl">🚀</span>
|
||||||
|
<h4 className="text-xl font-bold text-white">Bootstrap Your First Key</h4>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 text-sm leading-relaxed mb-4">
|
||||||
|
When setting up Banatie for the first time, create your initial master key using the
|
||||||
|
bootstrap endpoint:
|
||||||
|
</p>
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Response
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"key": "bnt_master_abc123...",
|
||||||
|
"message": "Master key created successfully"
|
||||||
|
}`}
|
||||||
|
language="bash"
|
||||||
|
filename="Create Master Key"
|
||||||
|
/>
|
||||||
|
<div className="mt-4 p-4 bg-red-500/10 border-2 border-red-500/30 rounded-xl">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<span className="text-xl">⚠️</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-bold text-red-300 mb-1">Important</p>
|
||||||
|
<p className="text-xs text-red-200">
|
||||||
|
This endpoint can only be used once. Save the returned key immediately - it will
|
||||||
|
never be shown again.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="text-2xl">🎨</span>
|
||||||
|
<h4 className="text-xl font-bold text-white">Create Project Keys</h4>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 text-sm leading-relaxed mb-4">
|
||||||
|
Use your master key to create project-specific keys:
|
||||||
|
</p>
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/admin/keys \\
|
||||||
|
-H "X-API-Key: YOUR_MASTER_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"type": "project",
|
||||||
|
"projectId": "my-project",
|
||||||
|
"name": "Production Key"
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Response
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"key": "bnt_project_xyz789...",
|
||||||
|
"keyId": "key_abc123",
|
||||||
|
"expiresAt": "2025-04-15T10:30:00Z"
|
||||||
|
}`}
|
||||||
|
language="bash"
|
||||||
|
filename="Create Project Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Using Keys */}
|
||||||
|
<section id="using-keys" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">💻</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Using API Keys</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Include your API key in every request using the X-API-Key header:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using curl
|
||||||
|
curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_PROJECT_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{"prompt": "sunset", "filename": "test"}'
|
||||||
|
|
||||||
|
# Using JavaScript fetch
|
||||||
|
const response = await fetch('https://api.banatie.com/api/text-to-image', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': 'YOUR_PROJECT_KEY',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: 'sunset',
|
||||||
|
filename: 'test'
|
||||||
|
})
|
||||||
|
});`}
|
||||||
|
language="bash"
|
||||||
|
filename="API Request Example"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Security */}
|
||||||
|
<section id="security" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<span className="text-3xl">🛡️</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Security Best Practices</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-6">
|
||||||
|
<div className="p-6 bg-gradient-to-br from-red-500/10 to-transparent border-2 border-red-500/30 rounded-2xl shadow-lg hover:shadow-red-500/30 hover:scale-105 transition-all">
|
||||||
|
<div className="text-3xl mb-4">🔒</div>
|
||||||
|
<h4 className="text-lg font-bold text-white mb-2">Never Commit Keys</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Use environment variables or secret management tools. Never commit keys to version
|
||||||
|
control.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 rounded-2xl shadow-lg hover:shadow-amber-500/30 hover:scale-105 transition-all">
|
||||||
|
<div className="text-3xl mb-4">🔄</div>
|
||||||
|
<h4 className="text-lg font-bold text-white mb-2">Rotate Keys Regularly</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Project keys expire after 90 days. Plan for rotation and implement graceful handling.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-lg hover:shadow-purple-500/30 hover:scale-105 transition-all">
|
||||||
|
<div className="text-3xl mb-4">🚫</div>
|
||||||
|
<h4 className="text-lg font-bold text-white mb-2">Server-Side Only</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Never use API keys in client-side code. Always make requests from your backend.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-lg hover:shadow-cyan-500/30 hover:scale-105 transition-all">
|
||||||
|
<div className="text-3xl mb-4">👁️</div>
|
||||||
|
<h4 className="text-lg font-bold text-white mb-2">Monitor Usage</h4>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Track API key usage patterns. Unusual activity may indicate a compromised key.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Rate Limits */}
|
||||||
|
<section id="rate-limits" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">⏱️</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Rate Limits</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
To ensure fair usage and system stability, all API keys are subject to rate limits:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="overflow-hidden border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-slate-950/80 border-b-2 border-purple-500/20">
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold">Key Type</th>
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold">Limit</th>
|
||||||
|
<th className="text-left py-4 px-6 text-purple-400 font-bold">Window</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-gray-300 bg-slate-900/50">
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-semibold">Master Key</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-purple-500/20 text-purple-400 rounded-lg font-mono font-bold border-2 border-purple-500/40">
|
||||||
|
500 requests
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="py-4 px-6">per hour</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-slate-800">
|
||||||
|
<td className="py-4 px-6 font-semibold">Project Key</td>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
<span className="px-3 py-1.5 bg-cyan-500/20 text-cyan-400 rounded-lg font-mono font-bold border-2 border-cyan-500/40">
|
||||||
|
100 requests
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="py-4 px-6">per hour</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-xl shadow-cyan-500/20">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<span className="text-2xl">💬</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-bold text-cyan-300 mb-1">Need Higher Limits?</p>
|
||||||
|
<p className="text-sm text-cyan-200">
|
||||||
|
Contact our sales team to discuss enterprise plans with custom rate limits.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</DocsLayoutC>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting Started Page - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Colorful, card-based, playful visual design
|
||||||
|
*
|
||||||
|
* Key Characteristics:
|
||||||
|
* - NO section numbers (more visual/playful)
|
||||||
|
* - Large emoji icons throughout (text-3xl)
|
||||||
|
* - Gradient borders on all callout boxes
|
||||||
|
* - More colorful design (purple/cyan/amber accents)
|
||||||
|
* - Generous spacing (mb-12, p-6)
|
||||||
|
* - Larger padding and gaps throughout
|
||||||
|
* - Card-based sections with shadows
|
||||||
|
* - Floating visual effects
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DocsLayoutC } from '@/components/docs/variant-c/DocsLayoutC';
|
||||||
|
import { DocsSidebarC } from '@/components/docs/variant-c/DocsSidebarC';
|
||||||
|
import { DocsTOCC } from '@/components/docs/variant-c/DocsTOCC';
|
||||||
|
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
||||||
|
import { CodeBlock } from '@/components/docs/shared/CodeBlock';
|
||||||
|
|
||||||
|
const tocItems = [
|
||||||
|
{ id: 'introduction', text: 'Introduction', level: 2 },
|
||||||
|
{ id: 'quick-start', text: 'Quick Start', level: 2 },
|
||||||
|
{ id: 'installation', text: 'Installation', level: 3 },
|
||||||
|
{ id: 'authentication', text: 'Authentication', level: 3 },
|
||||||
|
{ id: 'first-request', text: 'Your First Request', level: 2 },
|
||||||
|
{ id: 'next-steps', text: 'Next Steps', level: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function GettingStartedPageC() {
|
||||||
|
return (
|
||||||
|
<DocsLayoutC
|
||||||
|
sidebar={<DocsSidebarC currentPath="/docs/variant-c" />}
|
||||||
|
toc={<DocsTOCC items={tocItems} />}
|
||||||
|
>
|
||||||
|
<Breadcrumb items={[{ label: 'Documentation', href: '/docs' }, { label: 'Getting Started' }]} />
|
||||||
|
|
||||||
|
{/* Hero Section - Large and Colorful */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/20 to-cyan-500/20 border-2 border-purple-500/40 mb-6">
|
||||||
|
<span className="text-2xl">🚀</span>
|
||||||
|
<span className="text-sm font-bold text-white">START HERE</span>
|
||||||
|
</div>
|
||||||
|
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 bg-gradient-to-r from-purple-400 to-cyan-400 bg-clip-text text-transparent">
|
||||||
|
Getting Started
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-300 leading-relaxed">
|
||||||
|
Welcome to the Banatie API documentation. Learn how to integrate AI-powered image
|
||||||
|
generation into your applications in minutes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Introduction */}
|
||||||
|
<section id="introduction" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">👋</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Introduction</h2>
|
||||||
|
</div>
|
||||||
|
<div className="p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl shadow-xl shadow-purple-500/20">
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-4">
|
||||||
|
Banatie is a developer-first API for AI-powered image generation. Built on Google Gemini
|
||||||
|
2.5 Flash and Imagen 4.0, it transforms text prompts and reference images into
|
||||||
|
production-ready visuals.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-300 leading-relaxed">
|
||||||
|
Whether you're building a content creation platform, e-commerce site, or creative tool,
|
||||||
|
Banatie provides the infrastructure you need to generate high-quality images at scale.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Quick Start */}
|
||||||
|
<section id="quick-start" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">⚡</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Quick Start</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="installation" className="mb-8">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="text-2xl">📦</span>
|
||||||
|
<h3 className="text-2xl font-semibold text-white">Installation</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Banatie is a REST API, so you don't need to install any libraries. However, we provide
|
||||||
|
SDKs for popular languages to make integration easier.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Using npm (JavaScript/TypeScript)
|
||||||
|
npm install @banatie/sdk
|
||||||
|
|
||||||
|
# Using pip (Python)
|
||||||
|
pip install banatie
|
||||||
|
|
||||||
|
# Using Go
|
||||||
|
go get github.com/banatie/sdk-go`}
|
||||||
|
language="bash"
|
||||||
|
filename="Installation"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="authentication" className="mb-8">
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
<span className="text-2xl">🔑</span>
|
||||||
|
<h3 className="text-2xl font-semibold text-white">Authentication</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
All API requests require an API key. You can create an API key from your dashboard or
|
||||||
|
using the bootstrap endpoint for initial setup.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/40 rounded-2xl mb-6 shadow-xl shadow-amber-500/20">
|
||||||
|
<div className="flex items-start gap-3">
|
||||||
|
<span className="text-2xl">💡</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm font-bold text-amber-300 mb-2">Security Tip</p>
|
||||||
|
<p className="text-sm text-amber-200">
|
||||||
|
Keep your API keys secure. Never commit them to public repositories or expose them
|
||||||
|
in client-side code.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`# Create your first API key (one-time bootstrap)
|
||||||
|
curl -X POST https://api.banatie.com/api/bootstrap/initial-key
|
||||||
|
|
||||||
|
# Save the returned key securely
|
||||||
|
export BANATIE_API_KEY="bnt_your_key_here"`}
|
||||||
|
language="bash"
|
||||||
|
filename="Get API Key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* First Request */}
|
||||||
|
<section id="first-request" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-6">
|
||||||
|
<span className="text-3xl">🎨</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Your First Request</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-300 leading-relaxed mb-6">
|
||||||
|
Let's generate your first image! This example uses curl, but you can use any HTTP client
|
||||||
|
or our SDKs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CodeBlock
|
||||||
|
code={`curl -X POST https://api.banatie.com/api/text-to-image \\
|
||||||
|
-H "X-API-Key: YOUR_API_KEY" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a serene mountain landscape at sunset",
|
||||||
|
"filename": "mountain_sunset",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
"autoEnhance": true
|
||||||
|
}'`}
|
||||||
|
language="bash"
|
||||||
|
filename="Generate Image"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt-6 p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl shadow-xl shadow-cyan-500/20">
|
||||||
|
<div className="flex items-start gap-3 mb-4">
|
||||||
|
<span className="text-2xl">✨</span>
|
||||||
|
<p className="text-sm font-bold text-cyan-300">Expected Response:</p>
|
||||||
|
</div>
|
||||||
|
<pre className="text-sm text-gray-300 overflow-x-auto bg-slate-950/50 p-4 rounded-xl border-2 border-cyan-500/20">
|
||||||
|
<code>{`{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"url": "https://cdn.banatie.com/org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"filepath": "org/project/generated/2025-01/mountain_sunset.png",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"promptEnhancement": {
|
||||||
|
"enhancedPrompt": "A breathtaking mountain landscape..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Next Steps */}
|
||||||
|
<section id="next-steps" className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<span className="text-3xl">🎯</span>
|
||||||
|
<h2 className="text-3xl font-bold text-white">Next Steps</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-6">
|
||||||
|
<a
|
||||||
|
href="/docs/variant-c/api/text-to-image"
|
||||||
|
className="group p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl hover:border-purple-500/60 transition-all duration-300 shadow-lg hover:shadow-purple-500/30 hover:scale-105"
|
||||||
|
>
|
||||||
|
<div className="text-3xl mb-4">📚</div>
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-purple-400 transition-colors">
|
||||||
|
API Reference
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Explore all available endpoints, parameters, and response formats.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-c/guides/authentication"
|
||||||
|
className="group p-6 bg-gradient-to-br from-cyan-500/10 to-transparent border-2 border-cyan-500/30 rounded-2xl hover:border-cyan-500/60 transition-all duration-300 shadow-lg hover:shadow-cyan-500/30 hover:scale-105"
|
||||||
|
>
|
||||||
|
<div className="text-3xl mb-4">🔐</div>
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-cyan-400 transition-colors">
|
||||||
|
Authentication Guide
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Learn about API keys, rate limits, and security best practices.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-c/examples"
|
||||||
|
className="group p-6 bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 rounded-2xl hover:border-amber-500/60 transition-all duration-300 shadow-lg hover:shadow-amber-500/30 hover:scale-105"
|
||||||
|
>
|
||||||
|
<div className="text-3xl mb-4">💡</div>
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-amber-400 transition-colors">
|
||||||
|
Examples
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Browse code examples and use cases for common scenarios.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="/docs/variant-c/guides/error-handling"
|
||||||
|
className="group p-6 bg-gradient-to-br from-purple-500/10 to-transparent border-2 border-purple-500/30 rounded-2xl hover:border-purple-500/60 transition-all duration-300 shadow-lg hover:shadow-purple-500/30 hover:scale-105"
|
||||||
|
>
|
||||||
|
<div className="text-3xl mb-4">⚠️</div>
|
||||||
|
<h3 className="text-xl font-bold text-white mb-3 group-hover:text-purple-400 transition-colors">
|
||||||
|
Error Handling
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-400">
|
||||||
|
Understand error codes and how to handle failures gracefully.
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Fun CTA Card */}
|
||||||
|
<div className="mt-12 p-8 bg-gradient-to-br from-purple-500/20 via-cyan-500/20 to-amber-500/20 border-2 border-purple-500/40 rounded-2xl shadow-2xl shadow-purple-500/30 text-center">
|
||||||
|
<div className="text-4xl mb-4">🎉</div>
|
||||||
|
<h3 className="text-2xl font-bold text-white mb-3">Ready to Build Something Amazing?</h3>
|
||||||
|
<p className="text-gray-300 mb-6">
|
||||||
|
Start creating stunning AI-generated images for your applications today!
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="/docs/variant-c/api/text-to-image"
|
||||||
|
className="inline-flex items-center gap-2 px-8 py-4 bg-gradient-to-r from-purple-600 to-cyan-600 hover:from-purple-500 hover:to-cyan-500 text-white font-bold rounded-xl transition-all duration-300 shadow-lg hover:shadow-purple-500/50 hover:scale-105"
|
||||||
|
>
|
||||||
|
<span>⚡</span>
|
||||||
|
<span>Explore the API</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</DocsLayoutC>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,202 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EndpointCard Component
|
|
||||||
*
|
|
||||||
* A structured display block for API endpoint information including HTTP method,
|
|
||||||
* path, and base URL. Creates consistent, scannable API reference documentation.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Information Grouping**: Related endpoint data in one visual container
|
|
||||||
* - Method badge + endpoint path on same line for scannability
|
|
||||||
* - Base URL separated below for clarity without clutter
|
|
||||||
* - Container styling creates clear boundaries
|
|
||||||
*
|
|
||||||
* 2. **Visual Hierarchy**: Emphasis guides attention naturally
|
|
||||||
* - HTTP method badge draws eye first (color + position)
|
|
||||||
* - Endpoint path is prominent (white text, slightly larger)
|
|
||||||
* - Base URL is secondary (smaller, muted gray)
|
|
||||||
*
|
|
||||||
* 3. **Technical Precision**: Monospace fonts for code accuracy
|
|
||||||
* - Endpoint path uses code styling
|
|
||||||
* - Prevents ambiguity in technical content
|
|
||||||
* - Familiar to developers
|
|
||||||
*
|
|
||||||
* ## Layout Strategy
|
|
||||||
*
|
|
||||||
* Horizontal Flow:
|
|
||||||
* ```
|
|
||||||
* [METHOD BADGE] /api/endpoint-path
|
|
||||||
* Base URL: https://api.example.com
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* This layout:
|
|
||||||
* - Puts most important info (method + path) on top line
|
|
||||||
* - Creates natural left-to-right reading flow
|
|
||||||
* - Groups related information visually
|
|
||||||
* - Works well at various screen sizes
|
|
||||||
*
|
|
||||||
* ## Container Styling
|
|
||||||
*
|
|
||||||
* Background & Border:
|
|
||||||
* - bg-slate-900/50: Semi-transparent dark background
|
|
||||||
* - Separates from page background
|
|
||||||
* - Maintains dark theme consistency
|
|
||||||
* - Subtle enough not to dominate
|
|
||||||
*
|
|
||||||
* - border-slate-700: Defined edges
|
|
||||||
* - Creates clear container boundaries
|
|
||||||
* - Adds structure without heaviness
|
|
||||||
* - Professional, technical appearance
|
|
||||||
*
|
|
||||||
* - rounded-xl: Soft corners (12px radius)
|
|
||||||
* - Modern, friendly appearance
|
|
||||||
* - Matches other card elements
|
|
||||||
* - Balances technical precision with approachability
|
|
||||||
*
|
|
||||||
* Padding:
|
|
||||||
* - p-4 (16px): Comfortable breathing room
|
|
||||||
* - Prevents cramped appearance
|
|
||||||
* - Makes content easy to read
|
|
||||||
* - Balances whitespace and content
|
|
||||||
*
|
|
||||||
* ## Typography System
|
|
||||||
*
|
|
||||||
* Endpoint Path:
|
|
||||||
* - text-sm: Slightly smaller than body but clearly readable
|
|
||||||
* - text-white: Maximum contrast for primary content
|
|
||||||
* - font-mono implicitly via <code>: Technical accuracy
|
|
||||||
*
|
|
||||||
* Base URL:
|
|
||||||
* - text-xs: Clearly secondary information
|
|
||||||
* - text-gray-400: Muted to not compete with endpoint
|
|
||||||
* - Includes "Base URL:" label for context
|
|
||||||
*
|
|
||||||
* ## Spacing & Layout
|
|
||||||
*
|
|
||||||
* Flex Layout Benefits:
|
|
||||||
* - items-center: Vertically centers badge with text
|
|
||||||
* - gap-3 (12px): Comfortable space between badge and path
|
|
||||||
* - mb-2 (8px): Separates primary info from base URL
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Standard REST endpoint
|
|
||||||
* <EndpointCard
|
|
||||||
* method="POST"
|
|
||||||
* endpoint="/api/text-to-image"
|
|
||||||
* baseUrl="https://api.banatie.com"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Different HTTP methods
|
|
||||||
* <EndpointCard
|
|
||||||
* method="GET"
|
|
||||||
* endpoint="/api/images"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* <EndpointCard
|
|
||||||
* method="DELETE"
|
|
||||||
* endpoint="/api/admin/keys/:keyId"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Custom base URL
|
|
||||||
* <EndpointCard
|
|
||||||
* method="PUT"
|
|
||||||
* endpoint="/api/projects/:id"
|
|
||||||
* baseUrl="https://api.custom-domain.com"
|
|
||||||
* />
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Content Guidelines
|
|
||||||
*
|
|
||||||
* HTTP Method:
|
|
||||||
* - Always uppercase (GET, POST, PUT, DELETE, PATCH)
|
|
||||||
* - Choose semantically correct method
|
|
||||||
* - Follows REST conventions
|
|
||||||
*
|
|
||||||
* Endpoint Path:
|
|
||||||
* - Start with forward slash (/)
|
|
||||||
* - Use lowercase with hyphens (kebab-case)
|
|
||||||
* - Include path parameters with colon prefix (:id, :keyId)
|
|
||||||
* - Be specific and descriptive
|
|
||||||
* - Example: `/api/projects/:projectId/keys`
|
|
||||||
*
|
|
||||||
* Base URL:
|
|
||||||
* - Include protocol (https://)
|
|
||||||
* - Use production URL as default
|
|
||||||
* - No trailing slash
|
|
||||||
* - Example: `https://api.banatie.com`
|
|
||||||
*
|
|
||||||
* ## Accessibility
|
|
||||||
*
|
|
||||||
* - Semantic HTML structure
|
|
||||||
* - Proper contrast ratios for all text
|
|
||||||
* - MethodBadge includes aria-label
|
|
||||||
* - Logical reading order (method → path → base)
|
|
||||||
* - Keyboard accessible (no interactive elements, but focusable context)
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The EndpointCard establishes:
|
|
||||||
* - Professional, technical aesthetic
|
|
||||||
* - Consistent API documentation pattern
|
|
||||||
* - Clear, unambiguous endpoint identification
|
|
||||||
* - Easy copy-paste of endpoint information
|
|
||||||
* - Quick visual scanning in multi-endpoint docs
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <EndpointCard
|
|
||||||
* method="POST"
|
|
||||||
* endpoint="/api/text-to-image"
|
|
||||||
* baseUrl="https://api.banatie.com"
|
|
||||||
* />
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { MethodBadge, HttpMethod } from './MethodBadge';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the EndpointCard component
|
|
||||||
*/
|
|
||||||
export interface EndpointCardProps {
|
|
||||||
/** HTTP method for the endpoint */
|
|
||||||
method: HttpMethod;
|
|
||||||
/** API endpoint path (e.g., "/api/users") */
|
|
||||||
endpoint: string;
|
|
||||||
/** Base URL for the API (default: "https://api.banatie.com") */
|
|
||||||
baseUrl?: string;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EndpointCard = ({
|
|
||||||
method,
|
|
||||||
endpoint,
|
|
||||||
baseUrl = 'https://api.banatie.com',
|
|
||||||
className = '',
|
|
||||||
}: EndpointCardProps) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`
|
|
||||||
p-4
|
|
||||||
bg-slate-900/50
|
|
||||||
border border-slate-700
|
|
||||||
rounded-xl
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{/* Method + Endpoint Row */}
|
|
||||||
<div className="flex items-center gap-3 mb-2">
|
|
||||||
<MethodBadge method={method} />
|
|
||||||
<code className="text-sm text-white">{endpoint}</code>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Base URL */}
|
|
||||||
<p className="text-xs text-gray-400">
|
|
||||||
Base URL: <code className="text-purple-400">{baseUrl}</code>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hero Component
|
|
||||||
*
|
|
||||||
* The primary heading section at the top of documentation pages.
|
|
||||||
* Establishes visual hierarchy and sets expectations for page content.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Information Hierarchy**: Clear progression from title to description
|
|
||||||
* - Large, bold title commands attention immediately
|
|
||||||
* - Subtitle provides context without competing with title
|
|
||||||
* - Consistent spacing creates rhythm and flow
|
|
||||||
*
|
|
||||||
* 2. **Typography Scale**: Responsive sizing for all devices
|
|
||||||
* - Mobile-first approach with thoughtful breakpoints
|
|
||||||
* - Maintains readability across screen sizes
|
|
||||||
* - Proper line-height for comfortable reading
|
|
||||||
*
|
|
||||||
* 3. **Visual Weight**: Balanced presence without overwhelming
|
|
||||||
* - White title for maximum contrast and impact
|
|
||||||
* - Gray subtitle for supporting, not competing
|
|
||||||
* - Generous margins create breathing room
|
|
||||||
*
|
|
||||||
* ## Size Variants
|
|
||||||
*
|
|
||||||
* @param {'default'} default - Standard documentation pages
|
|
||||||
* - Title: text-4xl (36px) → md:text-5xl (48px)
|
|
||||||
* - Use cases: API references, guides, tutorials
|
|
||||||
* - Psychology: Professional, focused, informative
|
|
||||||
* - Spacing: mb-12 (48px) after hero
|
|
||||||
*
|
|
||||||
* @param {'large'} large - Major landing pages, section introductions
|
|
||||||
* - Title: text-5xl (48px) → md:text-6xl (60px)
|
|
||||||
* - Use cases: Documentation home, major category pages
|
|
||||||
* - Psychology: Welcoming, important, primary entry point
|
|
||||||
* - Spacing: mb-16 (64px) after hero
|
|
||||||
*
|
|
||||||
* ## Typographic Hierarchy
|
|
||||||
*
|
|
||||||
* Title Characteristics:
|
|
||||||
* - **Weight**: font-bold (700) - Commands attention
|
|
||||||
* - **Color**: text-white - Maximum contrast, immediately readable
|
|
||||||
* - **Spacing**: mb-4 (16px) - Connects title to subtitle
|
|
||||||
*
|
|
||||||
* Subtitle Characteristics:
|
|
||||||
* - **Size**: text-xl (20px) - Large enough to be comfortable, small enough to defer
|
|
||||||
* - **Weight**: Regular (400) - Contrast with bold title
|
|
||||||
* - **Color**: text-gray-400 - Supporting role, doesn't compete
|
|
||||||
* - **Line height**: leading-relaxed (1.625) - Comfortable multi-line reading
|
|
||||||
*
|
|
||||||
* ## Responsive Behavior
|
|
||||||
*
|
|
||||||
* Mobile (<768px):
|
|
||||||
* - Smaller text sizes to fit narrow screens
|
|
||||||
* - Maintains readability with appropriate line lengths
|
|
||||||
* - Single column layout
|
|
||||||
*
|
|
||||||
* Desktop (≥768px):
|
|
||||||
* - Larger text leverages available space
|
|
||||||
* - Enhanced visual impact
|
|
||||||
* - Better use of vertical rhythm
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The hero serves multiple purposes in documentation:
|
|
||||||
* 1. **Orientation**: Tells users where they are
|
|
||||||
* 2. **Context**: Explains what this page covers
|
|
||||||
* 3. **Hierarchy**: Establishes importance through size
|
|
||||||
* 4. **Consistency**: Familiarpattern across all docs pages
|
|
||||||
*
|
|
||||||
* Color Psychology:
|
|
||||||
* - **White title**: Authority, clarity, primary information
|
|
||||||
* - **Gray subtitle**: Support, context, secondary information
|
|
||||||
* - Creates natural reading flow: bold → light, primary → secondary
|
|
||||||
*
|
|
||||||
* ## Accessibility
|
|
||||||
*
|
|
||||||
* - Uses semantic HTML (<h1> for title)
|
|
||||||
* - Proper heading hierarchy (h1 is first heading on page)
|
|
||||||
* - Sufficient color contrast (white on dark background)
|
|
||||||
* - Readable font sizes (minimum 20px for subtitle)
|
|
||||||
* - Appropriate line-height for comfortable reading
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Standard API reference page
|
|
||||||
* <Hero
|
|
||||||
* title="Text to Image"
|
|
||||||
* subtitle="Generate high-quality images from text prompts using AI-powered models."
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Documentation home page
|
|
||||||
* <Hero
|
|
||||||
* size="large"
|
|
||||||
* title="Welcome to Banatie API Documentation"
|
|
||||||
* subtitle="Learn how to integrate AI-powered image generation into your applications in minutes."
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Guide page
|
|
||||||
* <Hero
|
|
||||||
* title="Authentication"
|
|
||||||
* subtitle="Learn how to authenticate with the Banatie API using API keys, manage rate limits, and implement security best practices."
|
|
||||||
* />
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Content Guidelines
|
|
||||||
*
|
|
||||||
* Title:
|
|
||||||
* - Keep short and specific (1-5 words ideal)
|
|
||||||
* - Use sentence case (capitalize first word only)
|
|
||||||
* - Avoid punctuation unless necessary
|
|
||||||
* - Match page's primary purpose
|
|
||||||
*
|
|
||||||
* Subtitle:
|
|
||||||
* - One to two sentences maximum
|
|
||||||
* - Explain what user will learn or accomplish
|
|
||||||
* - Use active voice and present tense
|
|
||||||
* - End with period for complete thoughts
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <Hero
|
|
||||||
* title="Getting Started"
|
|
||||||
* subtitle="Welcome to the Banatie API documentation."
|
|
||||||
* size="default"
|
|
||||||
* />
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size variant determining the visual scale of the hero
|
|
||||||
*/
|
|
||||||
export type HeroSize = 'default' | 'large';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the Hero component
|
|
||||||
*/
|
|
||||||
export interface HeroProps {
|
|
||||||
/** The main page title (renders as h1) */
|
|
||||||
title: string;
|
|
||||||
/** Supporting description or context */
|
|
||||||
subtitle: string | ReactNode;
|
|
||||||
/** Size variant (default: 'default') */
|
|
||||||
size?: HeroSize;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Title size system mapping size variant to responsive text classes
|
|
||||||
*/
|
|
||||||
const titleSizes: Record<HeroSize, string> = {
|
|
||||||
default: 'text-4xl md:text-5xl',
|
|
||||||
large: 'text-5xl md:text-6xl',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spacing system for bottom margin
|
|
||||||
*/
|
|
||||||
const spacingSizes: Record<HeroSize, string> = {
|
|
||||||
default: 'mb-12',
|
|
||||||
large: 'mb-16',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Hero = ({
|
|
||||||
title,
|
|
||||||
subtitle,
|
|
||||||
size = 'default',
|
|
||||||
className = '',
|
|
||||||
}: HeroProps) => {
|
|
||||||
return (
|
|
||||||
<div className={`${spacingSizes[size]} ${className}`}>
|
|
||||||
<h1 className={`${titleSizes[size]} font-bold text-white mb-4`}>
|
|
||||||
{title}
|
|
||||||
</h1>
|
|
||||||
<p className="text-xl text-gray-400 leading-relaxed">
|
|
||||||
{subtitle}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,156 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* InlineCode Component
|
|
||||||
*
|
|
||||||
* A consistent inline code element for technical content within documentation text.
|
|
||||||
* Provides semantic color variants to emphasize context and meaning.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Readability First**: High contrast with surrounding text
|
|
||||||
* - Dark background distinguishes code from prose
|
|
||||||
* - Slightly larger padding creates breathing room
|
|
||||||
* - Rounded corners soften appearance for inline usage
|
|
||||||
*
|
|
||||||
* 2. **Semantic Coloring**: Color conveys meaning beyond monospace
|
|
||||||
* - Different contexts require different visual emphasis
|
|
||||||
* - Colors match broader design system for consistency
|
|
||||||
* - Never rely on color alone (always has monospace + background)
|
|
||||||
*
|
|
||||||
* 3. **Typography**: Monospace font signals technical content
|
|
||||||
* - Built-in font-mono class ensures code appearance
|
|
||||||
* - Small size (text-sm) fits inline with body text
|
|
||||||
* - Maintains readability without disrupting flow
|
|
||||||
*
|
|
||||||
* ## Color Semantic Values
|
|
||||||
*
|
|
||||||
* @param {'primary'} primary - Default technical content, variable names, general code
|
|
||||||
* - Visual: Purple accent (matches brand primary)
|
|
||||||
* - Psychology: Neutral technical content, primary focus
|
|
||||||
* - Use cases: `apiKey`, `userId`, general inline code snippets
|
|
||||||
* - When to use: Default choice for any code reference
|
|
||||||
*
|
|
||||||
* @param {'success'} success - Positive examples, correct values, successful states
|
|
||||||
* - Visual: Green accent
|
|
||||||
* - Psychology: Correct, recommended, successful outcome
|
|
||||||
* - Use cases: `status: 200`, `"success": true`, correct API responses
|
|
||||||
* - When to use: Showing what TO do, expected good outcomes
|
|
||||||
*
|
|
||||||
* @param {'error'} error - Error values, incorrect usage, warnings
|
|
||||||
* - Visual: Red accent
|
|
||||||
* - Psychology: Wrong, dangerous, avoid
|
|
||||||
* - Use cases: `status: 500`, error codes, anti-patterns
|
|
||||||
* - When to use: Showing what NOT to do, error states
|
|
||||||
*
|
|
||||||
* @param {'neutral'} neutral - Informational, documentation, placeholders
|
|
||||||
* - Visual: Slate/Gray (matches text color scheme)
|
|
||||||
* - Psychology: Reference, documentation, less emphasis
|
|
||||||
* - Use cases: HTTP headers like `X-API-Key`, endpoints, technical terms
|
|
||||||
* - When to use: Supporting information, less critical code references
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* Background Strategy:
|
|
||||||
* - Dark bg (slate-800) creates clear separation from surrounding text
|
|
||||||
* - Works on both light and dark documentation themes
|
|
||||||
* - Sufficient contrast meets WCAG AA standards
|
|
||||||
*
|
|
||||||
* Padding Strategy:
|
|
||||||
* - Horizontal: px-1.5 (6px) - enough space but not disruptive
|
|
||||||
* - Vertical: py-0.5 (2px) - maintains inline text flow
|
|
||||||
* - Border radius: rounded (4px) - soft enough for inline, defined enough for blocks
|
|
||||||
*
|
|
||||||
* Font Strategy:
|
|
||||||
* - text-sm: Slightly smaller than body text but still readable
|
|
||||||
* - font-mono: Clear distinction from prose, signals code
|
|
||||||
* - font-normal: Not bold, integrates naturally with surrounding text
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Default technical content
|
|
||||||
* Set your <InlineCode>API_KEY</InlineCode> environment variable.
|
|
||||||
*
|
|
||||||
* // With semantic colors
|
|
||||||
* The response includes <InlineCode color="success">status: 200</InlineCode>.
|
|
||||||
* Avoid using <InlineCode color="error">hardcoded credentials</InlineCode>.
|
|
||||||
* Include the <InlineCode color="neutral">X-API-Key</InlineCode> header.
|
|
||||||
*
|
|
||||||
* // Parameter documentation
|
|
||||||
* The <InlineCode>autoEnhance</InlineCode> parameter defaults to false.
|
|
||||||
*
|
|
||||||
* // Error messages
|
|
||||||
* If you receive <InlineCode color="error">401 Unauthorized</InlineCode>, check your API key.
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Composition Guidelines
|
|
||||||
*
|
|
||||||
* DO:
|
|
||||||
* - Use for short code snippets (1-4 words)
|
|
||||||
* - Use for technical terms, variable names, values
|
|
||||||
* - Use semantic colors to reinforce meaning
|
|
||||||
* - Place naturally within sentences
|
|
||||||
*
|
|
||||||
* DON'T:
|
|
||||||
* - Use for multi-line code (use CodeBlock instead)
|
|
||||||
* - Use for long strings (creates readability issues)
|
|
||||||
* - Overuse color variants (primary is default for a reason)
|
|
||||||
* - Use as a design element (it's for code content only)
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <InlineCode color="primary">apiKey</InlineCode>
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Semantic color variants for inline code
|
|
||||||
*/
|
|
||||||
export type InlineCodeColor = 'primary' | 'success' | 'error' | 'neutral';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the InlineCode component
|
|
||||||
*/
|
|
||||||
export interface InlineCodeProps {
|
|
||||||
/** The code content to display */
|
|
||||||
children: ReactNode;
|
|
||||||
/** Semantic color variant (default: 'primary') */
|
|
||||||
color?: InlineCodeColor;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Color system mapping semantic meanings to text colors
|
|
||||||
* All use same dark background for consistency
|
|
||||||
*/
|
|
||||||
const colorStyles: Record<InlineCodeColor, string> = {
|
|
||||||
primary: 'text-purple-400',
|
|
||||||
success: 'text-green-400',
|
|
||||||
error: 'text-red-400',
|
|
||||||
neutral: 'text-gray-400',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const InlineCode = ({
|
|
||||||
children,
|
|
||||||
color = 'primary',
|
|
||||||
className = '',
|
|
||||||
}: InlineCodeProps) => {
|
|
||||||
return (
|
|
||||||
<code
|
|
||||||
className={`
|
|
||||||
inline-block
|
|
||||||
px-1.5 py-0.5
|
|
||||||
bg-slate-800
|
|
||||||
rounded
|
|
||||||
font-mono text-sm
|
|
||||||
${colorStyles[color]}
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</code>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,281 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LinkCard Component
|
|
||||||
*
|
|
||||||
* An interactive navigation card for guiding users to related documentation pages.
|
|
||||||
* Uses color accents and hover effects to create an engaging, explorable experience.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Visual Affordance**: Design signals interactivity
|
|
||||||
* - Gradient backgrounds hint at clickability
|
|
||||||
* - Hover states provide immediate feedback
|
|
||||||
* - Cursor changes to pointer on hover
|
|
||||||
* - Border transitions guide attention
|
|
||||||
*
|
|
||||||
* 2. **Semantic Color System**: Accent colors convey meaning
|
|
||||||
* - Primary (Purple): Main content, API references
|
|
||||||
* - Secondary (Cyan): Supporting content, guides
|
|
||||||
* - Success (Green): Getting started, tutorials
|
|
||||||
* - Warning (Amber): Important notices, deprecations
|
|
||||||
*
|
|
||||||
* 3. **Information Hierarchy**: Title dominates, description supports
|
|
||||||
* - Large, bold title draws attention
|
|
||||||
* - Smaller, muted description provides context
|
|
||||||
* - Title color changes on hover for feedback
|
|
||||||
* - Clean vertical rhythm (title → description)
|
|
||||||
*
|
|
||||||
* ## Accent Color Semantics
|
|
||||||
*
|
|
||||||
* @param {'primary'} primary - Main navigational elements, API documentation
|
|
||||||
* - Visual: Purple gradient and border
|
|
||||||
* - Psychology: Primary brand, core content, important
|
|
||||||
* - Use cases: "API Reference", "Core Concepts", main docs
|
|
||||||
* - Gradient: from-purple-500/10
|
|
||||||
* - Hover: border-purple-500/40, text-purple-400
|
|
||||||
*
|
|
||||||
* @param {'secondary'} secondary - Supporting content, guides, tutorials
|
|
||||||
* - Visual: Cyan gradient and border
|
|
||||||
* - Psychology: Complementary, helpful, educational
|
|
||||||
* - Use cases: "Guides", "Tutorials", "Best Practices"
|
|
||||||
* - Gradient: from-cyan-500/10
|
|
||||||
* - Hover: border-cyan-500/40, text-cyan-400
|
|
||||||
*
|
|
||||||
* @param {'success'} success - Getting started, quick wins, positive actions
|
|
||||||
* - Visual: Green gradient and border
|
|
||||||
* - Psychology: Achievement, beginning, growth
|
|
||||||
* - Use cases: "Getting Started", "Quick Start", "First Steps"
|
|
||||||
* - Gradient: from-green-500/10
|
|
||||||
* - Hover: border-green-500/40, text-green-400
|
|
||||||
*
|
|
||||||
* @param {'warning'} warning - Important notices, cautions, deprecations
|
|
||||||
* - Visual: Amber gradient and border
|
|
||||||
* - Psychology: Attention, caution, important
|
|
||||||
* - Use cases: "Migration Guide", "Breaking Changes", "Deprecations"
|
|
||||||
* - Gradient: from-amber-500/10
|
|
||||||
* - Hover: border-amber-500/40, text-amber-400
|
|
||||||
*
|
|
||||||
* ## Interactive States
|
|
||||||
*
|
|
||||||
* Default State:
|
|
||||||
* - Subtle gradient background (from-{color}-500/10)
|
|
||||||
* - Muted border (border-slate-700/50)
|
|
||||||
* - White title, gray description
|
|
||||||
* - Inviting but not demanding attention
|
|
||||||
*
|
|
||||||
* Hover State:
|
|
||||||
* - Border brightens to accent color (/40 opacity)
|
|
||||||
* - Title transitions to accent color
|
|
||||||
* - Smooth transition (transition-colors)
|
|
||||||
* - Clear feedback that element is clickable
|
|
||||||
*
|
|
||||||
* ## Layout Structure
|
|
||||||
*
|
|
||||||
* Padding System:
|
|
||||||
* - p-5 (20px): Generous padding for comfortable clicking
|
|
||||||
* - Creates substantial hit area for accessibility
|
|
||||||
* - Provides breathing room for content
|
|
||||||
*
|
|
||||||
* Border & Radius:
|
|
||||||
* - rounded-xl (12px): Modern, friendly appearance
|
|
||||||
* - border: Defined structure
|
|
||||||
* - Matches other card components in system
|
|
||||||
*
|
|
||||||
* ## Typography System
|
|
||||||
*
|
|
||||||
* Title (h3):
|
|
||||||
* - text-lg (18px): Large enough to be primary visual element
|
|
||||||
* - font-semibold (600): Strong but not overbearing
|
|
||||||
* - text-white: Maximum contrast and readability
|
|
||||||
* - mb-2 (8px): Separates from description
|
|
||||||
* - Transitions to accent color on hover
|
|
||||||
*
|
|
||||||
* Description (p):
|
|
||||||
* - text-sm (14px): Clearly secondary to title
|
|
||||||
* - text-gray-400: Muted, supporting role
|
|
||||||
* - Provides context without competing with title
|
|
||||||
*
|
|
||||||
* ## Accessibility Features
|
|
||||||
*
|
|
||||||
* - Semantic HTML (<a> tag for links)
|
|
||||||
* - Proper heading hierarchy (h3 for card titles)
|
|
||||||
* - Keyboard accessible (focusable link)
|
|
||||||
* - Sufficient color contrast in all states
|
|
||||||
* - Large click target (full card clickable)
|
|
||||||
* - Clear focus states (browser default + hover)
|
|
||||||
* - Descriptive link text (title + description)
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Primary content link
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/api/text-to-image"
|
|
||||||
* title="API Reference"
|
|
||||||
* description="Explore all available endpoints, parameters, and response formats."
|
|
||||||
* accent="primary"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Getting started
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/quick-start"
|
|
||||||
* title="Quick Start"
|
|
||||||
* description="Get up and running with Banatie API in 5 minutes."
|
|
||||||
* accent="success"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Supporting guide
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/guides/authentication"
|
|
||||||
* title="Authentication Guide"
|
|
||||||
* description="Learn about API keys, rate limits, and security best practices."
|
|
||||||
* accent="secondary"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Important notice
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/migration"
|
|
||||||
* title="Migration Guide"
|
|
||||||
* description="Upgrade to v2 API with this step-by-step migration guide."
|
|
||||||
* accent="warning"
|
|
||||||
* />
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Content Guidelines
|
|
||||||
*
|
|
||||||
* Title:
|
|
||||||
* - 2-5 words ideal
|
|
||||||
* - Action-oriented or noun-based
|
|
||||||
* - Clear and specific
|
|
||||||
* - Sentence case
|
|
||||||
* - Examples: "API Reference", "Quick Start", "Authentication Guide"
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* - One sentence (10-20 words)
|
|
||||||
* - Explain what user will find/learn
|
|
||||||
* - Start with verb (Explore, Learn, Discover)
|
|
||||||
* - End with period
|
|
||||||
* - Be specific about content
|
|
||||||
*
|
|
||||||
* Accent Color:
|
|
||||||
* - Choose based on content type and importance
|
|
||||||
* - Maintain consistency across similar pages
|
|
||||||
* - Use primary for most API/core documentation
|
|
||||||
* - Reserve warning for truly important notices
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The LinkCard system creates:
|
|
||||||
* - Intuitive navigation patterns
|
|
||||||
* - Clear content categorization through color
|
|
||||||
* - Engaging, explorable documentation
|
|
||||||
* - Professional yet friendly appearance
|
|
||||||
* - Consistent user experience across all docs
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/api"
|
|
||||||
* title="API Reference"
|
|
||||||
* description="Complete API documentation"
|
|
||||||
* accent="primary"
|
|
||||||
* />
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accent color determining the card's visual theme
|
|
||||||
*/
|
|
||||||
export type LinkCardAccent = 'primary' | 'secondary' | 'success' | 'warning';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the LinkCard component
|
|
||||||
*/
|
|
||||||
export interface LinkCardProps {
|
|
||||||
/** Navigation URL */
|
|
||||||
href: string;
|
|
||||||
/** Card title (renders as h3) */
|
|
||||||
title: string;
|
|
||||||
/** Supporting description */
|
|
||||||
description: string;
|
|
||||||
/** Visual accent color */
|
|
||||||
accent: LinkCardAccent;
|
|
||||||
/** Optional icon or emoji to display */
|
|
||||||
icon?: string;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accent styles mapping color to gradient and hover colors
|
|
||||||
*/
|
|
||||||
const accentStyles: Record<LinkCardAccent, {
|
|
||||||
gradient: string;
|
|
||||||
hoverBorder: string;
|
|
||||||
hoverText: string;
|
|
||||||
}> = {
|
|
||||||
primary: {
|
|
||||||
gradient: 'from-purple-500/10',
|
|
||||||
hoverBorder: 'hover:border-purple-500/40',
|
|
||||||
hoverText: 'group-hover:text-purple-400',
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
gradient: 'from-cyan-500/10',
|
|
||||||
hoverBorder: 'hover:border-cyan-500/40',
|
|
||||||
hoverText: 'group-hover:text-cyan-400',
|
|
||||||
},
|
|
||||||
success: {
|
|
||||||
gradient: 'from-green-500/10',
|
|
||||||
hoverBorder: 'hover:border-green-500/40',
|
|
||||||
hoverText: 'group-hover:text-green-400',
|
|
||||||
},
|
|
||||||
warning: {
|
|
||||||
gradient: 'from-amber-500/10',
|
|
||||||
hoverBorder: 'hover:border-amber-500/40',
|
|
||||||
hoverText: 'group-hover:text-amber-400',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LinkCard = ({
|
|
||||||
href,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
accent,
|
|
||||||
icon,
|
|
||||||
className = '',
|
|
||||||
}: LinkCardProps) => {
|
|
||||||
const styles = accentStyles[accent];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={href}
|
|
||||||
className={`
|
|
||||||
block
|
|
||||||
p-5
|
|
||||||
bg-gradient-to-br ${styles.gradient} to-transparent
|
|
||||||
border border-slate-700/50
|
|
||||||
rounded-xl
|
|
||||||
${styles.hoverBorder}
|
|
||||||
transition-colors
|
|
||||||
group
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{icon && (
|
|
||||||
<div className="text-2xl mb-3">{icon}</div>
|
|
||||||
)}
|
|
||||||
<h3
|
|
||||||
className={`
|
|
||||||
text-lg font-semibold text-white mb-2
|
|
||||||
${styles.hoverText}
|
|
||||||
transition-colors
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-sm text-gray-400">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,216 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LinkCardGrid Component
|
|
||||||
*
|
|
||||||
* A responsive grid layout container for organizing multiple LinkCard components.
|
|
||||||
* Provides consistent spacing and responsive behavior for navigation card collections.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Responsive Layout**: Adapts gracefully to all screen sizes
|
|
||||||
* - Mobile: Single column for comfortable tap targets
|
|
||||||
* - Tablet/Desktop: Multi-column for efficient space usage
|
|
||||||
* - Fluid transitions between breakpoints
|
|
||||||
*
|
|
||||||
* 2. **Grid System**: CSS Grid provides flexible, robust layout
|
|
||||||
* - Equal-width columns maintain balance
|
|
||||||
* - Auto-fit for flexible number of cards
|
|
||||||
* - Consistent gaps create visual rhythm
|
|
||||||
*
|
|
||||||
* 3. **Composition Pattern**: Wrapper abstracts layout complexity
|
|
||||||
* - Parent handles grid logic
|
|
||||||
* - Children (LinkCards) focus on content
|
|
||||||
* - Separation of concerns improves maintainability
|
|
||||||
*
|
|
||||||
* ## Column Configuration
|
|
||||||
*
|
|
||||||
* @param {2} columns=2 - Two-column layout (default)
|
|
||||||
* - Visual: Balanced, side-by-side comparison
|
|
||||||
* - Use cases: "Next Steps", paired content, binary choices
|
|
||||||
* - Responsive: md:grid-cols-2 (2 cols ≥768px, 1 col <768px)
|
|
||||||
* - Psychology: Compare and choose pattern
|
|
||||||
* - Example: "API Reference" vs "Authentication Guide"
|
|
||||||
*
|
|
||||||
* @param {3} columns=3 - Three-column layout
|
|
||||||
* - Visual: Information-rich, multiple options
|
|
||||||
* - Use cases: Resource hubs, category pages, multiple paths
|
|
||||||
* - Responsive: md:grid-cols-3 (3 cols ≥768px, 1 col <768px)
|
|
||||||
* - Psychology: Multiple choice, exploration
|
|
||||||
* - Example: "Getting Started", "API Docs", "Examples"
|
|
||||||
*
|
|
||||||
* @param {4} columns=4 - Four-column layout
|
|
||||||
* - Visual: Dense, comprehensive navigation
|
|
||||||
* - Use cases: Resource libraries, extensive catalogs
|
|
||||||
* - Responsive: md:grid-cols-2 lg:grid-cols-4 (2 cols tablet, 4 cols desktop)
|
|
||||||
* - Psychology: Broad exploration, many options
|
|
||||||
* - Example: Multiple API endpoints, extensive guides
|
|
||||||
*
|
|
||||||
* ## Responsive Breakpoints
|
|
||||||
*
|
|
||||||
* Mobile (<768px):
|
|
||||||
* - All grids collapse to single column
|
|
||||||
* - Prevents cramped cards on small screens
|
|
||||||
* - Optimizes for thumb-friendly tap targets
|
|
||||||
* - Maintains readability and usability
|
|
||||||
*
|
|
||||||
* Tablet (≥768px, <1024px):
|
|
||||||
* - 2-column: Displays as 2 columns
|
|
||||||
* - 3-column: Displays as 3 columns
|
|
||||||
* - 4-column: Displays as 2 columns (intermediate step)
|
|
||||||
* - Balances space usage and readability
|
|
||||||
*
|
|
||||||
* Desktop (≥1024px):
|
|
||||||
* - All grids display at full column count
|
|
||||||
* - Efficient use of available width
|
|
||||||
* - Supports quick visual scanning
|
|
||||||
*
|
|
||||||
* ## Spacing System
|
|
||||||
*
|
|
||||||
* Gap:
|
|
||||||
* - gap-4 (16px): Comfortable separation between cards
|
|
||||||
* - Creates visual grouping without crowding
|
|
||||||
* - Maintains clean grid appearance
|
|
||||||
* - Consistent with other spacing in design system
|
|
||||||
*
|
|
||||||
* Why gap-4?
|
|
||||||
* - Larger than text line-height (prevents cramping)
|
|
||||||
* - Small enough to show relationship between cards
|
|
||||||
* - Works well with card padding (p-5)
|
|
||||||
* - Scales gracefully at all screen sizes
|
|
||||||
*
|
|
||||||
* ## Grid Behavior
|
|
||||||
*
|
|
||||||
* CSS Grid Properties:
|
|
||||||
* - `grid`: Establishes grid container
|
|
||||||
* - `grid-cols-1`: Mobile baseline (single column)
|
|
||||||
* - `md:grid-cols-{n}`: Tablet/desktop columns
|
|
||||||
* - `gap-4`: Gutter between grid items
|
|
||||||
*
|
|
||||||
* ## Accessibility Considerations
|
|
||||||
*
|
|
||||||
* - Maintains logical reading order (top-to-bottom, left-to-right)
|
|
||||||
* - Grid doesn't interfere with keyboard navigation
|
|
||||||
* - Responsive design ensures usability on all devices
|
|
||||||
* - No JavaScript required (pure CSS grid)
|
|
||||||
* - Works with screen readers (semantic HTML preserved)
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Two-column "Next Steps" section
|
|
||||||
* <LinkCardGrid columns={2}>
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/api"
|
|
||||||
* title="API Reference"
|
|
||||||
* description="Explore all endpoints"
|
|
||||||
* accent="primary"
|
|
||||||
* />
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/guides"
|
|
||||||
* title="Guides"
|
|
||||||
* description="Learn best practices"
|
|
||||||
* accent="secondary"
|
|
||||||
* />
|
|
||||||
* </LinkCardGrid>
|
|
||||||
*
|
|
||||||
* // Three-column resource hub
|
|
||||||
* <LinkCardGrid columns={3}>
|
|
||||||
* <LinkCard href="..." title="Getting Started" accent="success" description="..." />
|
|
||||||
* <LinkCard href="..." title="API Docs" accent="primary" description="..." />
|
|
||||||
* <LinkCard href="..." title="Examples" accent="secondary" description="..." />
|
|
||||||
* </LinkCardGrid>
|
|
||||||
*
|
|
||||||
* // Four-column comprehensive navigation
|
|
||||||
* <LinkCardGrid columns={4}>
|
|
||||||
* <LinkCard href="..." title="Text to Image" accent="primary" description="..." />
|
|
||||||
* <LinkCard href="..." title="Upload" accent="primary" description="..." />
|
|
||||||
* <LinkCard href="..." title="Authentication" accent="secondary" description="..." />
|
|
||||||
* <LinkCard href="..." title="Rate Limits" accent="secondary" description="..." />
|
|
||||||
* </LinkCardGrid>
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Composition Guidelines
|
|
||||||
*
|
|
||||||
* DO:
|
|
||||||
* - Use consistent accent colors within a grid (e.g., all primary, or primary + secondary)
|
|
||||||
* - Keep card count balanced (even numbers work best for 2/4 columns)
|
|
||||||
* - Provide descriptive, parallel content in cards
|
|
||||||
* - Order cards by importance or logical flow
|
|
||||||
*
|
|
||||||
* DON'T:
|
|
||||||
* - Mix too many accent colors (creates visual chaos)
|
|
||||||
* - Use unbalanced card counts in 2-column (odd numbers leave gaps)
|
|
||||||
* - Nest grids inside grids (causes layout issues)
|
|
||||||
* - Put non-LinkCard components inside (breaks grid consistency)
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The LinkCardGrid creates:
|
|
||||||
* - Organized, scannable navigation patterns
|
|
||||||
* - Professional documentation architecture
|
|
||||||
* - Clear visual hierarchy through layout
|
|
||||||
* - Responsive, mobile-friendly experience
|
|
||||||
* - Consistent spacing and alignment
|
|
||||||
*
|
|
||||||
* ## Performance
|
|
||||||
*
|
|
||||||
* - Pure CSS (no JavaScript overhead)
|
|
||||||
* - Minimal DOM elements (single wrapper div)
|
|
||||||
* - Hardware-accelerated grid layout
|
|
||||||
* - No re-renders or layout thrashing
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <LinkCardGrid columns={2}>
|
|
||||||
* {children}
|
|
||||||
* </LinkCardGrid>
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Column configuration for the grid
|
|
||||||
*/
|
|
||||||
export type GridColumns = 2 | 3 | 4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the LinkCardGrid component
|
|
||||||
*/
|
|
||||||
export interface LinkCardGridProps {
|
|
||||||
/** Number of columns at tablet/desktop breakpoints */
|
|
||||||
columns?: GridColumns;
|
|
||||||
/** LinkCard components to display in the grid */
|
|
||||||
children: ReactNode;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Responsive grid class mappings for different column counts
|
|
||||||
*/
|
|
||||||
const columnStyles: Record<GridColumns, string> = {
|
|
||||||
2: 'md:grid-cols-2',
|
|
||||||
3: 'md:grid-cols-3',
|
|
||||||
4: 'md:grid-cols-2 lg:grid-cols-4', // 2 cols on tablet, 4 on desktop
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LinkCardGrid = ({
|
|
||||||
columns = 2,
|
|
||||||
children,
|
|
||||||
className = '',
|
|
||||||
}: LinkCardGridProps) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`
|
|
||||||
grid
|
|
||||||
grid-cols-1
|
|
||||||
${columnStyles[columns]}
|
|
||||||
gap-4
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MethodBadge Component
|
|
||||||
*
|
|
||||||
* A specialized badge for HTTP method display in API documentation.
|
|
||||||
* Uses industry-standard color conventions to communicate REST operation types.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **REST Semantic Mapping**: Colors align with HTTP method semantics
|
|
||||||
* - Follows industry conventions (GitHub, Stripe, Swagger UI)
|
|
||||||
* - Immediate visual recognition for developers
|
|
||||||
* - Consistent with HTTP specification meanings
|
|
||||||
*
|
|
||||||
* 2. **Visual Distinction**: Each method has unique, memorable color
|
|
||||||
* - High contrast for readability against dark backgrounds
|
|
||||||
* - Distinct enough to differentiate at a glance
|
|
||||||
* - Professional appearance suitable for technical documentation
|
|
||||||
*
|
|
||||||
* 3. **Typography**: Bold, uppercase display reinforces technical nature
|
|
||||||
* - font-bold for emphasis and readability
|
|
||||||
* - Uppercase matches HTTP specification format
|
|
||||||
* - Monospace-friendly sizing
|
|
||||||
*
|
|
||||||
* ## HTTP Method Semantics
|
|
||||||
*
|
|
||||||
* @param {'GET'} GET - Read/Retrieve operations (Safe, Idempotent)
|
|
||||||
* - Visual: Cyan/Blue - represents data flow inward (reading)
|
|
||||||
* - Psychology: Information retrieval, safe operation
|
|
||||||
* - Use cases: Fetch resources, list endpoints, query data
|
|
||||||
* - HTTP: Safe method, no side effects, cacheable
|
|
||||||
*
|
|
||||||
* @param {'POST'} POST - Create operations (Not safe, Not idempotent)
|
|
||||||
* - Visual: Green - represents creation, addition, growth
|
|
||||||
* - Psychology: Positive action, new resource creation
|
|
||||||
* - Use cases: Create resource, submit form, trigger action
|
|
||||||
* - HTTP: Creates new resource, may have side effects
|
|
||||||
*
|
|
||||||
* @param {'PUT'} PUT - Update/Replace operations (Not safe, Idempotent)
|
|
||||||
* - Visual: Amber/Orange - represents modification, change
|
|
||||||
* - Psychology: Caution, transformation, state change
|
|
||||||
* - Use cases: Update entire resource, replace content
|
|
||||||
* - HTTP: Idempotent, full resource update
|
|
||||||
*
|
|
||||||
* @param {'PATCH'} PATCH - Partial Update operations (Not safe, Not idempotent)
|
|
||||||
* - Visual: Purple - represents refinement, partial change
|
|
||||||
* - Psychology: Precision, targeted modification
|
|
||||||
* - Use cases: Update specific fields, partial resource modification
|
|
||||||
* - HTTP: Partial update, may not be idempotent
|
|
||||||
*
|
|
||||||
* @param {'DELETE'} DELETE - Delete operations (Not safe, Idempotent)
|
|
||||||
* - Visual: Red - represents removal, destruction, danger
|
|
||||||
* - Psychology: Warning, irreversible action, stop
|
|
||||||
* - Use cases: Remove resource, deactivate, destroy data
|
|
||||||
* - HTTP: Idempotent, removes resource
|
|
||||||
*
|
|
||||||
* ## Size Variants
|
|
||||||
*
|
|
||||||
* @param {'sm'} sm - Small size for inline usage (px-2 py-0.5, text-xs)
|
|
||||||
* @param {'md'} md - Medium size for standard usage (px-3 py-1, text-xs) [default]
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* - **Rounded corners**: Modern, friendly appearance
|
|
||||||
* - **Semi-transparent backgrounds**: Integrates with dark theme
|
|
||||||
* - **Solid borders**: Adds definition and structure
|
|
||||||
* - **Bold text**: Ensures readability and emphasis
|
|
||||||
* - **Consistent sizing**: Aligns with other badges in the design system
|
|
||||||
*
|
|
||||||
* Color Opacity Strategy:
|
|
||||||
* - Background: 20% opacity for subtle presence
|
|
||||||
* - Border: 40% opacity for clear definition
|
|
||||||
* - Text: 100% (400 weight) for maximum readability
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // API Endpoint Documentation
|
|
||||||
* <MethodBadge method="GET" /> /api/users
|
|
||||||
* <MethodBadge method="POST" /> /api/users
|
|
||||||
*
|
|
||||||
* // With size variants
|
|
||||||
* <MethodBadge method="DELETE" size="sm" />
|
|
||||||
* <MethodBadge method="PUT" size="md" />
|
|
||||||
*
|
|
||||||
* // In endpoint cards
|
|
||||||
* <div className="flex items-center gap-2">
|
|
||||||
* <MethodBadge method="POST" />
|
|
||||||
* <code>/api/text-to-image</code>
|
|
||||||
* </div>
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Industry Standards Reference
|
|
||||||
*
|
|
||||||
* This color scheme aligns with popular API documentation tools:
|
|
||||||
* - Swagger UI: Blue (GET), Green (POST), Orange (PUT), Red (DELETE)
|
|
||||||
* - Postman: Similar color conventions
|
|
||||||
* - GitHub API Docs: Consistent method color coding
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <MethodBadge method="POST" size="md" />
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP method types following REST conventions
|
|
||||||
*/
|
|
||||||
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size variant for the badge
|
|
||||||
*/
|
|
||||||
export type MethodBadgeSize = 'sm' | 'md';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the MethodBadge component
|
|
||||||
*/
|
|
||||||
export interface MethodBadgeProps {
|
|
||||||
/** The HTTP method to display */
|
|
||||||
method: HttpMethod;
|
|
||||||
/** Size variant (default: 'md') */
|
|
||||||
size?: MethodBadgeSize;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Color system mapping HTTP methods to semantic colors
|
|
||||||
* Follows industry standards for API documentation
|
|
||||||
*/
|
|
||||||
const methodStyles: Record<HttpMethod, string> = {
|
|
||||||
GET: 'bg-cyan-600/20 text-cyan-400 border-cyan-500/40',
|
|
||||||
POST: 'bg-green-600/20 text-green-400 border-green-500/40',
|
|
||||||
PUT: 'bg-amber-600/20 text-amber-400 border-amber-500/40',
|
|
||||||
PATCH: 'bg-purple-600/20 text-purple-400 border-purple-500/40',
|
|
||||||
DELETE: 'bg-red-600/20 text-red-400 border-red-500/40',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size system mapping size variant to padding and font size
|
|
||||||
*/
|
|
||||||
const sizeStyles: Record<MethodBadgeSize, string> = {
|
|
||||||
sm: 'px-2 py-0.5 text-xs',
|
|
||||||
md: 'px-3 py-1 text-xs',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessibility labels describing the HTTP method's purpose
|
|
||||||
*/
|
|
||||||
const methodLabels: Record<HttpMethod, string> = {
|
|
||||||
GET: 'GET request - retrieve data',
|
|
||||||
POST: 'POST request - create resource',
|
|
||||||
PUT: 'PUT request - update resource',
|
|
||||||
PATCH: 'PATCH request - partial update',
|
|
||||||
DELETE: 'DELETE request - remove resource',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MethodBadge = ({
|
|
||||||
method,
|
|
||||||
size = 'md',
|
|
||||||
className = '',
|
|
||||||
}: MethodBadgeProps) => {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className={`
|
|
||||||
inline-flex items-center justify-center
|
|
||||||
rounded border font-bold
|
|
||||||
${methodStyles[method]}
|
|
||||||
${sizeStyles[size]}
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
role="status"
|
|
||||||
aria-label={methodLabels[method]}
|
|
||||||
>
|
|
||||||
{method}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,244 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ResponseBlock Component
|
|
||||||
*
|
|
||||||
* A semantic display block for API response examples with status indicators.
|
|
||||||
* Visually differentiates success and error responses through color psychology.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Status Communication**: Color instantly conveys response type
|
|
||||||
* - Green = Success (2xx responses, positive outcomes)
|
|
||||||
* - Red = Error (4xx/5xx responses, failures)
|
|
||||||
* - Consistent with universal traffic light conventions
|
|
||||||
*
|
|
||||||
* 2. **Information Layering**: Progressive disclosure of details
|
|
||||||
* - Status badge in top-right for immediate recognition
|
|
||||||
* - Optional title provides context
|
|
||||||
* - Content area for actual response data
|
|
||||||
* - Layered styling adds depth without clutter
|
|
||||||
*
|
|
||||||
* 3. **Visual Feedback**: Subtle effects reinforce status
|
|
||||||
* - Background tint matches status color
|
|
||||||
* - Border emphasis adds structure
|
|
||||||
* - Soft shadow/glow creates depth
|
|
||||||
* - All at low opacity to avoid overwhelming
|
|
||||||
*
|
|
||||||
* ## Status Semantics
|
|
||||||
*
|
|
||||||
* @param {'success'} success - Successful API responses (2xx status codes)
|
|
||||||
* - Visual: Green color palette (green-500)
|
|
||||||
* - Psychology: Positive, correct, achieved
|
|
||||||
* - Use cases: 200 OK, 201 Created, 204 No Content
|
|
||||||
* - Styling: bg-green-500/5, border-green-500/30, shadow-green-500/10
|
|
||||||
* - Badge: "✓ 200 Success", "✓ 201 Created"
|
|
||||||
*
|
|
||||||
* @param {'error'} error - Error API responses (4xx/5xx status codes)
|
|
||||||
* - Visual: Red color palette (red-500)
|
|
||||||
* - Psychology: Warning, problem, attention needed
|
|
||||||
* - Use cases: 400 Bad Request, 401 Unauthorized, 500 Server Error
|
|
||||||
* - Styling: bg-red-500/5, border-red-500/30, shadow-red-500/10
|
|
||||||
* - Badge: "✗ 400 Error", "✗ 500 Error"
|
|
||||||
*
|
|
||||||
* ## Opacity Strategy
|
|
||||||
*
|
|
||||||
* Three-tier opacity system:
|
|
||||||
* - Background: /5 (5% opacity) - Subtle tint, doesn't obscure content
|
|
||||||
* - Border: /30 (30% opacity) - Clear definition, visible structure
|
|
||||||
* - Shadow: /10 (10% opacity) - Soft depth, enhances without distraction
|
|
||||||
*
|
|
||||||
* This creates:
|
|
||||||
* - Cohesive visual grouping
|
|
||||||
* - Clear status communication
|
|
||||||
* - Maintains content readability
|
|
||||||
* - Professional, polished appearance
|
|
||||||
*
|
|
||||||
* ## Layout Structure
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* ┌─────────────────────────────────────┐
|
|
||||||
* │ [STATUS BADGE] ←──┤ Absolute positioned
|
|
||||||
* │ Optional Title │
|
|
||||||
* │ (if provided) │
|
|
||||||
* │ │
|
|
||||||
* │ <pre><code> │
|
|
||||||
* │ Response content │
|
|
||||||
* │ ... │
|
|
||||||
* │ </code></pre> │
|
|
||||||
* └─────────────────────────────────────┘
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Positioning Strategy:
|
|
||||||
* - Container: relative positioning context
|
|
||||||
* - Badge: absolute top-3 right-3 (float in top-right)
|
|
||||||
* - Content: mt-6 when badge present (clear space for badge)
|
|
||||||
* - Title: mb-3 if provided (separate from content)
|
|
||||||
*
|
|
||||||
* ## Typography & Content
|
|
||||||
*
|
|
||||||
* Title (optional):
|
|
||||||
* - text-sm: Small, not competing with main content
|
|
||||||
* - font-semibold: Subtle emphasis
|
|
||||||
* - text-gray-300: Readable but secondary
|
|
||||||
* - Purpose: Labels response type, adds context
|
|
||||||
*
|
|
||||||
* Response Content:
|
|
||||||
* - text-xs: Appropriate for code samples
|
|
||||||
* - text-gray-300: High contrast on dark background
|
|
||||||
* - font-mono (implicit in <code>): Code appearance
|
|
||||||
* - overflow-x-auto: Handles long lines gracefully
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Success response with title
|
|
||||||
* <ResponseBlock
|
|
||||||
* status="success"
|
|
||||||
* statusCode={200}
|
|
||||||
* title="Expected Response:"
|
|
||||||
* content={`{
|
|
||||||
* "success": true,
|
|
||||||
* "data": { ... }
|
|
||||||
* }`}
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Error response without title
|
|
||||||
* <ResponseBlock
|
|
||||||
* status="error"
|
|
||||||
* statusCode={401}
|
|
||||||
* content={`{
|
|
||||||
* "error": "Unauthorized",
|
|
||||||
* "message": "Invalid API key"
|
|
||||||
* }`}
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* // Custom status label
|
|
||||||
* <ResponseBlock
|
|
||||||
* status="success"
|
|
||||||
* statusCode={201}
|
|
||||||
* statusLabel="✓ 201 Created"
|
|
||||||
* content="{ ... }"
|
|
||||||
* />
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Content Guidelines
|
|
||||||
*
|
|
||||||
* Response Content:
|
|
||||||
* - Use actual JSON/text from your API
|
|
||||||
* - Format with proper indentation (2 or 4 spaces)
|
|
||||||
* - Include realistic data (not just placeholders)
|
|
||||||
* - Show relevant fields (omit excessive detail)
|
|
||||||
* - Keep under 20-30 lines for readability
|
|
||||||
*
|
|
||||||
* Status Labels:
|
|
||||||
* - Include status code (200, 400, etc.)
|
|
||||||
* - Add descriptive text (Success, Error, Created)
|
|
||||||
* - Use checkmark (✓) for success
|
|
||||||
* - Use X (✗) for errors
|
|
||||||
* - Keep concise (2-3 words max)
|
|
||||||
*
|
|
||||||
* ## Accessibility
|
|
||||||
*
|
|
||||||
* - Semantic HTML structure (<pre><code>)
|
|
||||||
* - Color is supplementary (text + symbols)
|
|
||||||
* - High contrast text colors
|
|
||||||
* - StatusBadge includes aria-label
|
|
||||||
* - Proper heading hierarchy if title used
|
|
||||||
* - Scrollable overflow for long content
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The ResponseBlock creates:
|
|
||||||
* - Immediate status recognition through color
|
|
||||||
* - Professional code presentation
|
|
||||||
* - Clear example/documentation relationship
|
|
||||||
* - Consistent pattern across all API docs
|
|
||||||
* - Supports learn-by-example documentation style
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <ResponseBlock
|
|
||||||
* status="success"
|
|
||||||
* statusCode={200}
|
|
||||||
* title="Success Response"
|
|
||||||
* content={jsonString}
|
|
||||||
* />
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { StatusBadge, StatusType } from './StatusBadge';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the ResponseBlock component
|
|
||||||
*/
|
|
||||||
export interface ResponseBlockProps {
|
|
||||||
/** Status type determining color scheme */
|
|
||||||
status: Extract<StatusType, 'success' | 'error'>;
|
|
||||||
/** HTTP status code (e.g., 200, 400, 500) */
|
|
||||||
statusCode: number;
|
|
||||||
/** The response content to display (typically JSON) */
|
|
||||||
content: string;
|
|
||||||
/** Optional title above the response */
|
|
||||||
title?: string;
|
|
||||||
/** Optional custom status label (default: auto-generated from statusCode) */
|
|
||||||
statusLabel?: string;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status styles mapping status type to background, border, and shadow colors
|
|
||||||
*/
|
|
||||||
const statusStyles = {
|
|
||||||
success: 'bg-green-500/5 border-green-500/30 shadow-lg shadow-green-500/10',
|
|
||||||
error: 'bg-red-500/5 border-red-500/30 shadow-lg shadow-red-500/10',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate default status label from code and status
|
|
||||||
*/
|
|
||||||
const getDefaultStatusLabel = (code: number, status: 'success' | 'error'): string => {
|
|
||||||
const symbol = status === 'success' ? '✓' : '✗';
|
|
||||||
const text = status === 'success' ? 'Success' : 'Error';
|
|
||||||
return `${symbol} ${code} ${text}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ResponseBlock = ({
|
|
||||||
status,
|
|
||||||
statusCode,
|
|
||||||
content,
|
|
||||||
title,
|
|
||||||
statusLabel,
|
|
||||||
className = '',
|
|
||||||
}: ResponseBlockProps) => {
|
|
||||||
const label = statusLabel || getDefaultStatusLabel(statusCode, status);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`
|
|
||||||
relative
|
|
||||||
p-4
|
|
||||||
border rounded-xl
|
|
||||||
${statusStyles[status]}
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{/* Status Badge - Floating Top Right */}
|
|
||||||
<div className="absolute top-3 right-3">
|
|
||||||
<StatusBadge status={status} size="sm">
|
|
||||||
{label}
|
|
||||||
</StatusBadge>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Optional Title */}
|
|
||||||
{title && (
|
|
||||||
<p className="text-sm font-semibold text-gray-300 mb-3">{title}</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Response Content */}
|
|
||||||
<pre className={`text-xs text-gray-300 overflow-x-auto ${title || statusLabel ? 'mt-6' : ''}`}>
|
|
||||||
<code>{content}</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SectionHeader Component
|
|
||||||
*
|
|
||||||
* Consistent heading elements for organizing documentation content into hierarchical sections.
|
|
||||||
* Provides visual rhythm and structure throughout documentation pages.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Visual Hierarchy**: Size and weight indicate content importance
|
|
||||||
* - Level 2 (h2): Major sections, primary content divisions
|
|
||||||
* - Level 3 (h3): Subsections, supporting details
|
|
||||||
* - Consistent styling creates predictable structure
|
|
||||||
*
|
|
||||||
* 2. **Semantic HTML**: Proper heading levels for accessibility
|
|
||||||
* - Uses correct HTML heading tags (h2, h3)
|
|
||||||
* - Supports screen readers and document outline
|
|
||||||
* - Enables Table of Contents generation
|
|
||||||
* - Critical for SEO and document structure
|
|
||||||
*
|
|
||||||
* 3. **Spacing System**: Establishes vertical rhythm
|
|
||||||
* - Top margin separates from previous content
|
|
||||||
* - Bottom margin creates breathing room before content
|
|
||||||
* - Consistent spacing improves scannability
|
|
||||||
*
|
|
||||||
* ## Heading Level Semantics
|
|
||||||
*
|
|
||||||
* @param {2} level2 - Major section headings (h2)
|
|
||||||
* - Visual: text-3xl (30px), font-bold, text-white
|
|
||||||
* - Spacing: mb-4 (16px) below, mb-6 (24px) for sections with mb-12
|
|
||||||
* - Psychology: Primary divisions, main topics
|
|
||||||
* - Use cases: "Overview", "Parameters", "Response", "Error Codes"
|
|
||||||
* - Hierarchy: Second level (after page h1/Hero)
|
|
||||||
* - SEO: Key topic signals for search engines
|
|
||||||
*
|
|
||||||
* @param {3} level3 - Subsection headings (h3)
|
|
||||||
* - Visual: text-xl (20px), font-semibold, text-white
|
|
||||||
* - Spacing: mb-3 (12px) below, mb-4 (16px) for subsections with mb-8
|
|
||||||
* - Psychology: Supporting topics, detailed breakdowns
|
|
||||||
* - Use cases: "Key Types", "Creating Keys", "Rate Limits"
|
|
||||||
* - Hierarchy: Third level (under h2 sections)
|
|
||||||
* - SEO: Supporting detail signals
|
|
||||||
*
|
|
||||||
* ## Typography Scale Reasoning
|
|
||||||
*
|
|
||||||
* Level 2 (text-3xl / 30px):
|
|
||||||
* - Large enough to clearly mark major sections
|
|
||||||
* - Smaller than Hero (36-48px) to maintain hierarchy
|
|
||||||
* - Bold weight adds emphasis and structure
|
|
||||||
* - White color ensures readability and prominence
|
|
||||||
*
|
|
||||||
* Level 3 (text-xl / 20px):
|
|
||||||
* - Noticeably smaller than h2, maintaining hierarchy
|
|
||||||
* - Semibold (600) instead of bold provides subtle distinction
|
|
||||||
* - Large enough to serve as clear subsection marker
|
|
||||||
* - Balances prominence with subordinate role
|
|
||||||
*
|
|
||||||
* ## Spacing Philosophy
|
|
||||||
*
|
|
||||||
* Bottom Margin Strategy:
|
|
||||||
* - h2: mb-4 or mb-6 depending on section context
|
|
||||||
* - mb-4 for tighter sections with nearby content
|
|
||||||
* - mb-6 for major sections introducing substantial content
|
|
||||||
* - h3: mb-3 or mb-4 depending on subsection context
|
|
||||||
* - Smaller margins reflect subordinate hierarchy
|
|
||||||
* - Still provides clear separation from content
|
|
||||||
*
|
|
||||||
* ## Anchor Link Support
|
|
||||||
*
|
|
||||||
* The `id` prop enables:
|
|
||||||
* - Direct linking to specific sections (#section-name)
|
|
||||||
* - Table of Contents navigation
|
|
||||||
* - Deep linking from external sources
|
|
||||||
* - Browser history for scrolled positions
|
|
||||||
*
|
|
||||||
* ID Naming Convention:
|
|
||||||
* - Use kebab-case (lowercase with hyphens)
|
|
||||||
* - Descriptive and unique per page
|
|
||||||
* - Example: "api-keys", "rate-limits", "error-handling"
|
|
||||||
*
|
|
||||||
* ## Accessibility Features
|
|
||||||
*
|
|
||||||
* - Semantic HTML heading levels (h2, h3)
|
|
||||||
* - Proper document outline structure
|
|
||||||
* - Sufficient color contrast (white on dark)
|
|
||||||
* - Clear visual distinction between levels
|
|
||||||
* - Screen reader friendly navigation
|
|
||||||
* - Keyboard accessible anchor links
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // Major section heading (h2)
|
|
||||||
* <SectionHeader level={2} id="overview">
|
|
||||||
* Overview
|
|
||||||
* </SectionHeader>
|
|
||||||
*
|
|
||||||
* // Subsection heading (h3)
|
|
||||||
* <SectionHeader level={3} id="key-types">
|
|
||||||
* Key Types
|
|
||||||
* </SectionHeader>
|
|
||||||
*
|
|
||||||
* // Custom spacing with className
|
|
||||||
* <SectionHeader level={2} id="parameters" className="mb-6">
|
|
||||||
* Parameters
|
|
||||||
* </SectionHeader>
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Content Guidelines
|
|
||||||
*
|
|
||||||
* Level 2 Headings:
|
|
||||||
* - 1-3 words ideal (concise and scannable)
|
|
||||||
* - Sentence case (capitalize first word)
|
|
||||||
* - Action-oriented or descriptive nouns
|
|
||||||
* - Examples: "Quick Start", "Authentication", "Rate Limits"
|
|
||||||
*
|
|
||||||
* Level 3 Headings:
|
|
||||||
* - 1-4 words, slightly more descriptive
|
|
||||||
* - Sentence case
|
|
||||||
* - Specific subtopics or steps
|
|
||||||
* - Examples: "Creating Keys", "Using API Keys", "Security Best Practices"
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The header system creates a visual rhythm that:
|
|
||||||
* - Guides the eye through content naturally
|
|
||||||
* - Breaks long pages into digestible chunks
|
|
||||||
* - Signals importance through size and weight
|
|
||||||
* - Maintains consistency across all documentation
|
|
||||||
* - Supports quick scanning and navigation
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <SectionHeader level={2} id="getting-started">
|
|
||||||
* Getting Started
|
|
||||||
* </SectionHeader>
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Heading level determining HTML tag and visual styling
|
|
||||||
*/
|
|
||||||
export type SectionHeaderLevel = 2 | 3;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the SectionHeader component
|
|
||||||
*/
|
|
||||||
export interface SectionHeaderProps {
|
|
||||||
/** Heading level (h2 or h3) for semantic structure */
|
|
||||||
level: SectionHeaderLevel;
|
|
||||||
/** The heading text content */
|
|
||||||
children: ReactNode;
|
|
||||||
/** Optional ID for anchor linking and table of contents */
|
|
||||||
id?: string;
|
|
||||||
/** Optional CSS class name for additional styling (e.g., custom margins) */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Typography styles mapping heading level to text size and weight
|
|
||||||
*/
|
|
||||||
const levelStyles: Record<SectionHeaderLevel, string> = {
|
|
||||||
2: 'text-3xl font-bold',
|
|
||||||
3: 'text-xl font-semibold',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default spacing system for bottom margins
|
|
||||||
*/
|
|
||||||
const defaultSpacing: Record<SectionHeaderLevel, string> = {
|
|
||||||
2: 'mb-4',
|
|
||||||
3: 'mb-3',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SectionHeader = ({
|
|
||||||
level,
|
|
||||||
children,
|
|
||||||
id,
|
|
||||||
className,
|
|
||||||
}: SectionHeaderProps) => {
|
|
||||||
const Tag = `h${level}` as 'h2' | 'h3';
|
|
||||||
const spacing = className?.includes('mb-') ? '' : defaultSpacing[level];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tag
|
|
||||||
id={id}
|
|
||||||
className={`
|
|
||||||
${levelStyles[level]}
|
|
||||||
text-white
|
|
||||||
${spacing}
|
|
||||||
${className || ''}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* StatusBadge Component
|
|
||||||
*
|
|
||||||
* A semantic status indicator that uses color psychology and consistent styling
|
|
||||||
* to communicate state, result, or severity across documentation.
|
|
||||||
*
|
|
||||||
* ## Design Principles
|
|
||||||
*
|
|
||||||
* 1. **Semantic Color System**: Colors convey meaning, not just decoration
|
|
||||||
* - Uses consistent color mapping across all documentation
|
|
||||||
* - Follows industry standards (green = success, red = error, etc.)
|
|
||||||
*
|
|
||||||
* 2. **Visual Hierarchy**: Small, unobtrusive elements that enhance readability
|
|
||||||
* - Pill-shaped design for friendly, modern appearance
|
|
||||||
* - Subtle backgrounds with semi-transparent colors
|
|
||||||
* - Border emphasis for definition without heaviness
|
|
||||||
*
|
|
||||||
* 3. **Accessibility**: Meets WCAG 2.1 AA standards
|
|
||||||
* - Sufficient color contrast ratios
|
|
||||||
* - Semantic HTML with aria-label
|
|
||||||
* - Text labels (never color-only communication)
|
|
||||||
*
|
|
||||||
* ## Semantic Status Values
|
|
||||||
*
|
|
||||||
* @param {'success'} success - Positive outcomes, completed actions, 2xx HTTP responses
|
|
||||||
* - Visual: Green color palette
|
|
||||||
* - Psychology: Achievement, correctness, go-ahead signal
|
|
||||||
* - Use cases: "200 Success", "Completed", "Active", "✓ Passed"
|
|
||||||
*
|
|
||||||
* @param {'info'} info - Neutral information, documentation, helpful tips
|
|
||||||
* - Visual: Blue/Cyan color palette
|
|
||||||
* - Psychology: Calm, trustworthy, educational
|
|
||||||
* - Use cases: "Beta", "New", "Info", "Note"
|
|
||||||
*
|
|
||||||
* @param {'warning'} warning - Caution, deprecation, rate limits, 4xx client errors
|
|
||||||
* - Visual: Amber/Orange color palette
|
|
||||||
* - Psychology: Attention needed, proceed with caution
|
|
||||||
* - Use cases: "429 Rate Limit", "Deprecated", "Warning", "Limited"
|
|
||||||
*
|
|
||||||
* @param {'error'} error - Failures, critical issues, 5xx server errors, security alerts
|
|
||||||
* - Visual: Red color palette
|
|
||||||
* - Psychology: Stop, danger, requires immediate attention
|
|
||||||
* - Use cases: "500 Error", "Failed", "Critical", "Blocked"
|
|
||||||
*
|
|
||||||
* @param {'neutral'} neutral - Default state, placeholder, unspecified
|
|
||||||
* - Visual: Slate/Gray color palette
|
|
||||||
* - Psychology: Neutral, balanced, inactive
|
|
||||||
* - Use cases: "Pending", "Unknown", "Draft", "Inactive"
|
|
||||||
*
|
|
||||||
* ## Size Variants
|
|
||||||
*
|
|
||||||
* @param {'sm'} sm - Small size for inline usage, tight spaces
|
|
||||||
* - Font: text-xs
|
|
||||||
* - Padding: px-2 py-0.5
|
|
||||||
* - Use: Inline with text, table cells, compact layouts
|
|
||||||
*
|
|
||||||
* @param {'md'} md - Medium size (default) for standard usage
|
|
||||||
* - Font: text-xs
|
|
||||||
* - Padding: px-3 py-1
|
|
||||||
* - Use: General purpose, code examples, section markers
|
|
||||||
*
|
|
||||||
* ## Visual Language
|
|
||||||
*
|
|
||||||
* The badge uses a rounded-full design (pill shape) which:
|
|
||||||
* - Creates visual consistency with other UI elements (buttons, tags)
|
|
||||||
* - Feels modern and friendly (vs. harsh rectangular badges)
|
|
||||||
* - Groups related information visually
|
|
||||||
* - Works well at small sizes without appearing cramped
|
|
||||||
*
|
|
||||||
* Color opacity levels (X/20 bg, X/40 border):
|
|
||||||
* - Background: 20% opacity for subtle presence
|
|
||||||
* - Border: 40% opacity for definition
|
|
||||||
* - Text: 100% for maximum readability
|
|
||||||
*
|
|
||||||
* ## Usage Examples
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* // HTTP Status Codes
|
|
||||||
* <StatusBadge status="success" size="sm">200 OK</StatusBadge>
|
|
||||||
* <StatusBadge status="error" size="sm">500 Error</StatusBadge>
|
|
||||||
*
|
|
||||||
* // API States
|
|
||||||
* <StatusBadge status="info">Beta</StatusBadge>
|
|
||||||
* <StatusBadge status="warning">Deprecated</StatusBadge>
|
|
||||||
*
|
|
||||||
* // System Status
|
|
||||||
* <StatusBadge status="success">✓ Active</StatusBadge>
|
|
||||||
* <StatusBadge status="neutral">Pending</StatusBadge>
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @component
|
|
||||||
* @example
|
|
||||||
* <StatusBadge status="success" size="md">200 Success</StatusBadge>
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Semantic status type representing the meaning/severity of the badge
|
|
||||||
*/
|
|
||||||
export type StatusType = 'success' | 'info' | 'warning' | 'error' | 'neutral';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size variant for the badge
|
|
||||||
*/
|
|
||||||
export type StatusSize = 'sm' | 'md';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for the StatusBadge component
|
|
||||||
*/
|
|
||||||
export interface StatusBadgeProps {
|
|
||||||
/** The semantic status that determines color and meaning */
|
|
||||||
status: StatusType;
|
|
||||||
/** The content to display inside the badge */
|
|
||||||
children: ReactNode;
|
|
||||||
/** Size variant (default: 'md') */
|
|
||||||
size?: StatusSize;
|
|
||||||
/** Optional CSS class name for additional styling */
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Color system mapping semantic status to Tailwind color utilities
|
|
||||||
* Follows the established design system color palette
|
|
||||||
*/
|
|
||||||
const statusStyles: Record<StatusType, string> = {
|
|
||||||
success: 'bg-green-500/20 text-green-400 border border-green-500/40',
|
|
||||||
info: 'bg-cyan-500/20 text-cyan-400 border border-cyan-500/40',
|
|
||||||
warning: 'bg-amber-500/20 text-amber-400 border border-amber-500/40',
|
|
||||||
error: 'bg-red-500/20 text-red-400 border border-red-500/40',
|
|
||||||
neutral: 'bg-slate-500/20 text-slate-400 border border-slate-500/40',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size system mapping size variant to padding and font size
|
|
||||||
*/
|
|
||||||
const sizeStyles: Record<StatusSize, string> = {
|
|
||||||
sm: 'px-2 py-0.5 text-xs',
|
|
||||||
md: 'px-3 py-1 text-xs',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Human-readable labels for screen readers
|
|
||||||
*/
|
|
||||||
const statusLabels: Record<StatusType, string> = {
|
|
||||||
success: 'Success status',
|
|
||||||
info: 'Information status',
|
|
||||||
warning: 'Warning status',
|
|
||||||
error: 'Error status',
|
|
||||||
neutral: 'Neutral status',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const StatusBadge = ({
|
|
||||||
status,
|
|
||||||
children,
|
|
||||||
size = 'md',
|
|
||||||
className = '',
|
|
||||||
}: StatusBadgeProps) => {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className={`
|
|
||||||
inline-flex items-center justify-center
|
|
||||||
rounded-full font-bold
|
|
||||||
${statusStyles[status]}
|
|
||||||
${sizeStyles[size]}
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
role="status"
|
|
||||||
aria-label={statusLabels[status]}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,176 +0,0 @@
|
||||||
/**
|
|
||||||
* Documentation Block Components
|
|
||||||
*
|
|
||||||
* A comprehensive library of reusable, semantic components for building
|
|
||||||
* consistent, professional API documentation.
|
|
||||||
*
|
|
||||||
* ## Design System Overview
|
|
||||||
*
|
|
||||||
* This collection establishes a visual language for documentation through:
|
|
||||||
* - **Semantic Color System**: Enum-based color values with clear meanings
|
|
||||||
* - **Consistent Typography**: Hierarchical text sizing and weights
|
|
||||||
* - **Responsive Layouts**: Mobile-first, adaptive components
|
|
||||||
* - **Accessibility First**: WCAG 2.1 AA compliance throughout
|
|
||||||
* - **Comprehensive Documentation**: Every component fully documented
|
|
||||||
*
|
|
||||||
* ## Component Categories
|
|
||||||
*
|
|
||||||
* ### Status & Indicators
|
|
||||||
* - **StatusBadge**: Semantic status indicators (success, info, warning, error, neutral)
|
|
||||||
* - **MethodBadge**: HTTP method badges (GET, POST, PUT, PATCH, DELETE)
|
|
||||||
*
|
|
||||||
* ### Typography & Content
|
|
||||||
* - **Hero**: Page-level headings with title and subtitle
|
|
||||||
* - **SectionHeader**: Hierarchical section headings (h2, h3)
|
|
||||||
* - **InlineCode**: Semantic inline code elements
|
|
||||||
*
|
|
||||||
* ### API Documentation
|
|
||||||
* - **EndpointCard**: Structured API endpoint display
|
|
||||||
* - **ResponseBlock**: API response examples with status visualization
|
|
||||||
*
|
|
||||||
* ### Navigation
|
|
||||||
* - **LinkCard**: Interactive navigation cards with accent colors
|
|
||||||
* - **LinkCardGrid**: Responsive grid layout for link cards
|
|
||||||
*
|
|
||||||
* ## Usage Philosophy
|
|
||||||
*
|
|
||||||
* These components follow key principles:
|
|
||||||
*
|
|
||||||
* 1. **Composition over Configuration**
|
|
||||||
* - Small, focused components combine to create pages
|
|
||||||
* - Each component does one thing well
|
|
||||||
* - Easy to understand and maintain
|
|
||||||
*
|
|
||||||
* 2. **Semantic Props**
|
|
||||||
* - Enum values over raw values (accent='primary' not color='#8b5cf6')
|
|
||||||
* - Meaning-based names (status='success' not color='green')
|
|
||||||
* - Self-documenting API
|
|
||||||
*
|
|
||||||
* 3. **Consistent Patterns**
|
|
||||||
* - Similar props across components (className, children)
|
|
||||||
* - Predictable behavior and styling
|
|
||||||
* - Easy to learn and use
|
|
||||||
*
|
|
||||||
* 4. **Accessibility Built-in**
|
|
||||||
* - Semantic HTML throughout
|
|
||||||
* - ARIA labels where appropriate
|
|
||||||
* - Keyboard navigation support
|
|
||||||
* - Sufficient color contrast
|
|
||||||
*
|
|
||||||
* ## Example: Building a Documentation Page
|
|
||||||
*
|
|
||||||
* ```tsx
|
|
||||||
* import {
|
|
||||||
* Hero,
|
|
||||||
* SectionHeader,
|
|
||||||
* InlineCode,
|
|
||||||
* EndpointCard,
|
|
||||||
* ResponseBlock,
|
|
||||||
* LinkCard,
|
|
||||||
* LinkCardGrid,
|
|
||||||
* } from '@/components/docs/blocks';
|
|
||||||
*
|
|
||||||
* export default function APIPage() {
|
|
||||||
* return (
|
|
||||||
* <>
|
|
||||||
* <Hero
|
|
||||||
* title="Text to Image API"
|
|
||||||
* subtitle="Generate images from text prompts"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* <SectionHeader level={2} id="endpoint">
|
|
||||||
* Endpoint
|
|
||||||
* </SectionHeader>
|
|
||||||
*
|
|
||||||
* <EndpointCard
|
|
||||||
* method="POST"
|
|
||||||
* endpoint="/api/text-to-image"
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* <SectionHeader level={2} id="response">
|
|
||||||
* Response
|
|
||||||
* </SectionHeader>
|
|
||||||
*
|
|
||||||
* <ResponseBlock
|
|
||||||
* status="success"
|
|
||||||
* statusCode={200}
|
|
||||||
* content={responseJSON}
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* <SectionHeader level={2} id="next-steps">
|
|
||||||
* Next Steps
|
|
||||||
* </SectionHeader>
|
|
||||||
*
|
|
||||||
* <LinkCardGrid columns={2}>
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/guides"
|
|
||||||
* title="Guides"
|
|
||||||
* description="Learn best practices"
|
|
||||||
* accent="secondary"
|
|
||||||
* />
|
|
||||||
* <LinkCard
|
|
||||||
* href="/docs/examples"
|
|
||||||
* title="Examples"
|
|
||||||
* description="See code samples"
|
|
||||||
* accent="primary"
|
|
||||||
* />
|
|
||||||
* </LinkCardGrid>
|
|
||||||
* </>
|
|
||||||
* );
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* ## Color System Reference
|
|
||||||
*
|
|
||||||
* ### Semantic Colors
|
|
||||||
* - **primary**: Purple - Brand primary, main content
|
|
||||||
* - **secondary**: Cyan - Complementary, supporting content
|
|
||||||
* - **success**: Green - Positive outcomes, achievements
|
|
||||||
* - **info**: Blue/Cyan - Informational, neutral
|
|
||||||
* - **warning**: Amber - Caution, important notices
|
|
||||||
* - **error**: Red - Errors, problems, danger
|
|
||||||
* - **neutral**: Slate/Gray - Default, inactive
|
|
||||||
*
|
|
||||||
* ### HTTP Method Colors
|
|
||||||
* - **GET**: Cyan - Read operations
|
|
||||||
* - **POST**: Green - Create operations
|
|
||||||
* - **PUT**: Amber - Update operations
|
|
||||||
* - **PATCH**: Purple - Partial update
|
|
||||||
* - **DELETE**: Red - Delete operations
|
|
||||||
*
|
|
||||||
* ## Spacing System
|
|
||||||
*
|
|
||||||
* Consistent spacing creates visual rhythm:
|
|
||||||
* - **sm**: Tight spacing for compact layouts
|
|
||||||
* - **md**: Standard spacing (default for most components)
|
|
||||||
* - **lg**: Generous spacing for major sections
|
|
||||||
*
|
|
||||||
* ## Typography Scale
|
|
||||||
*
|
|
||||||
* Hierarchical text sizing:
|
|
||||||
* - **Hero**: text-4xl → text-6xl (large, page-level)
|
|
||||||
* - **H2**: text-3xl (section headings)
|
|
||||||
* - **H3**: text-xl (subsection headings)
|
|
||||||
* - **Body**: text-base (paragraph text)
|
|
||||||
* - **Small**: text-sm (supporting text)
|
|
||||||
* - **Code**: text-xs (code samples)
|
|
||||||
*
|
|
||||||
* @module blocks
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Status & Indicators
|
|
||||||
export { StatusBadge, type StatusBadgeProps, type StatusType, type StatusSize } from './StatusBadge';
|
|
||||||
export { MethodBadge, type MethodBadgeProps, type HttpMethod, type MethodBadgeSize } from './MethodBadge';
|
|
||||||
|
|
||||||
// Typography & Content
|
|
||||||
export { Hero, type HeroProps, type HeroSize } from './Hero';
|
|
||||||
export { SectionHeader, type SectionHeaderProps, type SectionHeaderLevel } from './SectionHeader';
|
|
||||||
export { InlineCode, type InlineCodeProps, type InlineCodeColor } from './InlineCode';
|
|
||||||
|
|
||||||
// API Documentation
|
|
||||||
export { EndpointCard, type EndpointCardProps } from './EndpointCard';
|
|
||||||
export { ResponseBlock, type ResponseBlockProps } from './ResponseBlock';
|
|
||||||
|
|
||||||
// Navigation
|
|
||||||
export { LinkCard, type LinkCardProps, type LinkCardAccent } from './LinkCard';
|
|
||||||
export { LinkCardGrid, type LinkCardGridProps, type GridColumns } from './LinkCardGrid';
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Documentation Layout - Production Version
|
* Documentation Layout - Final Variant
|
||||||
*
|
*
|
||||||
* Based on Variant A: Clean & Minimal with enhancements
|
* Based on Variant A: Clean & Minimal with enhancements
|
||||||
* This is the production-ready version combining the best aspects
|
* This is the production-ready version combining the best aspects
|
||||||
|
|
@ -26,13 +26,13 @@
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
interface DocsLayoutProps {
|
interface DocsLayoutFinalProps {
|
||||||
sidebar: ReactNode;
|
sidebar: ReactNode;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
toc: ReactNode;
|
toc: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DocsLayout = ({ sidebar, children, toc }: DocsLayoutProps) => {
|
export const DocsLayoutFinal = ({ sidebar, children, toc }: DocsLayoutFinalProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
||||||
{/* Animated gradient background (matching landing page) */}
|
{/* Animated gradient background (matching landing page) */}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Documentation Sidebar - Production Version
|
* Documentation Sidebar - Final Variant
|
||||||
*
|
*
|
||||||
* Based on Variant A with FIXED active states
|
* Based on Variant A with FIXED active states
|
||||||
*
|
*
|
||||||
|
|
@ -33,44 +33,44 @@ interface NavItem {
|
||||||
children?: NavItem[];
|
children?: NavItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DocsSidebarProps {
|
interface DocsSidebarFinalProps {
|
||||||
currentPath: string;
|
currentPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const navigationItems: NavItem[] = [
|
const navigationItems: NavItem[] = [
|
||||||
{
|
{
|
||||||
label: 'Getting Started',
|
label: 'Getting Started',
|
||||||
href: '/docs',
|
href: '/docs/final',
|
||||||
icon: '🚀',
|
icon: '🚀',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'API Reference',
|
label: 'API Reference',
|
||||||
href: '/docs/api',
|
href: '/docs/final/api',
|
||||||
icon: '📚',
|
icon: '📚',
|
||||||
children: [
|
children: [
|
||||||
{ label: 'Text to Image', href: '/docs/api/text-to-image' },
|
{ label: 'Text to Image', href: '/docs/final/api/text-to-image' },
|
||||||
{ label: 'Upload', href: '/docs/api/upload' },
|
{ label: 'Upload', href: '/docs/final/api/upload' },
|
||||||
{ label: 'Images', href: '/docs/api/images' },
|
{ label: 'Images', href: '/docs/final/api/images' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Guides',
|
label: 'Guides',
|
||||||
href: '/docs/guides',
|
href: '/docs/final/guides',
|
||||||
icon: '📖',
|
icon: '📖',
|
||||||
children: [
|
children: [
|
||||||
{ label: 'Authentication', href: '/docs/guides/authentication' },
|
{ label: 'Authentication', href: '/docs/final/guides/authentication' },
|
||||||
{ label: 'Error Handling', href: '/docs/guides/error-handling' },
|
{ label: 'Error Handling', href: '/docs/final/guides/error-handling' },
|
||||||
{ label: 'Rate Limits', href: '/docs/guides/rate-limits' },
|
{ label: 'Rate Limits', href: '/docs/final/guides/rate-limits' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Examples',
|
label: 'Examples',
|
||||||
href: '/docs/examples',
|
href: '/docs/final/examples',
|
||||||
icon: '💡',
|
icon: '💡',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
|
export const DocsSidebarFinal = ({ currentPath }: DocsSidebarFinalProps) => {
|
||||||
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
|
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
|
||||||
|
|
||||||
const toggleSection = (label: string) => {
|
const toggleSection = (label: string) => {
|
||||||
|
|
@ -87,7 +87,7 @@ export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
|
||||||
{/* Logo/Title */}
|
{/* Logo/Title */}
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<h2 className="text-lg font-semibold text-white">Documentation</h2>
|
<h2 className="text-lg font-semibold text-white">Documentation</h2>
|
||||||
<p className="text-xs text-gray-500 mt-1">API Reference</p>
|
<p className="text-xs text-gray-500 mt-1">Final: Production</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navigation Items */}
|
{/* Navigation Items */}
|
||||||
|
|
@ -170,8 +170,8 @@ export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {
|
||||||
<div className="mt-12 pt-6 border-t border-slate-800">
|
<div className="mt-12 pt-6 border-t border-slate-800">
|
||||||
<ul className="space-y-2 text-sm">
|
<ul className="space-y-2 text-sm">
|
||||||
<li>
|
<li>
|
||||||
<a href="/" className="text-gray-500 hover:text-gray-300 transition-colors">
|
<a href="/docs" className="text-gray-500 hover:text-gray-300 transition-colors">
|
||||||
← Back to home
|
← Back to variants
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table of Contents - Production Version
|
* Table of Contents - Final Variant
|
||||||
*
|
*
|
||||||
* Based on Variant A: Clean & Minimal (no changes needed)
|
* Based on Variant A: Clean & Minimal (no changes needed)
|
||||||
*
|
*
|
||||||
|
|
@ -26,11 +26,11 @@ interface TocItem {
|
||||||
level: number;
|
level: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DocsTOCProps {
|
interface DocsTOCFinalProps {
|
||||||
items: TocItem[];
|
items: TocItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DocsTOC = ({ items }: DocsTOCProps) => {
|
export const DocsTOCFinal = ({ items }: DocsTOCFinalProps) => {
|
||||||
const [activeId, setActiveId] = useState<string>('');
|
const [activeId, setActiveId] = useState<string>('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interactive API Widget - Production Version
|
* Interactive API Widget - Final Variant (Redesigned)
|
||||||
*
|
*
|
||||||
* Minimized layout with clean design system:
|
* Minimized layout inspired by Variant C with Final variant design system:
|
||||||
* - No inline API key input (uses DocsApiKeyInput component)
|
* - No inline API key input (uses DocsApiKeyInput component)
|
||||||
* - Clean header with method badge, endpoint, and expand button
|
* - Clean header with method badge, endpoint, and expand button
|
||||||
* - Full-width code snippet area
|
* - Full-width code snippet area
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface InteractiveAPIWidgetProps {
|
interface InteractiveAPIWidgetFinalProps {
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -26,32 +26,32 @@ interface InteractiveAPIWidgetProps {
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Language = 'curl' | 'javascript' | 'python' | 'go' | 'js-sdk' | 'mcp';
|
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||||
|
|
||||||
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||||
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||||
|
|
||||||
const getMethodBadgeStyle = (method: string): string => {
|
const getMethodColor = (method: string): string => {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case 'GET':
|
case 'GET':
|
||||||
return 'bg-cyan-600/20 text-cyan-400 border border-cyan-500/40';
|
return 'from-cyan-500 to-cyan-600';
|
||||||
case 'POST':
|
case 'POST':
|
||||||
return 'bg-green-600/20 text-green-400 border border-green-500/40';
|
return 'from-purple-500 to-purple-600';
|
||||||
case 'PUT':
|
case 'PUT':
|
||||||
return 'bg-amber-600/20 text-amber-400 border border-amber-500/40';
|
return 'from-amber-500 to-amber-600';
|
||||||
case 'DELETE':
|
case 'DELETE':
|
||||||
return 'bg-red-600/20 text-red-400 border border-red-500/40';
|
return 'from-red-500 to-red-600';
|
||||||
default:
|
default:
|
||||||
return 'bg-slate-600/20 text-slate-400 border border-slate-500/40';
|
return 'from-purple-500 to-cyan-500';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const InteractiveAPIWidget = ({
|
export const InteractiveAPIWidgetFinal = ({
|
||||||
endpoint,
|
endpoint,
|
||||||
method,
|
method,
|
||||||
description,
|
description,
|
||||||
parameters = [],
|
parameters = [],
|
||||||
}: InteractiveAPIWidgetProps) => {
|
}: InteractiveAPIWidgetFinalProps) => {
|
||||||
const [language, setLanguage] = useState<Language>('curl');
|
const [language, setLanguage] = useState<Language>('curl');
|
||||||
const [apiKey, setApiKey] = useState('');
|
const [apiKey, setApiKey] = useState('');
|
||||||
const [isExecuting, setIsExecuting] = useState(false);
|
const [isExecuting, setIsExecuting] = useState(false);
|
||||||
|
|
@ -96,33 +96,10 @@ export const InteractiveAPIWidget = ({
|
||||||
};
|
};
|
||||||
}, [parameters]);
|
}, [parameters]);
|
||||||
|
|
||||||
// Get language display name
|
|
||||||
const getLanguageLabel = (lang: Language): string => {
|
|
||||||
switch (lang) {
|
|
||||||
case 'curl':
|
|
||||||
return 'cURL';
|
|
||||||
case 'javascript':
|
|
||||||
return 'JavaScript';
|
|
||||||
case 'python':
|
|
||||||
return 'Python';
|
|
||||||
case 'go':
|
|
||||||
return 'Go';
|
|
||||||
case 'js-sdk':
|
|
||||||
return 'JS SDK';
|
|
||||||
case 'mcp':
|
|
||||||
return 'MCP';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generate code examples
|
// Generate code examples
|
||||||
const generateCode = (): string => {
|
const generateCode = (): string => {
|
||||||
const url = `${API_BASE_URL}${endpoint}`;
|
const url = `${API_BASE_URL}${endpoint}`;
|
||||||
|
|
||||||
// Coming soon placeholders
|
|
||||||
if (language === 'js-sdk' || language === 'mcp') {
|
|
||||||
return `# Coming soon\n# ${getLanguageLabel(language)} integration is under development`;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (language) {
|
switch (language) {
|
||||||
case 'curl':
|
case 'curl':
|
||||||
return `curl -X ${method} "${url}" \\
|
return `curl -X ${method} "${url}" \\
|
||||||
|
|
@ -274,52 +251,59 @@ func main() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Minimized Widget */}
|
{/* Minimized Widget */}
|
||||||
<div className="my-8 bg-slate-900/50 backdrop-blur-sm border border-slate-700/50 rounded-2xl overflow-hidden">
|
<div className="my-8 bg-slate-900/50 backdrop-blur-sm border border-purple-500/30 rounded-2xl overflow-hidden shadow-xl">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-slate-700/50">
|
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-purple-500/30">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className={`px-3 py-1 rounded text-xs font-bold ${getMethodBadgeStyle(method)}`}>
|
<div className={`px-3 py-1.5 rounded-lg bg-gradient-to-r ${getMethodColor(method)} text-white text-sm font-bold shadow-lg`}>
|
||||||
{method}
|
{method}
|
||||||
</div>
|
</div>
|
||||||
<code className="text-sm text-gray-400">{endpoint}</code>
|
<code className="text-sm text-gray-400">{endpoint}</code>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsExpanded(true)}
|
onClick={() => setIsExpanded(true)}
|
||||||
className="flex items-center gap-2 px-4 py-2 bg-cyan-600/10 hover:bg-cyan-600/20 text-cyan-400 rounded-lg transition-all text-sm font-medium border border-cyan-500/30 hover:border-cyan-500/50"
|
className="px-4 py-2 bg-cyan-600/20 hover:bg-cyan-600/30 text-cyan-400 rounded-lg transition-all text-sm font-semibold border border-cyan-500/40 hover:border-cyan-500/60"
|
||||||
>
|
>
|
||||||
<span>⛶</span>
|
⛶ Expand
|
||||||
<span>Expand</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Code Section - Full Width */}
|
{/* Code Section - Full Width */}
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
{/* Language Tabs */}
|
{/* Language Tabs */}
|
||||||
<div className="flex items-center gap-2 mb-4 flex-wrap">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
{(['curl', 'javascript', 'python', 'go', 'js-sdk', 'mcp'] as Language[]).map((lang) => (
|
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => {
|
||||||
<button
|
const colors = ['purple', 'cyan', 'amber', 'purple'];
|
||||||
key={lang}
|
const color = colors[idx];
|
||||||
onClick={() => setLanguage(lang)}
|
return (
|
||||||
className={`px-3 py-1.5 text-xs rounded-lg font-medium transition-all border ${
|
<button
|
||||||
language === lang
|
key={lang}
|
||||||
? 'bg-slate-700 text-white border-slate-600'
|
onClick={() => setLanguage(lang)}
|
||||||
: 'bg-slate-800/50 text-gray-400 border-slate-700/50 hover:border-slate-600 hover:text-gray-300'
|
className={`px-4 py-2 text-sm rounded-xl font-semibold transition-all border ${
|
||||||
}`}
|
language === lang
|
||||||
>
|
? color === 'purple'
|
||||||
{getLanguageLabel(lang)}
|
? 'bg-purple-500/30 text-white border-purple-500/60 shadow-lg shadow-purple-500/20'
|
||||||
</button>
|
: color === 'cyan'
|
||||||
))}
|
? 'bg-cyan-500/30 text-white border-cyan-500/60 shadow-lg shadow-cyan-500/20'
|
||||||
|
: 'bg-amber-500/30 text-white border-amber-500/60 shadow-lg shadow-amber-500/20'
|
||||||
|
: 'bg-slate-800/30 text-gray-400 border-slate-700 hover:border-slate-600 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{lang === 'javascript' ? 'JS' : lang.toUpperCase()}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Code Display */}
|
{/* Code Display */}
|
||||||
<div className="border border-slate-700/50 rounded-xl overflow-hidden">
|
<div className="border border-cyan-500/30 rounded-xl overflow-hidden shadow-lg">
|
||||||
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-slate-700/50">
|
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-cyan-500/20">
|
||||||
<span className="text-xs text-gray-400 font-medium">Code Example</span>
|
<span className="text-xs text-cyan-400 font-semibold">Code Example</span>
|
||||||
<button
|
<button
|
||||||
onClick={copyCode}
|
onClick={copyCode}
|
||||||
className="text-xs text-gray-400 hover:text-white transition-colors font-medium"
|
className="px-3 py-1.5 text-xs bg-purple-600/30 hover:bg-purple-600/50 text-purple-300 rounded-lg transition-all font-semibold"
|
||||||
>
|
>
|
||||||
Copy
|
📋 Copy
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 bg-slate-950/50 max-h-80 overflow-auto">
|
<div className="p-4 bg-slate-950/50 max-h-80 overflow-auto">
|
||||||
|
|
@ -331,43 +315,50 @@ func main() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="flex items-center justify-between px-6 pb-6">
|
<div className="grid grid-cols-2 gap-4 px-6 pb-6">
|
||||||
<button
|
<button
|
||||||
onClick={expandApiKey}
|
onClick={expandApiKey}
|
||||||
className="text-sm text-gray-400 hover:text-white underline-offset-4 hover:underline transition-colors"
|
className="flex items-center gap-2 px-4 py-2.5 bg-slate-800/50 hover:bg-slate-800 border border-slate-700 rounded-lg text-gray-400 hover:text-white text-sm transition-colors"
|
||||||
>
|
>
|
||||||
{apiKey ? 'API Key Set' : 'Enter API Key'}
|
<span>🔑</span>
|
||||||
|
<span>{apiKey ? 'API Key Set' : 'Enter API Key'}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={executeRequest}
|
onClick={executeRequest}
|
||||||
disabled={!apiKey || isExecuting}
|
disabled={!apiKey || isExecuting}
|
||||||
className="px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-sm font-medium transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
className="px-4 py-2.5 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-lg hover:shadow-purple-500/30"
|
||||||
>
|
>
|
||||||
{isExecuting ? 'Executing...' : 'Try It'}
|
{isExecuting ? '⚡ Executing...' : '⚡ Try It'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Inline Response (if any) */}
|
{/* Inline Response (if any) */}
|
||||||
{(response || error) && (
|
{(response || error) && (
|
||||||
<div className="border-t border-slate-700/50 p-6 bg-slate-950/50">
|
<div className="border-t border-purple-500/30 p-6 bg-slate-950/50">
|
||||||
<h4 className="text-sm font-semibold text-white mb-3">
|
<h4 className="text-sm font-semibold text-white mb-3 flex items-center gap-2">
|
||||||
|
<span>📦</span>
|
||||||
Response
|
Response
|
||||||
</h4>
|
</h4>
|
||||||
{error ? (
|
{error ? (
|
||||||
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm">
|
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm shadow-lg shadow-red-500/10">
|
||||||
<p className="font-semibold mb-1">Error</p>
|
<div className="flex items-start gap-2">
|
||||||
<p className="text-xs">{error}</p>
|
<span>⚠️</span>
|
||||||
|
<div>
|
||||||
|
<p className="font-semibold mb-1">Error</p>
|
||||||
|
<p className="text-xs">{error}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={`p-4 rounded-xl ${
|
<div className={`p-4 rounded-xl border ${
|
||||||
isSuccess
|
isSuccess
|
||||||
? 'bg-green-500/5 border border-green-500/30'
|
? 'bg-green-500/5 border-green-500/40 shadow-lg shadow-green-500/10'
|
||||||
: 'bg-slate-800/50 border border-slate-700'
|
: 'bg-slate-800/50 border-slate-700'
|
||||||
}`}>
|
}`}>
|
||||||
{isSuccess && (
|
{isSuccess && (
|
||||||
<div className="flex items-center gap-2 mb-3">
|
<div className="flex items-center gap-2 mb-3">
|
||||||
<span className="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded border border-green-500/40">
|
<span className="px-2 py-1 text-xs bg-green-500/20 text-green-400 rounded-full border border-green-500/40">
|
||||||
200 Success
|
✓ 200 Success
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -383,59 +374,63 @@ func main() {
|
||||||
{/* Expanded Modal */}
|
{/* Expanded Modal */}
|
||||||
{isExpanded && (
|
{isExpanded && (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm">
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm">
|
||||||
<div className="relative w-[90vw] h-[85vh] bg-slate-900 border border-slate-700/50 rounded-2xl shadow-2xl overflow-hidden flex flex-col">
|
<div className="relative w-[90vw] h-[85vh] bg-slate-900 border border-purple-500/30 rounded-2xl shadow-2xl overflow-hidden flex flex-col">
|
||||||
{/* Modal Header */}
|
{/* Modal Header */}
|
||||||
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-slate-700/50">
|
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b border-purple-500/30">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-3">
|
||||||
<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`}>
|
||||||
<div className={`px-3 py-1 rounded text-xs font-bold ${getMethodBadgeStyle(method)}`}>
|
{method}
|
||||||
{method}
|
|
||||||
</div>
|
|
||||||
<code className="text-sm text-gray-400">{endpoint}</code>
|
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-gray-500">•</span>
|
<code className="text-sm text-gray-400">{endpoint}</code>
|
||||||
<p className="text-xs text-gray-500">{description}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsExpanded(false)}
|
onClick={() => setIsExpanded(false)}
|
||||||
className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-gray-400 hover:text-white rounded-lg transition-all text-sm font-medium"
|
className="px-4 py-2 bg-slate-800 hover:bg-slate-700 text-gray-400 hover:text-white rounded-lg transition-all text-sm font-semibold"
|
||||||
>
|
>
|
||||||
Close
|
✕ Close
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Two-Panel Layout */}
|
{/* Two-Panel Layout */}
|
||||||
<div className="grid grid-cols-2 gap-6 p-6 flex-1 overflow-hidden">
|
<div className="grid grid-cols-2 gap-6 p-6 flex-1 overflow-hidden">
|
||||||
{/* Left: Code */}
|
{/* Left: Code */}
|
||||||
<div className="flex flex-col h-full min-h-0">
|
<div className="flex flex-col overflow-hidden">
|
||||||
<div className="flex items-center gap-2 mb-4 flex-wrap min-h-[32px] flex-shrink-0">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
{(['curl', 'javascript', 'python', 'go', 'js-sdk', 'mcp'] as Language[]).map((lang) => (
|
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => {
|
||||||
<button
|
const colors = ['purple', 'cyan', 'amber', 'purple'];
|
||||||
key={lang}
|
const color = colors[idx];
|
||||||
onClick={() => setLanguage(lang)}
|
return (
|
||||||
className={`px-3 py-1.5 text-xs rounded-lg font-medium transition-all border ${
|
<button
|
||||||
language === lang
|
key={lang}
|
||||||
? 'bg-slate-700 text-white border-slate-600'
|
onClick={() => setLanguage(lang)}
|
||||||
: 'bg-slate-800/50 text-gray-400 border-slate-700/50 hover:border-slate-600 hover:text-gray-300'
|
className={`px-4 py-2 text-sm rounded-xl font-semibold transition-all border ${
|
||||||
}`}
|
language === lang
|
||||||
>
|
? color === 'purple'
|
||||||
{getLanguageLabel(lang)}
|
? 'bg-purple-500/30 text-white border-purple-500/60 shadow-lg shadow-purple-500/20'
|
||||||
</button>
|
: color === 'cyan'
|
||||||
))}
|
? 'bg-cyan-500/30 text-white border-cyan-500/60 shadow-lg shadow-cyan-500/20'
|
||||||
|
: 'bg-amber-500/30 text-white border-amber-500/60 shadow-lg shadow-amber-500/20'
|
||||||
|
: 'bg-slate-800/30 text-gray-400 border-slate-700 hover:border-slate-600 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{lang === 'javascript' ? 'JS' : lang.toUpperCase()}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border border-slate-700/50 rounded-xl overflow-hidden flex-1 flex flex-col min-h-0">
|
<div className="border border-cyan-500/30 rounded-xl overflow-hidden shadow-lg flex-1 flex flex-col">
|
||||||
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-slate-700/50 flex-shrink-0">
|
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b border-cyan-500/20">
|
||||||
<span className="text-xs text-gray-400 font-medium">Code Example</span>
|
<span className="text-xs text-cyan-400 font-semibold">Code Example</span>
|
||||||
<button
|
<button
|
||||||
onClick={copyCode}
|
onClick={copyCode}
|
||||||
className="text-xs text-gray-400 hover:text-white transition-colors font-medium"
|
className="px-3 py-1.5 text-xs bg-purple-600/30 hover:bg-purple-600/50 text-purple-300 rounded-lg transition-all font-semibold"
|
||||||
>
|
>
|
||||||
Copy
|
📋 Copy
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 bg-slate-950/50 overflow-auto flex-1 min-h-0">
|
<div className="p-4 bg-slate-950/50 overflow-auto flex-1">
|
||||||
<pre className="text-sm text-gray-300 leading-relaxed">
|
<pre className="text-base text-gray-300 leading-relaxed">
|
||||||
<code>{generateCode()}</code>
|
<code>{generateCode()}</code>
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -443,30 +438,36 @@ func main() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right: Response */}
|
{/* Right: Response */}
|
||||||
<div className="flex flex-col h-full min-h-0">
|
<div className="flex flex-col overflow-hidden">
|
||||||
<h4 className="text-sm font-semibold text-white mb-4 min-h-[32px] flex items-center flex-shrink-0">
|
<h4 className="text-sm font-semibold text-white mb-4 flex items-center gap-2">
|
||||||
|
<span>📦</span>
|
||||||
Response
|
Response
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div className="border border-slate-700/50 rounded-xl overflow-hidden flex-1 flex flex-col min-h-0">
|
<div className="border border-purple-500/30 rounded-xl overflow-hidden shadow-lg flex-1 flex flex-col">
|
||||||
<div className="bg-slate-950/80 px-4 py-3 border-b border-slate-700/50 flex-shrink-0">
|
<div className="bg-slate-950/80 px-4 py-3 border-b border-purple-500/20">
|
||||||
{response && (
|
{response && (
|
||||||
<span
|
<span
|
||||||
className={`inline-flex items-center gap-2 px-3 py-1 rounded text-xs font-bold ${
|
className={`inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-bold ${
|
||||||
response.success
|
response.success
|
||||||
? 'bg-green-500/20 text-green-400 border border-green-500/40'
|
? 'bg-green-500/20 text-green-400 border border-green-500/40 shadow-lg shadow-green-500/10'
|
||||||
: 'bg-red-500/20 text-red-400 border border-red-500/40'
|
: 'bg-red-500/20 text-red-400 border border-red-500/40 shadow-lg shadow-red-500/10'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{response.success ? 'Success' : 'Error'}
|
{response.success ? '✓ Success' : '✕ Error'}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 bg-slate-950/50 overflow-auto flex-1 min-h-0">
|
<div className="p-4 bg-slate-950/50 overflow-auto flex-1">
|
||||||
{error ? (
|
{error ? (
|
||||||
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm">
|
<div className="p-4 bg-red-500/10 border border-red-500/40 rounded-xl text-red-400 text-sm shadow-lg shadow-red-500/10">
|
||||||
<p className="font-semibold mb-1">Error</p>
|
<div className="flex items-start gap-2">
|
||||||
<p className="text-xs">{error}</p>
|
<span className="text-xl">⚠️</span>
|
||||||
|
<div>
|
||||||
|
<p className="font-semibold mb-1">Error</p>
|
||||||
|
<p className="text-xs">{error}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : response ? (
|
) : response ? (
|
||||||
<pre className="text-sm text-gray-300 leading-relaxed">
|
<pre className="text-sm text-gray-300 leading-relaxed">
|
||||||
|
|
@ -475,8 +476,9 @@ func main() {
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center h-full">
|
<div className="flex items-center justify-center h-full">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
|
<p className="text-4xl mb-3">🚀</p>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
Click <strong className="text-white">"Try It"</strong> below to see the response
|
Click <strong className="text-purple-400">"Try It"</strong> below to see the response
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -488,12 +490,17 @@ func main() {
|
||||||
<button
|
<button
|
||||||
onClick={executeRequest}
|
onClick={executeRequest}
|
||||||
disabled={!apiKey || isExecuting}
|
disabled={!apiKey || isExecuting}
|
||||||
className="mt-4 px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-sm font-medium transition-all disabled:opacity-50 disabled:cursor-not-allowed flex-shrink-0"
|
className="mt-4 px-6 py-3 rounded-xl bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-base font-bold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-2xl hover:shadow-purple-500/50"
|
||||||
>
|
>
|
||||||
{isExecuting ? 'Executing...' : 'Try It'}
|
{isExecuting ? '⚡ Executing...' : '⚡ Try It Now'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Footer hint */}
|
||||||
|
<div className="px-6 pb-4 text-center">
|
||||||
|
<p className="text-xs text-gray-500">{description}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Documentation Page Layout Component
|
|
||||||
*
|
|
||||||
* Provides consistent structure for all documentation pages:
|
|
||||||
* - Breadcrumb navigation at top
|
|
||||||
* - Article content area (passed as children)
|
|
||||||
* - Next Steps section at bottom
|
|
||||||
* - Table of Contents sidebar on the right
|
|
||||||
*
|
|
||||||
* Uses ThreeColumnLayout for consistent column structure:
|
|
||||||
* - Center: Article content (max-w-3xl)
|
|
||||||
* - Right: Table of Contents (w-56, hidden xl:block)
|
|
||||||
*
|
|
||||||
* This component extracts common layout patterns from all doc pages,
|
|
||||||
* reducing duplication and ensuring consistency.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* ```tsx
|
|
||||||
* <DocPage
|
|
||||||
* breadcrumbItems={[...]}
|
|
||||||
* tocItems={[...]}
|
|
||||||
* nextSteps={{ description: "...", links: [...] }}
|
|
||||||
* >
|
|
||||||
* <Hero ... />
|
|
||||||
* <section>...</section>
|
|
||||||
* </DocPage>
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
import { Breadcrumb } from '@/components/docs/shared/Breadcrumb';
|
|
||||||
import { DocsTOC } from '@/components/docs/layout/DocsTOC';
|
|
||||||
import { SectionHeader, LinkCard, LinkCardGrid } from '@/components/docs/blocks';
|
|
||||||
import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Next step link card configuration
|
|
||||||
*/
|
|
||||||
export interface NextStepLink {
|
|
||||||
href: string;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
accent: 'primary' | 'secondary' | 'success' | 'warning';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Table of Contents item
|
|
||||||
*/
|
|
||||||
export interface TocItem {
|
|
||||||
id: string;
|
|
||||||
text: string;
|
|
||||||
level: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Breadcrumb navigation item
|
|
||||||
*/
|
|
||||||
export interface BreadcrumbItem {
|
|
||||||
label: string;
|
|
||||||
href?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DocPage component props
|
|
||||||
*/
|
|
||||||
export interface DocPageProps {
|
|
||||||
/** Breadcrumb navigation items (top of page) */
|
|
||||||
breadcrumbItems: BreadcrumbItem[];
|
|
||||||
|
|
||||||
/** Table of contents items (right sidebar) */
|
|
||||||
tocItems: TocItem[];
|
|
||||||
|
|
||||||
/** Next steps section configuration */
|
|
||||||
nextSteps: {
|
|
||||||
/** Optional description text before link cards */
|
|
||||||
description?: string;
|
|
||||||
/** Link cards to display (typically 2) */
|
|
||||||
links: NextStepLink[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Page content (Hero, sections, etc.) */
|
|
||||||
children: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Documentation Page Layout Component
|
|
||||||
*
|
|
||||||
* Wraps documentation content with consistent structure including
|
|
||||||
* breadcrumbs, TOC sidebar, and next steps section.
|
|
||||||
*/
|
|
||||||
export const DocPage = ({
|
|
||||||
breadcrumbItems,
|
|
||||||
tocItems,
|
|
||||||
nextSteps,
|
|
||||||
children,
|
|
||||||
}: DocPageProps) => {
|
|
||||||
return (
|
|
||||||
<ThreeColumnLayout
|
|
||||||
center={
|
|
||||||
<article className="max-w-3xl mx-auto px-6 lg:px-12 py-12">
|
|
||||||
{/* Breadcrumb Navigation */}
|
|
||||||
<Breadcrumb items={breadcrumbItems} />
|
|
||||||
|
|
||||||
{/* Page Content (Hero + Sections) */}
|
|
||||||
{children}
|
|
||||||
|
|
||||||
{/* Next Steps Section */}
|
|
||||||
<section id="next-steps" className="mb-12">
|
|
||||||
<SectionHeader level={2} id="next-steps" className="mb-6">
|
|
||||||
Next Steps
|
|
||||||
</SectionHeader>
|
|
||||||
|
|
||||||
{nextSteps.description && (
|
|
||||||
<p className="text-gray-300 leading-relaxed mb-6">
|
|
||||||
{nextSteps.description}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<LinkCardGrid columns={2}>
|
|
||||||
{nextSteps.links.map((link, index) => (
|
|
||||||
<LinkCard
|
|
||||||
key={index}
|
|
||||||
href={link.href}
|
|
||||||
title={link.title}
|
|
||||||
description={link.description}
|
|
||||||
accent={link.accent}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</LinkCardGrid>
|
|
||||||
</section>
|
|
||||||
</article>
|
|
||||||
}
|
|
||||||
right={
|
|
||||||
<div className="border-l border-white/10 bg-slate-950/30 backdrop-blur-sm sticky top-12 h-[calc(100vh-3rem)] overflow-y-auto">
|
|
||||||
<DocsTOC items={tocItems} />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation Layout - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* Design Philosophy: Vercel-inspired spacious, focused reading experience
|
||||||
|
*
|
||||||
|
* Layout Structure:
|
||||||
|
* - Left Sidebar: Thin (256px) with minimal design
|
||||||
|
* - Content Area: Wide margins (max-w-3xl) for comfortable reading
|
||||||
|
* - Right TOC: Subtle and unobtrusive (224px)
|
||||||
|
*
|
||||||
|
* Responsive Behavior:
|
||||||
|
* - Mobile (<768px): Single column, sidebars become overlays
|
||||||
|
* - Tablet (768px-1024px): Content + TOC only
|
||||||
|
* - Desktop (>1024px): Full three-column layout
|
||||||
|
*
|
||||||
|
* Design Characteristics:
|
||||||
|
* - Generous whitespace
|
||||||
|
* - Subtle borders and shadows
|
||||||
|
* - Focus on content clarity
|
||||||
|
* - Minimal visual noise
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface DocsLayoutAProps {
|
||||||
|
sidebar: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
toc: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DocsLayoutA = ({ sidebar, children, toc }: DocsLayoutAProps) => {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
||||||
|
{/* Animated gradient background (matching landing page) */}
|
||||||
|
<div className="fixed inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<div className="absolute top-1/4 -left-1/4 w-96 h-96 bg-purple-600/10 rounded-full blur-3xl animate-pulse"></div>
|
||||||
|
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative z-10 flex">
|
||||||
|
{/* Left Sidebar - Thin, minimal design */}
|
||||||
|
<aside className="hidden lg:block w-64 border-r border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
|
||||||
|
{sidebar}
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content Area - Wide margins for comfortable reading */}
|
||||||
|
<main className="flex-1 min-w-0">
|
||||||
|
<div className="max-w-3xl mx-auto px-6 lg:px-12 py-12">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{/* Right TOC - Subtle and unobtrusive */}
|
||||||
|
<aside className="hidden xl:block w-56 border-l border-white/10 bg-slate-950/30 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
|
||||||
|
{toc}
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation Sidebar - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* Design Philosophy: Vercel-inspired minimal navigation
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Thin sidebar with subtle hover states
|
||||||
|
* - Collapsible section groups
|
||||||
|
* - Active state: Purple left border + text
|
||||||
|
* - Minimal icons (chevron for expandable items)
|
||||||
|
* - Clean, uncluttered appearance
|
||||||
|
*
|
||||||
|
* Navigation Structure:
|
||||||
|
* - Getting Started
|
||||||
|
* - API Reference (collapsible)
|
||||||
|
* - Text to Image
|
||||||
|
* - Upload
|
||||||
|
* - Images
|
||||||
|
* - Guides (collapsible)
|
||||||
|
* - Authentication
|
||||||
|
* - Error Handling
|
||||||
|
* - Rate Limits
|
||||||
|
* - Examples
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
interface NavItem {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
icon?: string;
|
||||||
|
children?: NavItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocsSidebarAProps {
|
||||||
|
currentPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigationItems: NavItem[] = [
|
||||||
|
{
|
||||||
|
label: 'Getting Started',
|
||||||
|
href: '/docs/variant-a',
|
||||||
|
icon: '🚀',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'API Reference',
|
||||||
|
href: '/docs/variant-a/api',
|
||||||
|
icon: '📚',
|
||||||
|
children: [
|
||||||
|
{ label: 'Text to Image', href: '/docs/variant-a/api/text-to-image' },
|
||||||
|
{ label: 'Upload', href: '/docs/variant-a/api/upload' },
|
||||||
|
{ label: 'Images', href: '/docs/variant-a/api/images' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Guides',
|
||||||
|
href: '/docs/variant-a/guides',
|
||||||
|
icon: '📖',
|
||||||
|
children: [
|
||||||
|
{ label: 'Authentication', href: '/docs/variant-a/guides/authentication' },
|
||||||
|
{ label: 'Error Handling', href: '/docs/variant-a/guides/error-handling' },
|
||||||
|
{ label: 'Rate Limits', href: '/docs/variant-a/guides/rate-limits' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Examples',
|
||||||
|
href: '/docs/variant-a/examples',
|
||||||
|
icon: '💡',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const DocsSidebarA = ({ currentPath }: DocsSidebarAProps) => {
|
||||||
|
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
|
||||||
|
|
||||||
|
const toggleSection = (label: string) => {
|
||||||
|
setExpandedSections((prev) =>
|
||||||
|
prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isActive = (href: string) => currentPath === href;
|
||||||
|
const isExpanded = (label: string) => expandedSections.includes(label);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="p-6" aria-label="Documentation navigation">
|
||||||
|
{/* Logo/Title */}
|
||||||
|
<div className="mb-8">
|
||||||
|
<h2 className="text-lg font-semibold text-white">Documentation</h2>
|
||||||
|
<p className="text-xs text-gray-500 mt-1">Variant A: Clean</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Navigation Items */}
|
||||||
|
<ul className="space-y-1">
|
||||||
|
{navigationItems.map((item) => {
|
||||||
|
const hasChildren = item.children && item.children.length > 0;
|
||||||
|
const expanded = isExpanded(item.label);
|
||||||
|
const active = isActive(item.href);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.label}>
|
||||||
|
{/* Parent Item */}
|
||||||
|
<div className="relative">
|
||||||
|
{active && (
|
||||||
|
<div className="absolute left-0 top-0 bottom-0 w-0.5 bg-purple-500 rounded-r"></div>
|
||||||
|
)}
|
||||||
|
<a
|
||||||
|
href={item.href}
|
||||||
|
onClick={
|
||||||
|
hasChildren
|
||||||
|
? (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toggleSection(item.label);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
className={`
|
||||||
|
flex items-center justify-between px-3 py-2 rounded-lg text-sm transition-colors
|
||||||
|
${active ? 'bg-purple-500/10 text-white font-medium' : 'text-gray-400 hover:text-white hover:bg-white/5'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
{item.icon && <span className="text-base">{item.icon}</span>}
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</span>
|
||||||
|
{hasChildren && (
|
||||||
|
<svg
|
||||||
|
className={`w-4 h-4 transition-transform ${expanded ? 'rotate-90' : ''}`}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Children Items */}
|
||||||
|
{hasChildren && expanded && (
|
||||||
|
<ul className="ml-6 mt-1 space-y-1 border-l border-slate-800">
|
||||||
|
{item.children!.map((child) => {
|
||||||
|
const childActive = isActive(child.href);
|
||||||
|
return (
|
||||||
|
<li key={child.label}>
|
||||||
|
<a
|
||||||
|
href={child.href}
|
||||||
|
className={`
|
||||||
|
block px-3 py-1.5 text-sm rounded-lg transition-colors -ml-px
|
||||||
|
${childActive ? 'text-white font-medium border-l-2 border-purple-500' : 'text-gray-500 hover:text-gray-300 border-l-2 border-transparent'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{child.label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* Bottom Links */}
|
||||||
|
<div className="mt-12 pt-6 border-t border-slate-800">
|
||||||
|
<ul className="space-y-2 text-sm">
|
||||||
|
<li>
|
||||||
|
<a href="/docs" className="text-gray-500 hover:text-gray-300 transition-colors">
|
||||||
|
← Back to variants
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table of Contents - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* Design Philosophy: Subtle, unobtrusive TOC
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Small indicator dots for section levels
|
||||||
|
* - Smooth scroll to section
|
||||||
|
* - Active section highlighting (purple text)
|
||||||
|
* - Sticky positioning
|
||||||
|
* - Minimal visual weight
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* - Extracts H2 and H3 headings from content
|
||||||
|
* - Tracks scroll position to highlight active section
|
||||||
|
* - Click to smooth scroll to section
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
interface TocItem {
|
||||||
|
id: string;
|
||||||
|
text: string;
|
||||||
|
level: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocsTOCAProps {
|
||||||
|
items: TocItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DocsTOCA = ({ items }: DocsTOCAProps) => {
|
||||||
|
const [activeId, setActiveId] = useState<string>('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setActiveId(entry.target.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ rootMargin: '-20% 0px -35% 0px' }
|
||||||
|
);
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
const element = document.getElementById(item.id);
|
||||||
|
if (element) observer.observe(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => observer.disconnect();
|
||||||
|
}, [items]);
|
||||||
|
|
||||||
|
const scrollToSection = (id: string) => {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (items.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="p-6 sticky top-6" aria-label="Table of contents">
|
||||||
|
<h3 className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-4">
|
||||||
|
On This Page
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<ul className="space-y-2.5 text-sm">
|
||||||
|
{items.map((item) => {
|
||||||
|
const isActive = activeId === item.id;
|
||||||
|
const isH3 = item.level === 3;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.id} className={isH3 ? 'ml-4' : ''}>
|
||||||
|
<button
|
||||||
|
onClick={() => scrollToSection(item.id)}
|
||||||
|
className={`
|
||||||
|
flex items-start gap-2 text-left w-full transition-colors group
|
||||||
|
${isActive ? 'text-purple-400' : 'text-gray-500 hover:text-gray-300'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{/* Indicator dot */}
|
||||||
|
<span
|
||||||
|
className={`
|
||||||
|
flex-shrink-0 w-1 h-1 rounded-full mt-2 transition-colors
|
||||||
|
${isActive ? 'bg-purple-400' : 'bg-gray-600 group-hover:bg-gray-400'}
|
||||||
|
`}
|
||||||
|
></span>
|
||||||
|
<span className="line-clamp-2">{item.text}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,293 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interactive API Widget - Variant A: Clean & Minimal
|
||||||
|
*
|
||||||
|
* Design Philosophy: Inline playground with tabbed interface
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Multi-language code tabs (curl, JavaScript, Python, Go)
|
||||||
|
* - API key input field (persists via localStorage)
|
||||||
|
* - "Try It" button to execute live requests
|
||||||
|
* - Response viewer with syntax highlighting
|
||||||
|
* - Request/Response tabs
|
||||||
|
* - Error state handling
|
||||||
|
* - Clean, focused design
|
||||||
|
*
|
||||||
|
* Layout:
|
||||||
|
* - Top: Language tabs + Copy button
|
||||||
|
* - Middle: Code preview OR Request params
|
||||||
|
* - Bottom: Try It button
|
||||||
|
* - Response: Expandable section below
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
interface InteractiveAPIWidgetAProps {
|
||||||
|
endpoint: string;
|
||||||
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||||
|
description: string;
|
||||||
|
parameters?: Array<{
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
required: boolean;
|
||||||
|
description: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||||
|
type ViewMode = 'code' | 'response';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||||
|
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||||
|
|
||||||
|
export const InteractiveAPIWidgetA = ({
|
||||||
|
endpoint,
|
||||||
|
method,
|
||||||
|
description,
|
||||||
|
parameters = [],
|
||||||
|
}: InteractiveAPIWidgetAProps) => {
|
||||||
|
const [language, setLanguage] = useState<Language>('curl');
|
||||||
|
const [apiKey, setApiKey] = useState('');
|
||||||
|
const [isExecuting, setIsExecuting] = useState(false);
|
||||||
|
const [viewMode, setViewMode] = useState<ViewMode>('code');
|
||||||
|
const [response, setResponse] = useState<any>(null);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// Parameter values
|
||||||
|
const [paramValues, setParamValues] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
// Load API key from localStorage
|
||||||
|
useEffect(() => {
|
||||||
|
const stored = localStorage.getItem(API_KEY_STORAGE);
|
||||||
|
if (stored) setApiKey(stored);
|
||||||
|
|
||||||
|
// Initialize parameter default values
|
||||||
|
const defaults: Record<string, string> = {};
|
||||||
|
parameters.forEach((param) => {
|
||||||
|
if (param.defaultValue) {
|
||||||
|
defaults[param.name] = param.defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setParamValues(defaults);
|
||||||
|
}, [parameters]);
|
||||||
|
|
||||||
|
// Save API key to localStorage
|
||||||
|
const handleApiKeyChange = (value: string) => {
|
||||||
|
setApiKey(value);
|
||||||
|
if (value) {
|
||||||
|
localStorage.setItem(API_KEY_STORAGE, value);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(API_KEY_STORAGE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate code examples
|
||||||
|
const generateCode = (): string => {
|
||||||
|
const url = `${API_BASE_URL}${endpoint}`;
|
||||||
|
|
||||||
|
switch (language) {
|
||||||
|
case 'curl':
|
||||||
|
return `curl -X ${method} "${url}" \\
|
||||||
|
-H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a futuristic city at sunset",
|
||||||
|
"filename": "city",
|
||||||
|
"aspectRatio": "16:9"
|
||||||
|
}'`;
|
||||||
|
|
||||||
|
case 'javascript':
|
||||||
|
return `const response = await fetch('${url}', {
|
||||||
|
method: '${method}',
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': '${apiKey || 'YOUR_API_KEY'}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: 'a futuristic city at sunset',
|
||||||
|
filename: 'city',
|
||||||
|
aspectRatio: '16:9'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(data);`;
|
||||||
|
|
||||||
|
case 'python':
|
||||||
|
return `import requests
|
||||||
|
|
||||||
|
url = '${url}'
|
||||||
|
headers = {
|
||||||
|
'X-API-Key': '${apiKey || 'YOUR_API_KEY'}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
'prompt': 'a futuristic city at sunset',
|
||||||
|
'filename': 'city',
|
||||||
|
'aspectRatio': '16:9'
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.${method.toLowerCase()}(url, headers=headers, json=data)
|
||||||
|
print(response.json())`;
|
||||||
|
|
||||||
|
case 'go':
|
||||||
|
return `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
url := "${url}"
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"prompt": "a futuristic city at sunset",
|
||||||
|
"filename": "city",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, _ := json.Marshal(data)
|
||||||
|
req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData))
|
||||||
|
req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}")
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, _ := client.Do(req)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
}`;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute API request
|
||||||
|
const executeRequest = async () => {
|
||||||
|
if (!apiKey) {
|
||||||
|
setError('Please enter your API key');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsExecuting(true);
|
||||||
|
setError(null);
|
||||||
|
setViewMode('response');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const body: Record<string, any> = {};
|
||||||
|
parameters.forEach((param) => {
|
||||||
|
if (paramValues[param.name]) {
|
||||||
|
body[param.name] = paramValues[param.name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}${endpoint}`, {
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': apiKey,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: method !== 'GET' ? JSON.stringify(body) : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
setResponse(data);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : 'Failed to execute request');
|
||||||
|
} finally {
|
||||||
|
setIsExecuting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy code to clipboard
|
||||||
|
const copyCode = () => {
|
||||||
|
navigator.clipboard.writeText(generateCode());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="my-8 bg-slate-900/50 backdrop-blur-sm border border-slate-700 rounded-2xl overflow-hidden">
|
||||||
|
{/* Header with API Key Input */}
|
||||||
|
<div className="p-4 border-b border-slate-700 bg-slate-900/80">
|
||||||
|
<div className="flex flex-col md:flex-row gap-3 items-start md:items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-semibold text-white mb-1">Try it out</h3>
|
||||||
|
<p className="text-xs text-gray-500">{description}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 w-full md:w-64">
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={apiKey}
|
||||||
|
onChange={(e) => handleApiKeyChange(e.target.value)}
|
||||||
|
placeholder="Enter your API key"
|
||||||
|
className="w-full px-3 py-2 text-xs bg-slate-800 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Language Tabs */}
|
||||||
|
<div className="flex items-center justify-between bg-slate-950/50 px-4 py-2 border-b border-slate-700">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => (
|
||||||
|
<button
|
||||||
|
key={lang}
|
||||||
|
onClick={() => setLanguage(lang)}
|
||||||
|
className={`px-3 py-1 text-xs rounded transition-colors ${
|
||||||
|
language === lang
|
||||||
|
? 'bg-slate-700 text-white'
|
||||||
|
: 'text-gray-400 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{lang === 'javascript' ? 'JavaScript' : lang.charAt(0).toUpperCase() + lang.slice(1)}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={copyCode}
|
||||||
|
className="px-3 py-1 text-xs bg-purple-600/20 hover:bg-purple-600/30 text-purple-400 rounded transition-colors"
|
||||||
|
>
|
||||||
|
Copy
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Code Display */}
|
||||||
|
<div className="p-4 bg-slate-950/50">
|
||||||
|
<pre className="text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{generateCode()}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Try It Button */}
|
||||||
|
<div className="p-4 border-t border-slate-700 bg-slate-900/50">
|
||||||
|
<button
|
||||||
|
onClick={executeRequest}
|
||||||
|
disabled={!apiKey || isExecuting}
|
||||||
|
className="w-full px-4 py-2.5 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{isExecuting ? 'Executing...' : 'Try It'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Response Section */}
|
||||||
|
{(response || error) && (
|
||||||
|
<div className="border-t border-slate-700">
|
||||||
|
<div className="p-4 bg-slate-900/80">
|
||||||
|
<h4 className="text-sm font-semibold text-white mb-3">Response</h4>
|
||||||
|
{error ? (
|
||||||
|
<div className="p-3 bg-red-500/10 border border-red-500/20 rounded-lg text-red-400 text-xs">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<pre className="p-3 bg-slate-950/50 rounded-lg text-xs text-gray-300 overflow-x-auto">
|
||||||
|
<code>{JSON.stringify(response, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation Layout - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Design Philosophy: Next.js-inspired dense, hierarchical layout
|
||||||
|
*
|
||||||
|
* Layout Structure:
|
||||||
|
* - Left Sidebar: Wider (280px) with nested tree structure
|
||||||
|
* - Content Area: Narrower margins to show more content
|
||||||
|
* - Right TOC: Prominent with progress indicator (240px)
|
||||||
|
*
|
||||||
|
* Responsive Behavior:
|
||||||
|
* - Mobile (<768px): Bottom sheet navigation
|
||||||
|
* - Tablet (768px-1024px): Collapsible sidebar + TOC
|
||||||
|
* - Desktop (>1024px): Full three-column layout
|
||||||
|
*
|
||||||
|
* Design Characteristics:
|
||||||
|
* - Compact spacing
|
||||||
|
* - More content per screen
|
||||||
|
* - Nested navigation tree
|
||||||
|
* - Section numbers throughout
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface DocsLayoutBProps {
|
||||||
|
sidebar: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
toc: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DocsLayoutB = ({ sidebar, children, toc }: DocsLayoutBProps) => {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
||||||
|
{/* Animated gradient background (matching landing page) */}
|
||||||
|
<div className="fixed inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<div className="absolute top-1/4 -left-1/4 w-96 h-96 bg-purple-600/10 rounded-full blur-3xl animate-pulse"></div>
|
||||||
|
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-cyan-600/10 rounded-full blur-3xl animate-pulse delay-700"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative z-10 flex">
|
||||||
|
{/* Left Sidebar - Wider with nested structure */}
|
||||||
|
<aside className="hidden lg:block w-72 border-r border-white/10 bg-slate-950/80 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
|
||||||
|
{sidebar}
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content Area - Narrower margins for more content */}
|
||||||
|
<main className="flex-1 min-w-0">
|
||||||
|
<div className="max-w-4xl mx-auto px-6 lg:px-8 py-10">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{/* Right TOC - Prominent with progress */}
|
||||||
|
<aside className="hidden xl:block w-60 border-l border-white/10 bg-slate-950/50 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
|
||||||
|
{toc}
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation Sidebar - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Design Philosophy: Next.js-inspired nested tree structure
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Wider sidebar with deep nesting
|
||||||
|
* - Section numbers for all items
|
||||||
|
* - Compact spacing (more items visible)
|
||||||
|
* - Indent levels for hierarchy
|
||||||
|
* - Active state: Purple background + bold
|
||||||
|
* - Expand/collapse all button
|
||||||
|
*
|
||||||
|
* Navigation Structure with numbers:
|
||||||
|
* 1. Getting Started
|
||||||
|
* 2. API Reference
|
||||||
|
* 2.1 Text to Image
|
||||||
|
* 2.2 Upload
|
||||||
|
* 2.3 Images
|
||||||
|
* 3. Guides
|
||||||
|
* 3.1 Authentication
|
||||||
|
* 3.2 Error Handling
|
||||||
|
* 3.3 Rate Limits
|
||||||
|
* 4. Examples
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
interface NavItem {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
number?: string;
|
||||||
|
children?: NavItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocsSidebarBProps {
|
||||||
|
currentPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigationItems: NavItem[] = [
|
||||||
|
{
|
||||||
|
label: 'Getting Started',
|
||||||
|
href: '/docs/variant-b',
|
||||||
|
number: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'API Reference',
|
||||||
|
href: '/docs/variant-b/api',
|
||||||
|
number: '2',
|
||||||
|
children: [
|
||||||
|
{ label: 'Text to Image', href: '/docs/variant-b/api/text-to-image', number: '2.1' },
|
||||||
|
{ label: 'Upload', href: '/docs/variant-b/api/upload', number: '2.2' },
|
||||||
|
{ label: 'Images', href: '/docs/variant-b/api/images', number: '2.3' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Guides',
|
||||||
|
href: '/docs/variant-b/guides',
|
||||||
|
number: '3',
|
||||||
|
children: [
|
||||||
|
{ label: 'Authentication', href: '/docs/variant-b/guides/authentication', number: '3.1' },
|
||||||
|
{ label: 'Error Handling', href: '/docs/variant-b/guides/error-handling', number: '3.2' },
|
||||||
|
{ label: 'Rate Limits', href: '/docs/variant-b/guides/rate-limits', number: '3.3' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Examples',
|
||||||
|
href: '/docs/variant-b/examples',
|
||||||
|
number: '4',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const DocsSidebarB = ({ currentPath }: DocsSidebarBProps) => {
|
||||||
|
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
|
||||||
|
|
||||||
|
const toggleSection = (label: string) => {
|
||||||
|
setExpandedSections((prev) =>
|
||||||
|
prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isActive = (href: string) => currentPath === href;
|
||||||
|
const isExpanded = (label: string) => expandedSections.includes(label);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="p-4" aria-label="Documentation navigation">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-6 pb-4 border-b border-slate-800">
|
||||||
|
<h2 className="text-base font-bold text-white mb-1">Documentation</h2>
|
||||||
|
<p className="text-xs text-gray-500">Variant B: Dense</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Search (placeholder) */}
|
||||||
|
<div className="mb-4">
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search docs..."
|
||||||
|
className="w-full px-3 py-2 pl-9 text-sm bg-slate-800/50 border border-slate-700 rounded-lg text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Navigation Tree */}
|
||||||
|
<ul className="space-y-0.5">
|
||||||
|
{navigationItems.map((item) => {
|
||||||
|
const hasChildren = item.children && item.children.length > 0;
|
||||||
|
const expanded = isExpanded(item.label);
|
||||||
|
const active = isActive(item.href);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.label}>
|
||||||
|
{/* Parent Item */}
|
||||||
|
<a
|
||||||
|
href={item.href}
|
||||||
|
onClick={
|
||||||
|
hasChildren
|
||||||
|
? (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toggleSection(item.label);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
className={`
|
||||||
|
flex items-center justify-between px-3 py-2 rounded-md text-sm transition-colors
|
||||||
|
${active ? 'bg-purple-500/20 text-white font-semibold' : 'text-gray-400 hover:text-white hover:bg-slate-800/50'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<span className="text-xs font-mono text-gray-500">{item.number}</span>
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</span>
|
||||||
|
{hasChildren && (
|
||||||
|
<svg
|
||||||
|
className={`w-3.5 h-3.5 transition-transform ${expanded ? 'rotate-90' : ''}`}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* Children Items - Indented */}
|
||||||
|
{hasChildren && expanded && (
|
||||||
|
<ul className="ml-6 mt-0.5 space-y-0.5 border-l border-slate-800 pl-2">
|
||||||
|
{item.children!.map((child) => {
|
||||||
|
const childActive = isActive(child.href);
|
||||||
|
return (
|
||||||
|
<li key={child.label}>
|
||||||
|
<a
|
||||||
|
href={child.href}
|
||||||
|
className={`
|
||||||
|
flex items-center gap-2 px-3 py-1.5 text-sm rounded-md transition-colors
|
||||||
|
${childActive ? 'bg-purple-500/20 text-white font-semibold' : 'text-gray-500 hover:text-gray-300 hover:bg-slate-800/30'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className="text-xs font-mono text-gray-600">{child.number}</span>
|
||||||
|
<span>{child.label}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* Bottom Links */}
|
||||||
|
<div className="mt-8 pt-4 border-t border-slate-800">
|
||||||
|
<ul className="space-y-1.5 text-sm">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/docs"
|
||||||
|
className="flex items-center gap-2 px-3 py-1.5 text-gray-500 hover:text-gray-300 transition-colors"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
|
</svg>
|
||||||
|
<span>All variants</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table of Contents - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Design Philosophy: Prominent TOC with progress indicator
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Section numbers matching content
|
||||||
|
* - Progress bar showing read percentage
|
||||||
|
* - Larger, more prominent design
|
||||||
|
* - Active section with purple highlight
|
||||||
|
* - Sticky positioning with scroll progress
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* - Extracts H2 and H3 headings with numbers
|
||||||
|
* - Shows reading progress percentage
|
||||||
|
* - Click to smooth scroll to section
|
||||||
|
* - Visual progress bar
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
interface TocItem {
|
||||||
|
id: string;
|
||||||
|
text: string;
|
||||||
|
level: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocsTOCBProps {
|
||||||
|
items: TocItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DocsTOCB = ({ items }: DocsTOCBProps) => {
|
||||||
|
const [activeId, setActiveId] = useState<string>('');
|
||||||
|
const [scrollProgress, setScrollProgress] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setActiveId(entry.target.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ rootMargin: '-20% 0px -35% 0px' }
|
||||||
|
);
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
const element = document.getElementById(item.id);
|
||||||
|
if (element) observer.observe(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Track scroll progress
|
||||||
|
const handleScroll = () => {
|
||||||
|
const windowHeight = window.innerHeight;
|
||||||
|
const documentHeight = document.documentElement.scrollHeight;
|
||||||
|
const scrollTop = window.scrollY;
|
||||||
|
const progress = (scrollTop / (documentHeight - windowHeight)) * 100;
|
||||||
|
setScrollProgress(Math.min(progress, 100));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
window.removeEventListener('scroll', handleScroll);
|
||||||
|
};
|
||||||
|
}, [items]);
|
||||||
|
|
||||||
|
const scrollToSection = (id: string) => {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (items.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="p-5 sticky top-6" aria-label="Table of contents">
|
||||||
|
{/* Header with Progress */}
|
||||||
|
<div className="mb-4 pb-4 border-b border-slate-800">
|
||||||
|
<h3 className="text-xs font-bold text-white uppercase tracking-wider mb-3">
|
||||||
|
On This Page
|
||||||
|
</h3>
|
||||||
|
{/* Progress Bar */}
|
||||||
|
<div className="relative h-1 bg-slate-800 rounded-full overflow-hidden">
|
||||||
|
<div
|
||||||
|
className="absolute top-0 left-0 h-full bg-gradient-to-r from-purple-500 to-cyan-500 transition-all duration-300"
|
||||||
|
style={{ width: `${scrollProgress}%` }}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-gray-500 mt-2">{Math.round(scrollProgress)}% read</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* TOC Items with Numbers */}
|
||||||
|
<ul className="space-y-1.5 text-sm">
|
||||||
|
{items.map((item, index) => {
|
||||||
|
const isActive = activeId === item.id;
|
||||||
|
const isH3 = item.level === 3;
|
||||||
|
const number = isH3 ? `${Math.floor(index / 2)}.${index % 2 + 1}` : `${index + 1}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.id} className={isH3 ? 'ml-4' : ''}>
|
||||||
|
<button
|
||||||
|
onClick={() => scrollToSection(item.id)}
|
||||||
|
className={`
|
||||||
|
flex items-start gap-2 text-left w-full transition-colors py-1 px-2 rounded-md
|
||||||
|
${isActive ? 'bg-purple-500/20 text-purple-300 font-semibold' : 'text-gray-500 hover:text-gray-300 hover:bg-slate-800/30'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{/* Section number */}
|
||||||
|
<span className="flex-shrink-0 font-mono text-xs mt-0.5 opacity-60">
|
||||||
|
{isH3 ? '↳' : number}
|
||||||
|
</span>
|
||||||
|
<span className="line-clamp-2">{item.text}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* Back to Top Button */}
|
||||||
|
{scrollProgress > 20 && (
|
||||||
|
<button
|
||||||
|
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||||
|
className="mt-6 w-full px-3 py-2 text-xs bg-slate-800/50 hover:bg-slate-800 text-gray-400 hover:text-white rounded-lg transition-colors flex items-center justify-center gap-2"
|
||||||
|
>
|
||||||
|
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
||||||
|
</svg>
|
||||||
|
Back to top
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,291 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interactive API Widget - Variant B: Dense & Information-Rich
|
||||||
|
*
|
||||||
|
* Design Philosophy: Side-by-side code editor with persistent API key bar
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Persistent API key bar at the top of page (sticky)
|
||||||
|
* - Side-by-side code and response layout
|
||||||
|
* - Multi-language tabs (curl, JavaScript, Python, Go)
|
||||||
|
* - Live request execution
|
||||||
|
* - Compact, information-dense design
|
||||||
|
* - Parameter form on the left
|
||||||
|
* - Response on the right
|
||||||
|
*
|
||||||
|
* Layout:
|
||||||
|
* - Top: Sticky API key bar (global for page)
|
||||||
|
* - Left: Code + Parameters
|
||||||
|
* - Right: Response viewer
|
||||||
|
* - Bottom: Try It button
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
interface InteractiveAPIWidgetBProps {
|
||||||
|
endpoint: string;
|
||||||
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||||
|
description: string;
|
||||||
|
parameters?: Array<{
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
required: boolean;
|
||||||
|
description: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||||
|
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||||
|
|
||||||
|
export const InteractiveAPIWidgetB = ({
|
||||||
|
endpoint,
|
||||||
|
method,
|
||||||
|
description,
|
||||||
|
parameters = [],
|
||||||
|
}: InteractiveAPIWidgetBProps) => {
|
||||||
|
const [language, setLanguage] = useState<Language>('curl');
|
||||||
|
const [apiKey, setApiKey] = useState('');
|
||||||
|
const [isExecuting, setIsExecuting] = useState(false);
|
||||||
|
const [response, setResponse] = useState<any>(null);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [paramValues, setParamValues] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
// Load API key from localStorage
|
||||||
|
useEffect(() => {
|
||||||
|
const stored = localStorage.getItem(API_KEY_STORAGE);
|
||||||
|
if (stored) setApiKey(stored);
|
||||||
|
|
||||||
|
// Initialize parameter default values
|
||||||
|
const defaults: Record<string, string> = {};
|
||||||
|
parameters.forEach((param) => {
|
||||||
|
if (param.defaultValue) {
|
||||||
|
defaults[param.name] = param.defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setParamValues(defaults);
|
||||||
|
}, [parameters]);
|
||||||
|
|
||||||
|
// Save API key to localStorage
|
||||||
|
const handleApiKeyChange = (value: string) => {
|
||||||
|
setApiKey(value);
|
||||||
|
if (value) {
|
||||||
|
localStorage.setItem(API_KEY_STORAGE, value);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(API_KEY_STORAGE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate code examples
|
||||||
|
const generateCode = (): string => {
|
||||||
|
const url = `${API_BASE_URL}${endpoint}`;
|
||||||
|
|
||||||
|
switch (language) {
|
||||||
|
case 'curl':
|
||||||
|
return `curl -X ${method} "${url}" \\
|
||||||
|
-H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a futuristic city at sunset",
|
||||||
|
"filename": "city",
|
||||||
|
"aspectRatio": "16:9"
|
||||||
|
}'`;
|
||||||
|
|
||||||
|
case 'javascript':
|
||||||
|
return `const response = await fetch('${url}', {
|
||||||
|
method: '${method}',
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': '${apiKey || 'YOUR_API_KEY'}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: 'a futuristic city at sunset',
|
||||||
|
filename: 'city',
|
||||||
|
aspectRatio: '16:9'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();`;
|
||||||
|
|
||||||
|
case 'python':
|
||||||
|
return `import requests
|
||||||
|
|
||||||
|
url = '${url}'
|
||||||
|
headers = {
|
||||||
|
'X-API-Key': '${apiKey || 'YOUR_API_KEY'}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
'prompt': 'a futuristic city at sunset',
|
||||||
|
'filename': 'city',
|
||||||
|
'aspectRatio': '16:9'
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.${method.toLowerCase()}(url, headers=headers, json=data)`;
|
||||||
|
|
||||||
|
case 'go':
|
||||||
|
return `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
url := "${url}"
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"prompt": "a futuristic city at sunset",
|
||||||
|
"filename": "city",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, _ := json.Marshal(data)
|
||||||
|
req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData))
|
||||||
|
req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}")
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, _ := client.Do(req)
|
||||||
|
}`;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute API request
|
||||||
|
const executeRequest = async () => {
|
||||||
|
if (!apiKey) {
|
||||||
|
setError('Please enter your API key in the bar above');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsExecuting(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const body: Record<string, any> = {};
|
||||||
|
parameters.forEach((param) => {
|
||||||
|
if (paramValues[param.name]) {
|
||||||
|
body[param.name] = paramValues[param.name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}${endpoint}`, {
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': apiKey,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: method !== 'GET' ? JSON.stringify(body) : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
setResponse(data);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : 'Failed to execute request');
|
||||||
|
} finally {
|
||||||
|
setIsExecuting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy code to clipboard
|
||||||
|
const copyCode = () => {
|
||||||
|
navigator.clipboard.writeText(generateCode());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="my-6">
|
||||||
|
{/* API Key Bar - Persistent at top */}
|
||||||
|
<div className="mb-3 p-3 bg-slate-900/80 backdrop-blur-sm border border-slate-700 rounded-lg">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<label className="text-xs font-semibold text-gray-400 whitespace-nowrap">API Key:</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={apiKey}
|
||||||
|
onChange={(e) => handleApiKeyChange(e.target.value)}
|
||||||
|
placeholder="Enter your API key (persists across examples)"
|
||||||
|
className="flex-1 px-3 py-1.5 text-xs bg-slate-800 border border-slate-700 rounded text-white placeholder-gray-600 focus:outline-none focus:ring-1 focus:ring-purple-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
<span className={`text-xs ${apiKey ? 'text-green-400' : 'text-gray-500'}`}>
|
||||||
|
{apiKey ? '✓ Set' : 'Not set'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main Widget - Two Column Layout */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-3 bg-slate-900/50 backdrop-blur-sm border border-slate-700 rounded-lg overflow-hidden">
|
||||||
|
{/* Left Column: Code */}
|
||||||
|
<div className="border-r border-slate-700">
|
||||||
|
{/* Language Tabs */}
|
||||||
|
<div className="flex items-center justify-between bg-slate-950/50 px-3 py-2 border-b border-slate-700">
|
||||||
|
<div className="flex gap-1.5">
|
||||||
|
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang) => (
|
||||||
|
<button
|
||||||
|
key={lang}
|
||||||
|
onClick={() => setLanguage(lang)}
|
||||||
|
className={`px-2 py-1 text-xs rounded transition-colors ${
|
||||||
|
language === lang ? 'bg-slate-700 text-white' : 'text-gray-500 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{lang === 'javascript' ? 'JS' : lang.toUpperCase()}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={copyCode}
|
||||||
|
className="px-2 py-1 text-xs bg-purple-600/20 hover:bg-purple-600/30 text-purple-400 rounded transition-colors"
|
||||||
|
>
|
||||||
|
Copy
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Code Display */}
|
||||||
|
<div className="p-3 bg-slate-950/50 h-64 overflow-auto">
|
||||||
|
<pre className="text-xs text-gray-300">
|
||||||
|
<code>{generateCode()}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Column: Response */}
|
||||||
|
<div>
|
||||||
|
<div className="bg-slate-950/50 px-3 py-2 border-b border-slate-700">
|
||||||
|
<h4 className="text-xs font-semibold text-white">Response</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-3 bg-slate-950/50 h-64 overflow-auto">
|
||||||
|
{error ? (
|
||||||
|
<div className="p-2 bg-red-500/10 border border-red-500/20 rounded text-red-400 text-xs">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
) : response ? (
|
||||||
|
<pre className="text-xs text-gray-300">
|
||||||
|
<code>{JSON.stringify(response, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
) : (
|
||||||
|
<p className="text-xs text-gray-500 italic">
|
||||||
|
Click "Execute Request" to see the response
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Try It Button - Full Width */}
|
||||||
|
<button
|
||||||
|
onClick={executeRequest}
|
||||||
|
disabled={!apiKey || isExecuting}
|
||||||
|
className="mt-3 w-full px-4 py-2 rounded-lg bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-sm font-semibold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{isExecuting ? 'Executing...' : '▶ Execute Request'}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<p className="mt-2 text-xs text-gray-500 text-center">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation Layout - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Colorful, card-based, engaging visual layout
|
||||||
|
*
|
||||||
|
* Layout Structure:
|
||||||
|
* - Left Sidebar: Wide (320px) with large card-style navigation
|
||||||
|
* - Content Area: Generous padding (p-12) with wide max-width (max-w-5xl)
|
||||||
|
* - Right TOC: Floating card with gradient borders (280px)
|
||||||
|
*
|
||||||
|
* Design Characteristics:
|
||||||
|
* - Colorful gradient borders everywhere (purple/cyan)
|
||||||
|
* - Card-based design with shadows
|
||||||
|
* - Large, generous spacing (p-6, gap-6, mb-12)
|
||||||
|
* - Playful and engaging visual style
|
||||||
|
* - NO section numbers (more visual/intuitive)
|
||||||
|
* - Large emoji icons throughout
|
||||||
|
* - Floating shadow effects
|
||||||
|
*
|
||||||
|
* Responsive Behavior:
|
||||||
|
* - Mobile (<768px): Single column, cards stack
|
||||||
|
* - Tablet (768px-1024px): Content + floating TOC
|
||||||
|
* - Desktop (>1024px): Full three-column card layout
|
||||||
|
*
|
||||||
|
* Color Palette:
|
||||||
|
* - Purple gradients: from-purple-500/30 to-purple-600/20
|
||||||
|
* - Cyan gradients: from-cyan-500/30 to-cyan-600/20
|
||||||
|
* - Amber accents: amber-500, amber-600
|
||||||
|
* - Background: slate-950, slate-900
|
||||||
|
* - Borders: purple-500/40, cyan-500/40, slate-700
|
||||||
|
* - Shadows: shadow-lg shadow-purple-500/20
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface DocsLayoutCProps {
|
||||||
|
sidebar: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
toc: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DocsLayoutC = ({ sidebar, children, toc }: DocsLayoutCProps) => {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950">
|
||||||
|
{/* Animated gradient background - More colorful */}
|
||||||
|
<div className="fixed inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<div className="absolute top-1/4 -left-1/4 w-[600px] h-[600px] bg-purple-600/20 rounded-full blur-3xl animate-pulse"></div>
|
||||||
|
<div className="absolute bottom-1/4 -right-1/4 w-[600px] h-[600px] bg-cyan-600/20 rounded-full blur-3xl animate-pulse delay-700"></div>
|
||||||
|
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[400px] h-[400px] bg-amber-600/10 rounded-full blur-3xl animate-pulse delay-1000"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative z-10 flex">
|
||||||
|
{/* Left Sidebar - Wide with card-style navigation */}
|
||||||
|
<aside className="hidden lg:block w-80 border-r-2 border-purple-500/20 bg-slate-950/80 backdrop-blur-sm sticky top-0 h-screen overflow-y-auto">
|
||||||
|
{sidebar}
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Main Content Area - Wide with generous padding */}
|
||||||
|
<main className="flex-1 min-w-0">
|
||||||
|
<div className="max-w-5xl mx-auto px-8 lg:px-12 py-12">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{/* Right TOC - Floating card with gradient border */}
|
||||||
|
<aside className="hidden xl:block w-72 border-l-2 border-cyan-500/20 bg-slate-950/60 backdrop-blur-md sticky top-0 h-screen overflow-y-auto">
|
||||||
|
{toc}
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documentation Sidebar - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Card-based navigation with large colorful visual elements
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Navigation items as large gradient-bordered cards
|
||||||
|
* - Large emoji icons (text-2xl) for visual hierarchy
|
||||||
|
* - Alternating purple/cyan gradient accents
|
||||||
|
* - Generous spacing (gap-4, p-4 per item)
|
||||||
|
* - Touch-friendly minimum heights (min-h-12)
|
||||||
|
* - NO section numbers (more playful/intuitive)
|
||||||
|
* - Hover effects with shadow and scale
|
||||||
|
* - Active state with prominent gradient background
|
||||||
|
*
|
||||||
|
* Navigation Structure (NO numbers):
|
||||||
|
* - 🚀 Getting Started
|
||||||
|
* - 📚 API Reference
|
||||||
|
* - 🎨 Text to Image
|
||||||
|
* - 📤 Upload
|
||||||
|
* - 🖼️ Images
|
||||||
|
* - 🔐 Guides
|
||||||
|
* - 🔑 Authentication
|
||||||
|
* - ⚠️ Error Handling
|
||||||
|
* - ⏱️ Rate Limits
|
||||||
|
* - 💡 Examples
|
||||||
|
*
|
||||||
|
* Color Palette:
|
||||||
|
* - Purple: from-purple-500/30 to-purple-600/20
|
||||||
|
* - Cyan: from-cyan-500/30 to-cyan-600/20
|
||||||
|
* - Active: bg-gradient-to-br from-purple-500/30 to-cyan-500/30
|
||||||
|
* - Hover: shadow-lg shadow-purple-500/20, scale-102
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
interface NavItem {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
icon: string;
|
||||||
|
color: 'purple' | 'cyan' | 'amber';
|
||||||
|
children?: NavItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocsSidebarCProps {
|
||||||
|
currentPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigationItems: NavItem[] = [
|
||||||
|
{
|
||||||
|
label: 'Getting Started',
|
||||||
|
href: '/docs/variant-c',
|
||||||
|
icon: '🚀',
|
||||||
|
color: 'purple',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'API Reference',
|
||||||
|
href: '/docs/variant-c/api',
|
||||||
|
icon: '📚',
|
||||||
|
color: 'cyan',
|
||||||
|
children: [
|
||||||
|
{ label: 'Text to Image', href: '/docs/variant-c/api/text-to-image', icon: '🎨', color: 'purple' },
|
||||||
|
{ label: 'Upload', href: '/docs/variant-c/api/upload', icon: '📤', color: 'cyan' },
|
||||||
|
{ label: 'Images', href: '/docs/variant-c/api/images', icon: '🖼️', color: 'purple' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Guides',
|
||||||
|
href: '/docs/variant-c/guides',
|
||||||
|
icon: '🔐',
|
||||||
|
color: 'purple',
|
||||||
|
children: [
|
||||||
|
{ label: 'Authentication', href: '/docs/variant-c/guides/authentication', icon: '🔑', color: 'cyan' },
|
||||||
|
{ label: 'Error Handling', href: '/docs/variant-c/guides/error-handling', icon: '⚠️', color: 'purple' },
|
||||||
|
{ label: 'Rate Limits', href: '/docs/variant-c/guides/rate-limits', icon: '⏱️', color: 'cyan' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Examples',
|
||||||
|
href: '/docs/variant-c/examples',
|
||||||
|
icon: '💡',
|
||||||
|
color: 'amber',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const getGradientClasses = (color: 'purple' | 'cyan' | 'amber', active: boolean) => {
|
||||||
|
if (active) {
|
||||||
|
return 'bg-gradient-to-br from-purple-500/30 to-cyan-500/30 border-purple-500/60 shadow-lg shadow-purple-500/30';
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseClasses = 'border-2 hover:shadow-lg transition-all duration-300 hover:scale-[1.02]';
|
||||||
|
|
||||||
|
switch (color) {
|
||||||
|
case 'purple':
|
||||||
|
return `${baseClasses} border-purple-500/30 hover:border-purple-500/50 hover:shadow-purple-500/20 hover:bg-purple-500/10`;
|
||||||
|
case 'cyan':
|
||||||
|
return `${baseClasses} border-cyan-500/30 hover:border-cyan-500/50 hover:shadow-cyan-500/20 hover:bg-cyan-500/10`;
|
||||||
|
case 'amber':
|
||||||
|
return `${baseClasses} border-amber-500/30 hover:border-amber-500/50 hover:shadow-amber-500/20 hover:bg-amber-500/10`;
|
||||||
|
default:
|
||||||
|
return baseClasses;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DocsSidebarC = ({ currentPath }: DocsSidebarCProps) => {
|
||||||
|
const [expandedSections, setExpandedSections] = useState<string[]>(['API Reference', 'Guides']);
|
||||||
|
|
||||||
|
const toggleSection = (label: string) => {
|
||||||
|
setExpandedSections((prev) =>
|
||||||
|
prev.includes(label) ? prev.filter((item) => item !== label) : [...prev, label]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isActive = (href: string) => currentPath === href;
|
||||||
|
const isExpanded = (label: string) => expandedSections.includes(label);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="p-6" aria-label="Documentation navigation">
|
||||||
|
{/* Header - Colorful */}
|
||||||
|
<div className="mb-8 pb-6 border-b-2 border-gradient-to-r from-purple-500/30 to-cyan-500/30">
|
||||||
|
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-purple-500/20 to-cyan-500/20 border-2 border-purple-500/40 mb-3">
|
||||||
|
<span className="text-xl">📖</span>
|
||||||
|
<h2 className="text-base font-bold text-white">Documentation</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-gray-400 mt-2 ml-1">Variant C: Modern & Visual</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Search (placeholder) - Colorful border */}
|
||||||
|
<div className="mb-6">
|
||||||
|
<div className="relative">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search docs..."
|
||||||
|
className="w-full px-4 py-3 pl-11 text-sm bg-slate-900/50 border-2 border-purple-500/30 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500/50 transition-all"
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-purple-400"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Navigation Cards */}
|
||||||
|
<ul className="space-y-4">
|
||||||
|
{navigationItems.map((item) => {
|
||||||
|
const hasChildren = item.children && item.children.length > 0;
|
||||||
|
const expanded = isExpanded(item.label);
|
||||||
|
const active = isActive(item.href);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.label}>
|
||||||
|
{/* Parent Item - Large Card */}
|
||||||
|
<a
|
||||||
|
href={item.href}
|
||||||
|
onClick={
|
||||||
|
hasChildren
|
||||||
|
? (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
toggleSection(item.label);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
className={`
|
||||||
|
flex items-center justify-between p-4 rounded-xl transition-all duration-300
|
||||||
|
${getGradientClasses(item.color, active)}
|
||||||
|
${active ? 'text-white font-bold' : 'text-gray-300 hover:text-white'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-3">
|
||||||
|
<span className="text-2xl">{item.icon}</span>
|
||||||
|
<span className="text-base">{item.label}</span>
|
||||||
|
</span>
|
||||||
|
{hasChildren && (
|
||||||
|
<svg
|
||||||
|
className={`w-5 h-5 transition-transform duration-300 ${expanded ? 'rotate-90' : ''}`}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{/* Children Items - Smaller Cards with Indent */}
|
||||||
|
{hasChildren && expanded && (
|
||||||
|
<ul className="ml-6 mt-3 space-y-2 border-l-2 border-purple-500/20 pl-4">
|
||||||
|
{item.children!.map((child) => {
|
||||||
|
const childActive = isActive(child.href);
|
||||||
|
return (
|
||||||
|
<li key={child.label}>
|
||||||
|
<a
|
||||||
|
href={child.href}
|
||||||
|
className={`
|
||||||
|
flex items-center gap-3 p-3 rounded-lg transition-all duration-300
|
||||||
|
${getGradientClasses(child.color, childActive)}
|
||||||
|
${childActive ? 'text-white font-semibold' : 'text-gray-400 hover:text-white'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className="text-xl">{child.icon}</span>
|
||||||
|
<span className="text-sm">{child.label}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* Bottom Links - Colorful Card */}
|
||||||
|
<div className="mt-8 pt-6 border-t-2 border-purple-500/20">
|
||||||
|
<a
|
||||||
|
href="/docs"
|
||||||
|
className="flex items-center gap-3 px-4 py-3 text-sm text-gray-400 hover:text-white transition-colors rounded-xl border-2 border-cyan-500/30 hover:border-cyan-500/50 hover:bg-cyan-500/10"
|
||||||
|
>
|
||||||
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||||
|
</svg>
|
||||||
|
<span>View all variants</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,212 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table of Contents - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Floating card with colorful visual indicators
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Wrapped in large gradient-bordered card
|
||||||
|
* - Colorful dot indicators (alternating purple/cyan/amber)
|
||||||
|
* - Large text sizes (text-base for items)
|
||||||
|
* - Generous spacing (p-6, gap-4)
|
||||||
|
* - Floating shadow effect with colored glow
|
||||||
|
* - NO section numbers (more visual/playful)
|
||||||
|
* - Active state with gradient background
|
||||||
|
* - Smooth hover animations with scale
|
||||||
|
* - Fun, engaging design with emoji header
|
||||||
|
*
|
||||||
|
* Visual Elements:
|
||||||
|
* - Large colored dots instead of numbers
|
||||||
|
* - Gradient progress bar with rainbow colors
|
||||||
|
* - Active item with gradient highlight
|
||||||
|
* - Hover effects with shadow and scale
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* - Extracts H2 and H3 headings (no numbers)
|
||||||
|
* - Shows reading progress with colorful bar
|
||||||
|
* - Click to smooth scroll to section
|
||||||
|
* - Visual feedback with animations
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
interface TocItem {
|
||||||
|
id: string;
|
||||||
|
text: string;
|
||||||
|
level: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocsTOCCProps {
|
||||||
|
items: TocItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const getColorForIndex = (index: number): string => {
|
||||||
|
const colors = ['purple', 'cyan', 'amber'];
|
||||||
|
return colors[index % colors.length];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDotClasses = (color: string, isActive: boolean): string => {
|
||||||
|
const baseClasses = 'w-2.5 h-2.5 rounded-full flex-shrink-0 transition-all duration-300';
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
return `${baseClasses} shadow-lg ${
|
||||||
|
color === 'purple'
|
||||||
|
? 'bg-purple-500 shadow-purple-500/50'
|
||||||
|
: color === 'cyan'
|
||||||
|
? 'bg-cyan-500 shadow-cyan-500/50'
|
||||||
|
: 'bg-amber-500 shadow-amber-500/50'
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${baseClasses} ${
|
||||||
|
color === 'purple'
|
||||||
|
? 'bg-purple-500/40'
|
||||||
|
: color === 'cyan'
|
||||||
|
? 'bg-cyan-500/40'
|
||||||
|
: 'bg-amber-500/40'
|
||||||
|
}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DocsTOCC = ({ items }: DocsTOCCProps) => {
|
||||||
|
const [activeId, setActiveId] = useState<string>('');
|
||||||
|
const [scrollProgress, setScrollProgress] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setActiveId(entry.target.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ rootMargin: '-20% 0px -35% 0px' }
|
||||||
|
);
|
||||||
|
|
||||||
|
items.forEach((item) => {
|
||||||
|
const element = document.getElementById(item.id);
|
||||||
|
if (element) observer.observe(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
const windowHeight = window.innerHeight;
|
||||||
|
const documentHeight = document.documentElement.scrollHeight;
|
||||||
|
const scrollTop = window.scrollY;
|
||||||
|
const progress = (scrollTop / (documentHeight - windowHeight)) * 100;
|
||||||
|
setScrollProgress(Math.min(progress, 100));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
window.removeEventListener('scroll', handleScroll);
|
||||||
|
};
|
||||||
|
}, [items]);
|
||||||
|
|
||||||
|
const scrollToSection = (id: string) => {
|
||||||
|
const element = document.getElementById(id);
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (items.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="p-6 sticky top-6" aria-label="Table of contents">
|
||||||
|
{/* Floating Card with Gradient Border */}
|
||||||
|
<div className="rounded-2xl border-2 border-purple-500/40 bg-slate-900/60 backdrop-blur-md shadow-xl shadow-purple-500/20 overflow-hidden">
|
||||||
|
{/* Header with Icon and Progress */}
|
||||||
|
<div className="p-6 pb-4 border-b-2 border-purple-500/20">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<span className="text-2xl">📍</span>
|
||||||
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider">
|
||||||
|
On This Page
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Rainbow Progress Bar */}
|
||||||
|
<div className="relative h-2 bg-slate-800 rounded-full overflow-hidden">
|
||||||
|
<div
|
||||||
|
className="absolute top-0 left-0 h-full bg-gradient-to-r from-purple-500 via-cyan-500 to-amber-500 transition-all duration-300 shadow-lg"
|
||||||
|
style={{ width: `${scrollProgress}%` }}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 flex items-center justify-between">
|
||||||
|
<p className="text-xs text-gray-400">{Math.round(scrollProgress)}% complete</p>
|
||||||
|
<span className="text-xs text-purple-400 font-semibold">
|
||||||
|
{items.findIndex((item) => item.id === activeId) + 1}/{items.length}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* TOC Items with Colorful Dots */}
|
||||||
|
<ul className="p-6 space-y-3">
|
||||||
|
{items.map((item, index) => {
|
||||||
|
const isActive = activeId === item.id;
|
||||||
|
const isH3 = item.level === 3;
|
||||||
|
const color = getColorForIndex(index);
|
||||||
|
const cleanText = item.text.replace(/^\d+\.?\s*/, '');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={item.id} className={isH3 ? 'ml-6' : ''}>
|
||||||
|
<button
|
||||||
|
onClick={() => scrollToSection(item.id)}
|
||||||
|
className={`
|
||||||
|
flex items-start gap-3 text-left w-full transition-all duration-300 py-2 px-3 rounded-lg
|
||||||
|
${
|
||||||
|
isActive
|
||||||
|
? 'bg-gradient-to-br from-purple-500/20 to-cyan-500/20 text-white font-semibold shadow-lg scale-105'
|
||||||
|
: 'text-gray-400 hover:text-white hover:bg-slate-800/50 hover:scale-102'
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{/* Colorful Dot Indicator */}
|
||||||
|
<span className="mt-1.5">
|
||||||
|
{isH3 ? (
|
||||||
|
<span className="text-gray-600 text-xs ml-0.5">↳</span>
|
||||||
|
) : (
|
||||||
|
<span className={getDotClasses(color, isActive)}></span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{/* Text */}
|
||||||
|
<span className="flex-1 text-base leading-relaxed">{cleanText}</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{/* Back to Top Button - Colorful */}
|
||||||
|
{scrollProgress > 20 && (
|
||||||
|
<div className="p-6 pt-0">
|
||||||
|
<button
|
||||||
|
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
|
||||||
|
className="w-full px-4 py-3 text-sm bg-gradient-to-r from-purple-600/30 to-cyan-600/30 hover:from-purple-600/50 hover:to-cyan-600/50 text-white rounded-xl transition-all duration-300 flex items-center justify-center gap-2 border-2 border-purple-500/40 hover:border-purple-500/60 shadow-lg hover:shadow-purple-500/30 hover:scale-105"
|
||||||
|
>
|
||||||
|
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
||||||
|
</svg>
|
||||||
|
<span className="font-semibold">Back to top</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Fun Floating Tip Card */}
|
||||||
|
<div className="mt-6 p-4 rounded-xl bg-gradient-to-br from-amber-500/10 to-transparent border-2 border-amber-500/30 shadow-lg">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<span className="text-xl">💡</span>
|
||||||
|
<p className="text-xs text-amber-300">
|
||||||
|
<strong>Tip:</strong> Click any item to jump directly to that section!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,393 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interactive API Widget - Variant C: Modern & Visual (Shopify-inspired)
|
||||||
|
*
|
||||||
|
* Design Philosophy: Floating, expandable card with colorful visual feedback
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* - Full-screen expandable mode toggle button
|
||||||
|
* - Large gradient-bordered card with shadow glow
|
||||||
|
* - Prominent "Test Now ⚡" button (larger, more visual)
|
||||||
|
* - Response in colorful gradient-bordered card
|
||||||
|
* - Success/error states with vibrant colored badges
|
||||||
|
* - More visual feedback and animations
|
||||||
|
* - Large emoji icons throughout
|
||||||
|
* - Colorful code syntax highlighting hints
|
||||||
|
* - Floating shadow effects
|
||||||
|
*
|
||||||
|
* Layout:
|
||||||
|
* - Top: Large colorful API key input card
|
||||||
|
* - Main: Expandable code editor with rainbow gradient border
|
||||||
|
* - Language tabs as colorful pills
|
||||||
|
* - Large prominent "Test Now" button with gradient
|
||||||
|
* - Response card with colored status indicators
|
||||||
|
*
|
||||||
|
* Visual Elements:
|
||||||
|
* - Purple/cyan/amber gradients everywhere
|
||||||
|
* - Large shadows with colored glows
|
||||||
|
* - Scale and hover animations
|
||||||
|
* - Success: Green gradient with glow
|
||||||
|
* - Error: Red gradient with glow
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
interface InteractiveAPIWidgetCProps {
|
||||||
|
endpoint: string;
|
||||||
|
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||||
|
description: string;
|
||||||
|
parameters?: Array<{
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
required: boolean;
|
||||||
|
description: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Language = 'curl' | 'javascript' | 'python' | 'go';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
|
||||||
|
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||||
|
|
||||||
|
const getMethodColor = (method: string): string => {
|
||||||
|
switch (method) {
|
||||||
|
case 'GET':
|
||||||
|
return 'from-cyan-500 to-cyan-600';
|
||||||
|
case 'POST':
|
||||||
|
return 'from-purple-500 to-purple-600';
|
||||||
|
case 'PUT':
|
||||||
|
return 'from-amber-500 to-amber-600';
|
||||||
|
case 'DELETE':
|
||||||
|
return 'from-red-500 to-red-600';
|
||||||
|
default:
|
||||||
|
return 'from-purple-500 to-cyan-500';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const InteractiveAPIWidgetC = ({
|
||||||
|
endpoint,
|
||||||
|
method,
|
||||||
|
description,
|
||||||
|
parameters = [],
|
||||||
|
}: InteractiveAPIWidgetCProps) => {
|
||||||
|
const [language, setLanguage] = useState<Language>('curl');
|
||||||
|
const [apiKey, setApiKey] = useState('');
|
||||||
|
const [isExecuting, setIsExecuting] = useState(false);
|
||||||
|
const [response, setResponse] = useState<any>(null);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [paramValues, setParamValues] = useState<Record<string, string>>({});
|
||||||
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const stored = localStorage.getItem(API_KEY_STORAGE);
|
||||||
|
if (stored) setApiKey(stored);
|
||||||
|
|
||||||
|
const defaults: Record<string, string> = {};
|
||||||
|
parameters.forEach((param) => {
|
||||||
|
if (param.defaultValue) {
|
||||||
|
defaults[param.name] = param.defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setParamValues(defaults);
|
||||||
|
}, [parameters]);
|
||||||
|
|
||||||
|
const handleApiKeyChange = (value: string) => {
|
||||||
|
setApiKey(value);
|
||||||
|
if (value) {
|
||||||
|
localStorage.setItem(API_KEY_STORAGE, value);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(API_KEY_STORAGE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateCode = (): string => {
|
||||||
|
const url = `${API_BASE_URL}${endpoint}`;
|
||||||
|
|
||||||
|
switch (language) {
|
||||||
|
case 'curl':
|
||||||
|
return `curl -X ${method} "${url}" \\
|
||||||
|
-H "X-API-Key: ${apiKey || 'YOUR_API_KEY'}" \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-d '{
|
||||||
|
"prompt": "a futuristic city at sunset",
|
||||||
|
"filename": "city",
|
||||||
|
"aspectRatio": "16:9"
|
||||||
|
}'`;
|
||||||
|
|
||||||
|
case 'javascript':
|
||||||
|
return `const response = await fetch('${url}', {
|
||||||
|
method: '${method}',
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': '${apiKey || 'YOUR_API_KEY'}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: 'a futuristic city at sunset',
|
||||||
|
filename: 'city',
|
||||||
|
aspectRatio: '16:9'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();`;
|
||||||
|
|
||||||
|
case 'python':
|
||||||
|
return `import requests
|
||||||
|
|
||||||
|
url = '${url}'
|
||||||
|
headers = {
|
||||||
|
'X-API-Key': '${apiKey || 'YOUR_API_KEY'}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
'prompt': 'a futuristic city at sunset',
|
||||||
|
'filename': 'city',
|
||||||
|
'aspectRatio': '16:9'
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.${method.toLowerCase()}(url, headers=headers, json=data)`;
|
||||||
|
|
||||||
|
case 'go':
|
||||||
|
return `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
url := "${url}"
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"prompt": "a futuristic city at sunset",
|
||||||
|
"filename": "city",
|
||||||
|
"aspectRatio": "16:9",
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, _ := json.Marshal(data)
|
||||||
|
req, _ := http.NewRequest("${method}", url, bytes.NewBuffer(jsonData))
|
||||||
|
req.Header.Set("X-API-Key", "${apiKey || 'YOUR_API_KEY'}")
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, _ := client.Do(req)
|
||||||
|
}`;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const executeRequest = async () => {
|
||||||
|
if (!apiKey) {
|
||||||
|
setError('Please enter your API key above ✨');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsExecuting(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const body: Record<string, any> = {};
|
||||||
|
parameters.forEach((param) => {
|
||||||
|
if (paramValues[param.name]) {
|
||||||
|
body[param.name] = paramValues[param.name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE_URL}${endpoint}`, {
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
'X-API-Key': apiKey,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: method !== 'GET' ? JSON.stringify(body) : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
setResponse(data);
|
||||||
|
} catch (err) {
|
||||||
|
setError(err instanceof Error ? err.message : 'Failed to execute request 😔');
|
||||||
|
} finally {
|
||||||
|
setIsExecuting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyCode = () => {
|
||||||
|
navigator.clipboard.writeText(generateCode());
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="my-12">
|
||||||
|
{/* API Key Card - Large and Colorful */}
|
||||||
|
<div className="mb-6 p-6 bg-gradient-to-br from-purple-500/10 to-cyan-500/10 backdrop-blur-sm border-2 border-purple-500/40 rounded-2xl shadow-xl shadow-purple-500/20">
|
||||||
|
<div className="flex items-center gap-4 mb-3">
|
||||||
|
<span className="text-2xl">🔑</span>
|
||||||
|
<label className="text-sm font-bold text-white">Your API Key</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={apiKey}
|
||||||
|
onChange={(e) => handleApiKeyChange(e.target.value)}
|
||||||
|
placeholder="Enter your API key (saved locally)"
|
||||||
|
className="flex-1 px-4 py-3 text-sm bg-slate-900/80 border-2 border-purple-500/30 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500/50 transition-all"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={`px-4 py-3 rounded-xl font-semibold text-sm transition-all ${
|
||||||
|
apiKey
|
||||||
|
? 'bg-green-500/20 text-green-400 border-2 border-green-500/40 shadow-lg shadow-green-500/20'
|
||||||
|
: 'bg-gray-500/20 text-gray-400 border-2 border-gray-500/20'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{apiKey ? '✓ Ready' : '⚠️ Required'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Main Widget Card - Large Gradient Border */}
|
||||||
|
<div
|
||||||
|
className={`bg-gradient-to-br from-slate-900/80 to-slate-950/80 backdrop-blur-sm border-2 border-purple-500/40 rounded-2xl overflow-hidden shadow-2xl shadow-purple-500/30 transition-all duration-500 ${
|
||||||
|
isExpanded ? 'fixed inset-4 z-50' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{/* Header with Expand Button */}
|
||||||
|
<div className="flex items-center justify-between bg-slate-950/80 px-6 py-4 border-b-2 border-purple-500/30">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className={`px-3 py-1.5 rounded-lg bg-gradient-to-r ${getMethodColor(method)} text-white text-sm font-bold shadow-lg`}>
|
||||||
|
{method}
|
||||||
|
</div>
|
||||||
|
<span className="text-sm text-gray-400">{endpoint}</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
|
className="px-4 py-2 bg-cyan-600/20 hover:bg-cyan-600/30 text-cyan-400 rounded-lg transition-all text-sm font-semibold border-2 border-cyan-500/40 hover:border-cyan-500/60"
|
||||||
|
>
|
||||||
|
{isExpanded ? '✕ Close' : '⛶ Expand'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-6 p-6">
|
||||||
|
{/* Left: Code Editor */}
|
||||||
|
<div>
|
||||||
|
{/* Language Tabs - Colorful Pills */}
|
||||||
|
<div className="flex items-center gap-2 mb-4">
|
||||||
|
{(['curl', 'javascript', 'python', 'go'] as Language[]).map((lang, idx) => {
|
||||||
|
const colors = ['purple', 'cyan', 'amber', 'purple'];
|
||||||
|
const color = colors[idx];
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={lang}
|
||||||
|
onClick={() => setLanguage(lang)}
|
||||||
|
className={`px-4 py-2 text-sm rounded-xl font-semibold transition-all border-2 ${
|
||||||
|
language === lang
|
||||||
|
? color === 'purple'
|
||||||
|
? 'bg-purple-500/30 text-white border-purple-500/60 shadow-lg shadow-purple-500/30'
|
||||||
|
: color === 'cyan'
|
||||||
|
? 'bg-cyan-500/30 text-white border-cyan-500/60 shadow-lg shadow-cyan-500/30'
|
||||||
|
: 'bg-amber-500/30 text-white border-amber-500/60 shadow-lg shadow-amber-500/30'
|
||||||
|
: 'bg-slate-800/30 text-gray-400 border-slate-700 hover:border-slate-600 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{lang === 'javascript' ? 'JS' : lang.toUpperCase()}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Code Display - Gradient Border */}
|
||||||
|
<div className="border-2 border-cyan-500/30 rounded-xl overflow-hidden shadow-lg">
|
||||||
|
<div className="flex items-center justify-between bg-slate-950/80 px-4 py-3 border-b-2 border-cyan-500/20">
|
||||||
|
<span className="text-xs text-cyan-400 font-semibold">Code Example</span>
|
||||||
|
<button
|
||||||
|
onClick={copyCode}
|
||||||
|
className="px-3 py-1.5 text-xs bg-purple-600/30 hover:bg-purple-600/50 text-purple-300 rounded-lg transition-all font-semibold"
|
||||||
|
>
|
||||||
|
📋 Copy
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-950/50 h-80 overflow-auto">
|
||||||
|
<pre className="text-xs text-gray-300 leading-relaxed">
|
||||||
|
<code>{generateCode()}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right: Response */}
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-bold text-white mb-4 flex items-center gap-2">
|
||||||
|
<span className="text-xl">📦</span>
|
||||||
|
Response
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div className="border-2 border-purple-500/30 rounded-xl overflow-hidden shadow-lg">
|
||||||
|
<div className="bg-slate-950/80 px-4 py-3 border-b-2 border-purple-500/20">
|
||||||
|
{response && (
|
||||||
|
<span
|
||||||
|
className={`inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-bold ${
|
||||||
|
response.success
|
||||||
|
? 'bg-green-500/20 text-green-400 border-2 border-green-500/40 shadow-lg shadow-green-500/20'
|
||||||
|
: 'bg-red-500/20 text-red-400 border-2 border-red-500/40 shadow-lg shadow-red-500/20'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{response.success ? '✓ Success' : '✕ Error'}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="p-4 bg-slate-950/50 h-80 overflow-auto">
|
||||||
|
{error ? (
|
||||||
|
<div className="p-4 bg-red-500/10 border-2 border-red-500/40 rounded-xl text-red-400 text-sm shadow-lg shadow-red-500/20">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<span className="text-xl">⚠️</span>
|
||||||
|
<div>
|
||||||
|
<p className="font-semibold mb-1">Error</p>
|
||||||
|
<p className="text-xs">{error}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : response ? (
|
||||||
|
<pre className="text-xs text-gray-300 leading-relaxed">
|
||||||
|
<code>{JSON.stringify(response, null, 2)}</code>
|
||||||
|
</pre>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-center h-full">
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="text-2xl mb-3">🚀</p>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
Click <strong className="text-purple-400">"Test Now"</strong> below to see the response
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Large Test Now Button */}
|
||||||
|
<div className="px-6 pb-6">
|
||||||
|
<button
|
||||||
|
onClick={executeRequest}
|
||||||
|
disabled={!apiKey || isExecuting}
|
||||||
|
className="w-full px-8 py-4 rounded-xl bg-gradient-to-r from-purple-600 to-cyan-600 text-white text-base font-bold hover:from-purple-500 hover:to-cyan-500 transition-all disabled:opacity-50 disabled:cursor-not-allowed shadow-2xl hover:shadow-purple-500/50 hover:scale-105 flex items-center justify-center gap-3 border-2 border-purple-500/50"
|
||||||
|
>
|
||||||
|
{isExecuting ? (
|
||||||
|
<>
|
||||||
|
<span className="animate-spin">⚡</span>
|
||||||
|
<span>Executing...</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<span>⚡</span>
|
||||||
|
<span>Test Now</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
<p className="mt-3 text-xs text-gray-500 text-center">{description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
'use client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Three Column Layout - Core Wireframe Component
|
|
||||||
*
|
|
||||||
* Provides a consistent three-column layout structure used across the application.
|
|
||||||
* This is the single source of truth for column widths, breakpoints, and responsive behavior.
|
|
||||||
*
|
|
||||||
* Column Structure:
|
|
||||||
* - Left: w-64 (256px), hidden until lg breakpoint
|
|
||||||
* - Center: flex-1 (flexible, takes remaining space)
|
|
||||||
* - Right: w-56 (224px), hidden until xl breakpoint
|
|
||||||
*
|
|
||||||
* Usage Examples:
|
|
||||||
*
|
|
||||||
* 1. SubsectionNav (3 columns):
|
|
||||||
* <ThreeColumnLayout
|
|
||||||
* left={<Logo />}
|
|
||||||
* center={<NavItems />}
|
|
||||||
* right={<UserMenu />}
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* 2. Docs Layout (2 columns - left + center):
|
|
||||||
* <ThreeColumnLayout
|
|
||||||
* left={<DocsSidebar />}
|
|
||||||
* center={<DocPage />}
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* 3. Doc Page (2 columns - center + right):
|
|
||||||
* <ThreeColumnLayout
|
|
||||||
* center={<Article />}
|
|
||||||
* right={<DocsTOC />}
|
|
||||||
* />
|
|
||||||
*
|
|
||||||
* Design Principles:
|
|
||||||
* - Responsive breakpoints match Tailwind defaults (lg: 1024px, xl: 1280px)
|
|
||||||
* - Column widths ensure visual alignment across all usage contexts
|
|
||||||
* - Flexible center column adapts to available space
|
|
||||||
* - Optional columns enable 1, 2, or 3 column layouts
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ReactNode } from 'react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Props for ThreeColumnLayout component
|
|
||||||
*/
|
|
||||||
export interface ThreeColumnLayoutProps {
|
|
||||||
/** Left column content (w-64, hidden until lg breakpoint) */
|
|
||||||
left?: ReactNode;
|
|
||||||
|
|
||||||
/** Center column content (flex-1, always visible) */
|
|
||||||
center: ReactNode;
|
|
||||||
|
|
||||||
/** Right column content (w-56, hidden until xl breakpoint) */
|
|
||||||
right?: ReactNode;
|
|
||||||
|
|
||||||
/** Additional classes for left column */
|
|
||||||
leftClassName?: string;
|
|
||||||
|
|
||||||
/** Additional classes for center column */
|
|
||||||
centerClassName?: string;
|
|
||||||
|
|
||||||
/** Additional classes for right column */
|
|
||||||
rightClassName?: string;
|
|
||||||
|
|
||||||
/** Additional classes for container */
|
|
||||||
containerClassName?: string;
|
|
||||||
|
|
||||||
/** Breakpoint for showing left column (default: 'lg') */
|
|
||||||
leftBreakpoint?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
||||||
|
|
||||||
/** Breakpoint for showing right column (default: 'xl') */
|
|
||||||
rightBreakpoint?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Three Column Layout Component
|
|
||||||
*
|
|
||||||
* Core wireframe for consistent three-column layouts across the application.
|
|
||||||
* Handles responsive behavior and provides customization via className props.
|
|
||||||
*/
|
|
||||||
export const ThreeColumnLayout = ({
|
|
||||||
left,
|
|
||||||
center,
|
|
||||||
right,
|
|
||||||
leftClassName = '',
|
|
||||||
centerClassName = '',
|
|
||||||
rightClassName = '',
|
|
||||||
containerClassName = '',
|
|
||||||
leftBreakpoint = 'lg',
|
|
||||||
rightBreakpoint = 'xl',
|
|
||||||
}: ThreeColumnLayoutProps) => {
|
|
||||||
// Generate responsive visibility classes
|
|
||||||
const leftHidden = `hidden ${leftBreakpoint}:block`;
|
|
||||||
const rightHidden = `hidden ${rightBreakpoint}:block`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`flex ${containerClassName}`}>
|
|
||||||
{/* Left Column - w-64 (256px) */}
|
|
||||||
{left && (
|
|
||||||
<div className={`${leftHidden} w-64 shrink-0 ${leftClassName}`}>
|
|
||||||
{left}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Center Column - flex-1 (flexible) */}
|
|
||||||
<div className={`flex-1 min-w-0 ${centerClassName}`}>
|
|
||||||
{center}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right Column - w-56 (224px) */}
|
|
||||||
{right && (
|
|
||||||
<div className={`${rightHidden} w-56 shrink-0 ${rightClassName}`}>
|
|
||||||
{right}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -9,24 +9,17 @@
|
||||||
* - Active state indicator (purple color)
|
* - Active state indicator (purple color)
|
||||||
* - Optional API Key input on the right
|
* - Optional API Key input on the right
|
||||||
* - Responsive (hamburger menu on mobile)
|
* - Responsive (hamburger menu on mobile)
|
||||||
* - Three-column layout matching docs structure
|
* - Can be reused across landing app sections
|
||||||
* - Customizable left/right slots
|
|
||||||
*
|
|
||||||
* Uses ThreeColumnLayout for consistent alignment with docs pages.
|
|
||||||
* Columns align with docs layout at all screen widths.
|
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* <SubsectionNav
|
* <SubsectionNav
|
||||||
* items={[...]}
|
* items={[...]}
|
||||||
* currentPath="/docs/final"
|
* currentPath="/docs/final"
|
||||||
* showApiKeyInput={true}
|
* showApiKeyInput={true}
|
||||||
* leftSlot={<Logo />}
|
|
||||||
* rightSlot={<UserMenu />}
|
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState, useEffect, useRef, ReactNode } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
import { ThreeColumnLayout } from '@/components/layout/ThreeColumnLayout';
|
|
||||||
|
|
||||||
interface NavItem {
|
interface NavItem {
|
||||||
label: string;
|
label: string;
|
||||||
|
|
@ -40,10 +33,6 @@ interface SubsectionNavProps {
|
||||||
ctaHref?: string;
|
ctaHref?: string;
|
||||||
onCtaClick?: () => void;
|
onCtaClick?: () => void;
|
||||||
showApiKeyInput?: boolean;
|
showApiKeyInput?: boolean;
|
||||||
/** Optional content for left column (w-64, hidden until lg) */
|
|
||||||
leftSlot?: ReactNode;
|
|
||||||
/** Optional content for right column (w-56, hidden until xl). If not provided and showApiKeyInput is true, API key input is used. */
|
|
||||||
rightSlot?: ReactNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
const API_KEY_STORAGE = 'banatie_docs_api_key';
|
||||||
|
|
@ -52,8 +41,6 @@ export const SubsectionNav = ({
|
||||||
items,
|
items,
|
||||||
currentPath,
|
currentPath,
|
||||||
showApiKeyInput = false,
|
showApiKeyInput = false,
|
||||||
leftSlot,
|
|
||||||
rightSlot,
|
|
||||||
}: SubsectionNavProps) => {
|
}: SubsectionNavProps) => {
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||||
const [apiKey, setApiKey] = useState('');
|
const [apiKey, setApiKey] = useState('');
|
||||||
|
|
@ -123,8 +110,32 @@ export const SubsectionNav = ({
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Desktop API Key Input Component
|
return (
|
||||||
const apiKeyComponent = showApiKeyInput && (
|
<nav className="sticky top-0 z-40 bg-slate-950/80 backdrop-blur-sm border-b border-white/10">
|
||||||
|
{/* Main Nav Container */}
|
||||||
|
<div className="max-w-7xl mx-auto px-6">
|
||||||
|
<div className="flex items-center justify-between h-12">
|
||||||
|
{/* Desktop Navigation */}
|
||||||
|
<div className="hidden md:flex items-center gap-8">
|
||||||
|
{items.map((item) => {
|
||||||
|
const active = isActive(item.href);
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className={`
|
||||||
|
py-3 text-sm font-medium transition-colors
|
||||||
|
${active ? 'text-purple-400' : 'text-gray-400 hover:text-white'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Side: API Key Input (Desktop) */}
|
||||||
|
{showApiKeyInput && (
|
||||||
<div className="hidden md:block relative" ref={dropdownRef}>
|
<div className="hidden md:block relative" ref={dropdownRef}>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsApiKeyExpanded(!isApiKeyExpanded)}
|
onClick={() => setIsApiKeyExpanded(!isApiKeyExpanded)}
|
||||||
|
|
@ -241,37 +252,10 @@ export const SubsectionNav = ({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
)}
|
||||||
|
|
||||||
return (
|
{/* Mobile Menu Button */}
|
||||||
<nav className="sticky top-0 z-40 bg-slate-950/80 backdrop-blur-sm border-b border-white/10">
|
<div className="md:hidden flex items-center ml-auto">
|
||||||
{/* Three-Column Layout */}
|
|
||||||
<ThreeColumnLayout
|
|
||||||
left={leftSlot}
|
|
||||||
center={
|
|
||||||
<div className="max-w-7xl mx-auto px-6">
|
|
||||||
<div className="flex items-center justify-between h-12">
|
|
||||||
{/* Desktop Navigation Items */}
|
|
||||||
<div className="hidden md:flex items-center gap-8">
|
|
||||||
{items.map((item) => {
|
|
||||||
const active = isActive(item.href);
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
key={item.href}
|
|
||||||
href={item.href}
|
|
||||||
className={`
|
|
||||||
py-3 text-sm font-medium transition-colors
|
|
||||||
${active ? 'text-purple-400' : 'text-gray-400 hover:text-white'}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Mobile Menu Button */}
|
|
||||||
<div className="md:hidden flex items-center ml-auto">
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
className="p-2 text-gray-400 hover:text-white transition-colors"
|
className="p-2 text-gray-400 hover:text-white transition-colors"
|
||||||
|
|
@ -300,12 +284,9 @@ export const SubsectionNav = ({
|
||||||
)}
|
)}
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
</div>
|
||||||
right={rightSlot || apiKeyComponent}
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Decorative Wave Line */}
|
{/* Decorative Wave Line */}
|
||||||
<div className="absolute bottom-0 left-0 right-0 h-px overflow-hidden">
|
<div className="absolute bottom-0 left-0 right-0 h-px overflow-hidden">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue