doc: updates to live urls

This commit is contained in:
Oleg Proskurin 2026-01-04 15:04:26 +07:00
parent 1aa307aac9
commit 9b032eaf5a
3 changed files with 332 additions and 273 deletions

View File

@ -6,11 +6,7 @@ import { DocPage } from '@/components/docs/layout/DocPage';
import { JsonLd } from '@/components/seo/JsonLd';
import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo';
import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema';
import {
Hero,
SectionHeader,
InlineCode,
} from '@/components/docs/blocks';
import { Hero, SectionHeader, InlineCode } from '@/components/docs/blocks';
const PAGE = DOCS_PAGES['live-urls'];
@ -42,129 +38,276 @@ export default function LiveUrlsPage() {
<JsonLd data={breadcrumbSchema} />
<JsonLd data={articleSchema} />
<DocPage
breadcrumbItems={[
{ label: 'Documentation', href: '/docs/' },
{ label: 'Live URLs' },
]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/live-scopes/',
title: 'API Reference: Live Scopes',
description: 'Manage scopes and generation limits.',
accent: 'primary',
},
{
href: '/docs/generation/',
title: 'Image Generation',
description: 'Full control via the generations API.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Live URLs"
subtitle="Generate AI placeholder images and dynamic visuals directly from URL. No API calls — just use the URL in your HTML."
/>
<section id="the-concept" className="mb-12">
<SectionHeader level={2} id="the-concept">
The Concept
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Put your prompt in a URL. Use it directly in an <InlineCode>&lt;img src="..."&gt;</InlineCode> tag.
</p>
<p className="text-gray-300 leading-relaxed">
First request generates the image. All subsequent requests serve it from cache instantly.
</p>
</section>
<section id="url-format" className="mb-12">
<SectionHeader level={2} id="url-format">
URL Format
</SectionHeader>
<CodeBlock
code={`https://cdn.banatie.app/{org}/{project}/live/{scope}?prompt=...&aspectRatio=...`}
language="text"
filename="Live URL Format"
breadcrumbItems={[{ label: 'Documentation', href: '/docs/' }, { label: 'Live URLs' }]}
tocItems={tocItems}
nextSteps={{
links: [
{
href: '/docs/api/live-scopes/',
title: 'API Reference: Live Scopes',
description: 'Manage scopes and generation limits.',
accent: 'primary',
},
{
href: '/docs/generation/',
title: 'Image Generation',
description: 'Full control via the generations API.',
accent: 'secondary',
},
],
}}
>
<Hero
title="Live URLs"
subtitle="Generate images directly from URL parameters. No API calls needed — just use the URL in your HTML."
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
Query parameters:
</p>
<section id="the-concept" className="mb-12">
<SectionHeader level={2} id="the-concept">
The Concept
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-4">
Put your prompt in a URL. Use it directly in an{' '}
<InlineCode>&lt;img src="..."&gt;</InlineCode> tag.
</p>
<p className="text-gray-300 leading-relaxed">
First request generates the image. All subsequent requests serve it from cache
instantly.
</p>
</section>
<Table
headers={['Parameter', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">prompt</InlineCode>,
<span key="r" className="text-green-400">Yes</span>,
'Text description of the image to generate',
],
[
<InlineCode key="p">aspectRatio</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Image ratio: 1:1, 16:9, 9:16, 3:2 (default: 16:9)',
],
[
<InlineCode key="p">autoEnhance</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Enable prompt enhancement (default: true)',
],
[
<InlineCode key="p">template</InlineCode>,
<span key="r" className="text-gray-500">No</span>,
'Enhancement template to use',
],
]}
/>
</section>
<section id="url-format" className="mb-12">
<SectionHeader level={2} id="url-format">
URL Format
</SectionHeader>
<section id="try-it" className="mb-12">
<SectionHeader level={2} id="try-it">
Try It
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Open this URL in your browser:
</p>
<CodeBlock
code={`https://cdn.banatie.app/{org}/{project}/live/{scope}?prompt=...&aspectRatio=...`}
language="text"
filename="Live URL Format"
/>
<CodeBlock
code={`https://cdn.banatie.app/my-org/my-project/live/demo?prompt=a+friendly+robot+waving+hello&aspectRatio=16:9`}
language="text"
filename="Example Live URL"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">Query parameters:</p>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">
Or use it directly in HTML:
</p>
<Table
headers={['Parameter', 'Required', 'Description']}
rows={[
[
<InlineCode key="p">prompt</InlineCode>,
<span key="r" className="text-green-400">
Yes
</span>,
'Text description of the image to generate',
],
[
<InlineCode key="p">aspectRatio</InlineCode>,
<span key="r" className="text-gray-500">
No
</span>,
'Image ratio: 1:1, 16:9, 9:16, 3:2 (default: 16:9)',
],
[
<InlineCode key="p">template</InlineCode>,
<span key="r" className="text-gray-500">
No
</span>,
'Enhancement template to use',
],
[
<InlineCode key="p">autoEnhance</InlineCode>,
<span key="r" className="text-gray-500">
No
</span>,
'Enable prompt enhancement (default: true)',
],
]}
/>
</section>
<CodeBlock
code={`<img
<section id="try-it" className="mb-12">
<SectionHeader level={2} id="try-it">
Try It
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">Open this URL in your browser:</p>
<CodeBlock
code={`https://cdn.banatie.app/my-org/my-project/live/demo?prompt=a+friendly+robot+waving+hello&aspectRatio=16:9`}
language="text"
filename="Example Live URL"
/>
<p className="text-gray-300 leading-relaxed mt-6 mb-4">Or use it directly in HTML:</p>
<CodeBlock
code={`<img
src="https://cdn.banatie.app/my-org/my-project/live/hero?prompt=mountain+landscape+at+sunset&aspectRatio=16:9"
alt="Mountain landscape"
/>`}
language="html"
filename="HTML Usage"
/>
</section>
language="html"
filename="HTML Usage"
/>
</section>
<section id="placeholder-images" className="mb-12">
<SectionHeader level={2} id="placeholder-images">
Placeholder Images
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Live URLs are perfect for generating AI placeholder images during development.
Unlike generic placeholder services that show gray boxes or random stock photos,
Banatie generates contextual images that match your design intent.
</p>
<section id="caching-behavior" className="mb-12">
<SectionHeader level={2} id="caching-behavior">
Caching Behavior
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
The response includes an <InlineCode>X-Cache-Status</InlineCode> header:
</p>
<p className="text-gray-400 text-sm mb-4">Common placeholder sizes:</p>
<Table
headers={['Status', 'Meaning', 'Response Time']}
rows={[
[
<InlineCode key="s" color="success">
HIT
</InlineCode>,
'Image served from cache',
'Instant (milliseconds)',
],
[<InlineCode key="s">MISS</InlineCode>, 'New image generated', 'A few seconds'],
]}
/>
<CodeBlock
code={`<!-- Avatar placeholder (200×200) -->
<p className="text-gray-300 leading-relaxed mt-6">
Cache hits are unlimited and don't count toward rate limits. Only new generations (cache
MISS) are rate limited.
</p>
</section>
<section id="scopes" className="mb-12">
<SectionHeader level={2} id="scopes">
Scopes
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Scopes organize your live generations. Each scope has its own generation limit.
</p>
<CodeBlock
code={`# Different scopes for different purposes
https://cdn.banatie.app/my-org/my-project/live/hero-section?prompt=...
https://cdn.banatie.app/my-org/my-project/live/product-gallery?prompt=...
https://cdn.banatie.app/my-org/my-project/live/blog-images?prompt=...`}
language="text"
filename="Scope Examples"
/>
<p className="text-gray-300 leading-relaxed mt-6">
Scopes are auto-created on first use. You can also pre-configure them via the API to set
custom limits.
</p>
</section>
{/* <section id="rate-limits" className="mb-12">
<SectionHeader level={2} id="rate-limits">
Rate Limits
</SectionHeader>
<Table
headers={['Limit Type', 'Value', 'Notes']}
rows={[
[
'Per IP',
<span key="v" className="text-amber-400">
10 new generations/hour
</span>,
'Only applies to cache MISS',
],
[
'Per Scope',
<span key="v" className="text-amber-400">
30 generations
</span>,
'Configurable via API',
],
[
'Cache Hits',
<span key="v" className="text-green-400">
Unlimited
</span>,
'No limits on cached images',
],
]}
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
Rate limits protect the service from abuse. For high-volume needs, use the generations
API directly.
</TipBox>
</div>
</section> */}
<section id="use-cases" className="mb-12">
<SectionHeader level={2} id="use-cases">
Use Cases
</SectionHeader>
<ul className="space-y-4 text-gray-300">
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Static HTML & serverless sites</strong>
<p className="text-gray-400 text-sm mt-1">
Deploy HTML pages without configuring asset hosting or CDN infrastructure. Images
are served directly from Banatie's edge network.
</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">AI-assisted development</strong>
<p className="text-gray-400 text-sm mt-1">
Enable AI coding assistants to generate complete HTML or JSX with contextual
images in a single passno asset pipeline required.
</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Rapid prototyping</strong>
<p className="text-gray-400 text-sm mt-1">
Test different visuals without writing backend code.
</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">AI placeholder images</strong>
<p className="text-gray-400 text-sm mt-1">
Replace gray boxes and random stock photos with contextual AI images. Perfect for
prototypes, client demos, and design mockups.
</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Personalized content</strong>
<p className="text-gray-400 text-sm mt-1">
Generate unique images based on user data or preferences for dynamic,
individualized experiences.
</p>
</div>
</li>
</ul>
</section>
<section id="placeholder-images" className="mb-12">
<TipBox variant="protip">
Use Live URLs as intelligent placeholder images during development. Generate contextual
visuals that match your design intentno more gray boxes or random stock photos.
</TipBox>
<p className="text-gray-400 text-sm mt-6 mb-4">Common placeholder configurations:</p>
<CodeBlock
code={`<!-- Avatar placeholder (200×200) -->
<img src="https://cdn.banatie.app/.../live/avatars?prompt=professional+headshot&aspectRatio=1:1" />
<!-- Thumbnail placeholder (300×200) -->
@ -175,141 +318,18 @@ export default function LiveUrlsPage() {
<!-- Card image placeholder (400×300) -->
<img src="https://cdn.banatie.app/.../live/cards?prompt=abstract+gradient+background&aspectRatio=4:3" />`}
language="html"
filename="Placeholder Examples"
/>
language="html"
filename="Placeholder Examples"
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
For dark mode interfaces, include "dark theme" or "dark background" in your prompt.
</TipBox>
</div>
</section>
<div className="mt-6">
<TipBox variant="compact" type="info">
For dark mode interfaces, include "dark theme" or "dark background" in your prompt.
</TipBox>
</div>
</section>
<section id="caching-behavior" className="mb-12">
<SectionHeader level={2} id="caching-behavior">
Caching Behavior
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
The response includes an <InlineCode>X-Cache-Status</InlineCode> header:
</p>
<Table
headers={['Status', 'Meaning', 'Response Time']}
rows={[
[
<InlineCode key="s" color="success">HIT</InlineCode>,
'Image served from cache',
'Instant (milliseconds)',
],
[
<InlineCode key="s">MISS</InlineCode>,
'New image generated',
'A few seconds',
],
]}
/>
<p className="text-gray-300 leading-relaxed mt-6">
Cache hits are unlimited and don't count toward rate limits. Only new generations (cache MISS) are rate limited.
</p>
</section>
<section id="scopes" className="mb-12">
<SectionHeader level={2} id="scopes">
Scopes
</SectionHeader>
<p className="text-gray-300 leading-relaxed mb-6">
Scopes organize your live generations. Each scope has its own generation limit.
</p>
<CodeBlock
code={`# Different scopes for different purposes
https://cdn.banatie.app/my-org/my-project/live/hero-section?prompt=...
https://cdn.banatie.app/my-org/my-project/live/product-gallery?prompt=...
https://cdn.banatie.app/my-org/my-project/live/blog-images?prompt=...`}
language="text"
filename="Scope Examples"
/>
<p className="text-gray-300 leading-relaxed mt-6">
Scopes are auto-created on first use. You can also pre-configure them via the API to set custom limits.
</p>
</section>
<section id="rate-limits" className="mb-12">
<SectionHeader level={2} id="rate-limits">
Rate Limits
</SectionHeader>
<Table
headers={['Limit Type', 'Value', 'Notes']}
rows={[
[
'Per IP',
<span key="v" className="text-amber-400">10 new generations/hour</span>,
'Only applies to cache MISS',
],
[
'Per Scope',
<span key="v" className="text-amber-400">30 generations</span>,
'Configurable via API',
],
[
'Cache Hits',
<span key="v" className="text-green-400">Unlimited</span>,
'No limits on cached images',
],
]}
/>
<div className="mt-6">
<TipBox variant="compact" type="info">
Rate limits protect the service from abuse. For high-volume needs, use the generations API directly.
</TipBox>
</div>
</section>
<section id="use-cases" className="mb-12">
<SectionHeader level={2} id="use-cases">
Use Cases
</SectionHeader>
<ul className="space-y-4 text-gray-300">
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">AI Placeholder Images</strong>
<p className="text-gray-400 text-sm mt-1">
Replace gray boxes and random stock photos with contextual AI images.
Perfect for prototypes, client demos, and design mockups.
</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Personalized content</strong>
<p className="text-gray-400 text-sm mt-1">Create unique images based on user data or preferences.</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">Rapid prototyping</strong>
<p className="text-gray-400 text-sm mt-1">Test different visuals without writing backend code.</p>
</div>
</li>
<li className="flex items-start gap-3">
<span className="text-purple-400 mt-1"></span>
<div>
<strong className="text-white">HTML emails</strong>
<p className="text-gray-400 text-sm mt-1">Include dynamic images in email templates with just a URL.</p>
</div>
</li>
</ul>
</section>
</DocPage>
</DocPage>
</>
);
}

View File

@ -58,6 +58,13 @@ const navigationItems: NavItem[] = [
label: 'Authentication',
href: '/docs/authentication/',
},
{
label: 'Guides',
href: '/docs/guides/',
children: [
{ label: 'Image Placeholders', href: '/docs/guides/placeholder-images/' },
],
},
{
label: 'API Reference',
href: '/docs/api/',
@ -69,13 +76,7 @@ const navigationItems: NavItem[] = [
{ label: 'Live Scopes', href: '/docs/api/live-scopes/' },
],
},
{
label: 'Guides',
href: '/docs/guides/',
children: [
{ label: 'Image Placeholders', href: '/docs/guides/placeholder-images/' },
],
},
];
export const DocsSidebar = ({ currentPath }: DocsSidebarProps) => {

View File

@ -1,18 +1,20 @@
'use client';
import { Sparkles, Lightbulb, AlertTriangle, CheckCircle } from 'lucide-react';
/**
* TipBox Component - Dual Style System
* TipBox Component - Multi-Style Callout System
*
* Provides two distinct styles for callouts/notes:
* Provides three distinct styles for callouts/notes:
*
* 1. Compact Style (Variant A inspired):
* - Small emoji icon on left
* 1. Compact Style:
* - Lucide icon on left
* - Compact padding (p-4)
* - Smaller text (text-sm)
* - Subtle background with thin border
* - Best for minor notes and tips
*
* 2. Prominent Style (Adapted from Variant C):
* 2. Prominent Style:
* - NO icon
* - Larger padding (p-6)
* - Larger text (text-base)
@ -20,6 +22,12 @@
* - More visual weight
* - Best for important warnings and security notices
*
* 3. Protip Style:
* - Sparkles icon with "Pro Tip" label
* - Golden/amber color scheme
* - Premium visual treatment with glow
* - Best for highlighting valuable tips and tricks
*
* Usage:
* <TipBox variant="compact" type="info">
* This is a compact tip
@ -28,10 +36,14 @@
* <TipBox variant="prominent" type="warning">
* This is an important security warning
* </TipBox>
*
* <TipBox variant="protip">
* This is a valuable pro tip
* </TipBox>
*/
type TipType = 'info' | 'warning' | 'success';
type TipVariant = 'compact' | 'prominent';
type TipVariant = 'compact' | 'prominent' | 'protip';
interface TipBoxProps {
children: React.ReactNode;
@ -39,10 +51,10 @@ interface TipBoxProps {
type?: TipType;
}
const icons: Record<TipType, string> = {
info: '💡',
warning: '⚠️',
success: '✓',
const icons: Record<TipType, React.ReactNode> = {
info: <Lightbulb className="w-5 h-5 text-purple-400" />,
warning: <AlertTriangle className="w-5 h-5 text-amber-400" />,
success: <CheckCircle className="w-5 h-5 text-green-400" />,
};
const compactStyles: Record<TipType, string> = {
@ -53,23 +65,49 @@ const compactStyles: Record<TipType, string> = {
const prominentStyles: Record<TipType, string> = {
info: 'bg-gradient-to-br from-purple-500/5 via-cyan-500/5 to-purple-500/5 border-purple-500/30 text-gray-300 shadow-lg shadow-purple-500/10',
warning: 'bg-gradient-to-br from-amber-500/5 via-orange-500/5 to-amber-500/5 border-amber-500/30 text-gray-300 shadow-lg shadow-amber-500/10',
success: 'bg-gradient-to-br from-green-500/5 via-emerald-500/5 to-green-500/5 border-green-500/30 text-gray-300 shadow-lg shadow-green-500/10',
warning:
'bg-gradient-to-br from-amber-500/5 via-orange-500/5 to-amber-500/5 border-amber-500/30 text-gray-300 shadow-lg shadow-amber-500/10',
success:
'bg-gradient-to-br from-green-500/5 via-emerald-500/5 to-green-500/5 border-green-500/30 text-gray-300 shadow-lg shadow-green-500/10',
};
export const TipBox = ({ children, variant = 'compact', type = 'info' }: TipBoxProps) => {
const isCompact = variant === 'compact';
const icon = icons[type];
const styleClass = isCompact ? compactStyles[type] : prominentStyles[type];
const protipStyle =
'bg-gradient-to-r from-amber-500/15 via-yellow-500/10 to-amber-500/15 border-amber-400/40 text-amber-100 shadow-lg shadow-amber-500/20 ring-1 ring-amber-400/20';
if (isCompact) {
export const TipBox = ({ children, variant = 'compact', type = 'info' }: TipBoxProps) => {
// Protip variant - premium golden style
if (variant === 'protip') {
return (
<div
className={`flex gap-3 p-5 rounded-xl border ${protipStyle}`}
role="note"
aria-label="Pro tip"
>
<span className="flex-shrink-0 mt-0.5">
<Sparkles className="w-5 h-5 text-amber-300" />
</span>
<div>
<span className="text-xs font-semibold uppercase tracking-wider text-amber-400 block mb-1">
Pro Tip
</span>
<div className="text-sm leading-relaxed">{children}</div>
</div>
</div>
);
}
const icon = icons[type];
const styleClass = variant === 'compact' ? compactStyles[type] : prominentStyles[type];
// Compact style
if (variant === 'compact') {
return (
<div
className={`flex gap-3 p-4 rounded-xl border ${styleClass}`}
role="note"
aria-label={`${type} note`}
>
<span className="text-lg flex-shrink-0">{icon}</span>
<span className="flex-shrink-0 mt-0.5">{icon}</span>
<div className="text-sm leading-relaxed">{children}</div>
</div>
);