fix: page

This commit is contained in:
Oleg Proskurin 2025-12-03 15:08:36 +07:00
parent 7588817803
commit 21ac410780
5 changed files with 235 additions and 108 deletions

View File

@ -10,17 +10,18 @@
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"react": "19.1.0", "@banatie/database": "workspace:*",
"react-dom": "19.1.0", "lucide-react": "^0.400.0",
"next": "15.5.4", "next": "15.5.4",
"@banatie/database": "workspace:*" "react": "19.1.0",
"react-dom": "19.1.0"
}, },
"devDependencies": { "devDependencies": {
"typescript": "^5", "@tailwindcss/postcss": "^4",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",
"@tailwindcss/postcss": "^4", "tailwindcss": "^4",
"tailwindcss": "^4" "typescript": "^5"
} }
} }

View File

@ -45,6 +45,15 @@ body {
} }
} }
@keyframes gradient-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.animate-gradient { .animate-gradient {
background-size: 200% 200%; background-size: 200% 200%;
animation: gradient-shift 3s ease infinite; animation: gradient-shift 3s ease infinite;

View File

@ -0,0 +1,55 @@
interface AnimatedGradientBorderProps {
children: React.ReactNode;
className?: string;
}
const gradientStyle: React.CSSProperties = {
background: `conic-gradient(
from 0deg,
rgba(99, 102, 241, 0.3),
rgba(139, 92, 246, 0.8),
rgba(236, 72, 153, 0.6),
rgba(34, 211, 238, 0.8),
rgba(99, 102, 241, 0.3)
)`,
filter: 'blur(40px)',
};
const glowStyle: React.CSSProperties = {
background: `conic-gradient(
from 0deg,
rgba(99, 102, 241, 0.1),
rgba(139, 92, 246, 0.4),
rgba(236, 72, 153, 0.3),
rgba(34, 211, 238, 0.4),
rgba(99, 102, 241, 0.1)
)`,
filter: 'blur(15px)',
};
export const AnimatedGradientBorder = ({
children,
className = '',
}: AnimatedGradientBorderProps) => {
return (
<div className={`relative p-10 rounded-xl isolate ${className}`}>
<div
className="absolute -inset-16 pointer-events-none"
style={{
maskImage: 'radial-gradient(ellipse closest-side at center, black 0%, black 50%, transparent 100%)',
WebkitMaskImage: 'radial-gradient(ellipse closest-side at center, black 0%, black 50%, transparent 100%)',
}}
>
<div
className="absolute inset-[-52%] opacity-60 -z-10 animate-[gradient-rotate_4s_linear_infinite]"
style={glowStyle}
/>
<div
className="absolute inset-[-50%] z-0 animate-[gradient-rotate_4s_linear_infinite]"
style={gradientStyle}
/>
</div>
<div className="relative z-10 bg-[#0a0612] rounded-[10px]">{children}</div>
</div>
);
};

View File

@ -1,6 +1,7 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState } from 'react';
import { AnimatedGradientBorder } from './components/AnimatedGradientBorder';
import { import {
Zap, Zap,
Globe, Globe,
@ -42,12 +43,6 @@ import {
const customStyles = ` const customStyles = `
@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@500;600;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Caveat:wght@500;600;700&display=swap');
@property --form-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
.gradient-text { .gradient-text {
background: linear-gradient(90deg, #818cf8 0%, #c084fc 25%, #f472b6 50%, #c084fc 75%, #818cf8 100%); background: linear-gradient(90deg, #818cf8 0%, #c084fc 25%, #f472b6 50%, #c084fc 75%, #818cf8 100%);
background-size: 200% 100%; background-size: 200% 100%;
@ -63,47 +58,6 @@ const customStyles = `
100% { background-position: 100% 50%; } 100% { background-position: 100% 50%; }
} }
.email-form-wrapper {
position: relative;
max-width: 28rem;
margin: 0 auto;
padding: 2px;
border-radius: 12px;
background: linear-gradient(#0a0612, #0a0612) padding-box,
conic-gradient(from var(--form-angle),
rgba(99, 102, 241, 0.3),
rgba(139, 92, 246, 0.8),
rgba(236, 72, 153, 0.6),
rgba(34, 211, 238, 0.8),
rgba(99, 102, 241, 0.3)
) border-box;
animation: form-glow-rotate 4s linear infinite;
}
.email-form-wrapper::before {
content: '';
position: absolute;
inset: -2px;
border-radius: 14px;
background: conic-gradient(from var(--form-angle),
rgba(99, 102, 241, 0.1),
rgba(139, 92, 246, 0.4),
rgba(236, 72, 153, 0.3),
rgba(34, 211, 238, 0.4),
rgba(99, 102, 241, 0.1)
);
filter: blur(15px);
opacity: 0.6;
z-index: -1;
animation: form-glow-rotate 4s linear infinite;
}
@keyframes form-glow-rotate {
to {
--form-angle: 360deg;
}
}
.beta-dot { .beta-dot {
animation: beta-dot-delay 20s linear forwards, beta-dot-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) 20s infinite; animation: beta-dot-delay 20s linear forwards, beta-dot-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) 20s infinite;
} }
@ -138,12 +92,30 @@ const customStyles = `
function BackgroundBlobs() { function BackgroundBlobs() {
const blobs = [ const blobs = [
{ className: 'w-[600px] h-[600px] top-[-200px] right-[-100px]', gradient: 'rgba(139, 92, 246, 0.3)' }, {
{ className: 'w-[500px] h-[500px] top-[800px] left-[-150px]', gradient: 'rgba(99, 102, 241, 0.25)' }, className: 'w-[600px] h-[600px] top-[-200px] right-[-100px]',
{ className: 'w-[400px] h-[400px] top-[1600px] right-[-100px]', gradient: 'rgba(236, 72, 153, 0.2)' }, gradient: 'rgba(139, 92, 246, 0.3)',
{ className: 'w-[550px] h-[550px] top-[2400px] left-[-200px]', gradient: 'rgba(34, 211, 238, 0.15)' }, },
{ className: 'w-[450px] h-[450px] top-[3200px] right-[-150px]', gradient: 'rgba(139, 92, 246, 0.25)' }, {
{ className: 'w-[500px] h-[500px] top-[4000px] left-[-100px]', gradient: 'rgba(99, 102, 241, 0.2)' }, className: 'w-[500px] h-[500px] top-[800px] left-[-150px]',
gradient: 'rgba(99, 102, 241, 0.25)',
},
{
className: 'w-[400px] h-[400px] top-[1600px] right-[-100px]',
gradient: 'rgba(236, 72, 153, 0.2)',
},
{
className: 'w-[550px] h-[550px] top-[2400px] left-[-200px]',
gradient: 'rgba(34, 211, 238, 0.15)',
},
{
className: 'w-[450px] h-[450px] top-[3200px] right-[-150px]',
gradient: 'rgba(139, 92, 246, 0.25)',
},
{
className: 'w-[500px] h-[500px] top-[4000px] left-[-100px]',
gradient: 'rgba(99, 102, 241, 0.2)',
},
]; ];
return ( return (
@ -164,7 +136,8 @@ function HeroGlow() {
<div <div
className="absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-[1200px] h-[600px] pointer-events-none" className="absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-[1200px] h-[600px] pointer-events-none"
style={{ style={{
background: 'radial-gradient(ellipse at center top, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.1) 30%, transparent 70%)', background:
'radial-gradient(ellipse at center top, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.1) 30%, transparent 70%)',
}} }}
/> />
); );
@ -246,7 +219,9 @@ function HeroSection() {
: 'bg-indigo-500/15 border border-indigo-500/30 text-indigo-300' : 'bg-indigo-500/15 border border-indigo-500/30 text-indigo-300'
}`} }`}
> >
<badge.icon className={`w-4 h-4 ${badge.variant === 'cyan' ? 'text-cyan-400' : 'text-indigo-400'}`} /> <badge.icon
className={`w-4 h-4 ${badge.variant === 'cyan' ? 'text-cyan-400' : 'text-indigo-400'}`}
/>
{badge.text} {badge.text}
</span> </span>
))} ))}
@ -277,13 +252,17 @@ function ApiExampleSection() {
<div className="bg-black/50 border border-indigo-500/20 rounded-lg p-4 font-mono text-sm overflow-x-auto mb-4"> <div className="bg-black/50 border border-indigo-500/20 rounded-lg p-4 font-mono text-sm overflow-x-auto mb-4">
<div className="text-gray-500 mb-2"># Generate an image</div> <div className="text-gray-500 mb-2"># Generate an image</div>
<span className="text-cyan-400">curl</span> <span className="text-gray-300">-X POST https://api.banatie.app/v1/generate \</span> <span className="text-cyan-400">curl</span>{' '}
<span className="text-gray-300">-X POST https://api.banatie.app/v1/generate \</span>
<br /> <br />
<span className="text-gray-300 ml-4">-H</span> <span className="text-green-400">&quot;Authorization: Bearer $API_KEY&quot;</span>{' '} <span className="text-gray-300 ml-4">-H</span>{' '}
<span className="text-green-400">&quot;Authorization: Bearer $API_KEY&quot;</span>{' '}
<span className="text-gray-300">\</span> <span className="text-gray-300">\</span>
<br /> <br />
<span className="text-gray-300 ml-4">-d</span>{' '} <span className="text-gray-300 ml-4">-d</span>{' '}
<span className="text-green-400">&apos;{`{"prompt": "modern office interior, natural light"}`}&apos;</span> <span className="text-green-400">
&apos;{`{"prompt": "modern office interior, natural light"}`}&apos;
</span>
</div> </div>
<div className="bg-black/50 border border-indigo-500/20 rounded-lg p-4 font-mono text-sm overflow-x-auto"> <div className="bg-black/50 border border-indigo-500/20 rounded-lg p-4 font-mono text-sm overflow-x-auto">
@ -291,11 +270,15 @@ function ApiExampleSection() {
<span className="text-gray-300">{'{'}</span> <span className="text-gray-300">{'{'}</span>
<br /> <br />
<span className="text-purple-400 ml-4">&quot;url&quot;</span> <span className="text-purple-400 ml-4">&quot;url&quot;</span>
<span className="text-gray-300">:</span> <span className="text-green-400">&quot;https://cdn.banatie.app/img/a7x2k9.png&quot;</span> <span className="text-gray-300">:</span>{' '}
<span className="text-green-400">
&quot;https://cdn.banatie.app/img/a7x2k9.png&quot;
</span>
<span className="text-gray-300">,</span> <span className="text-gray-300">,</span>
<br /> <br />
<span className="text-purple-400 ml-4">&quot;enhanced_prompt&quot;</span> <span className="text-purple-400 ml-4">&quot;enhanced_prompt&quot;</span>
<span className="text-gray-300">:</span> <span className="text-green-400">&quot;A photorealistic modern office...&quot;</span> <span className="text-gray-300">:</span>{' '}
<span className="text-green-400">&quot;A photorealistic modern office...&quot;</span>
<span className="text-gray-300">,</span> <span className="text-gray-300">,</span>
<br /> <br />
<span className="text-purple-400 ml-4">&quot;generation_time&quot;</span> <span className="text-purple-400 ml-4">&quot;generation_time&quot;</span>
@ -348,8 +331,12 @@ function ProblemSolutionSection() {
return ( return (
<section className="py-20 px-6"> <section className="py-20 px-6">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<h2 className="text-3xl md:text-4xl font-bold text-center mb-4">Why developers choose Banatie</h2> <h2 className="text-3xl md:text-4xl font-bold text-center mb-4">
<p className="text-gray-400 text-center mb-16 max-w-2xl mx-auto">Stop fighting your image workflow. Start building.</p> Why developers choose Banatie
</h2>
<p className="text-gray-400 text-center mb-16 max-w-2xl mx-auto">
Stop fighting your image workflow. Start building.
</p>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6"> <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
{problems.map((item, i) => ( {problems.map((item, i) => (
@ -390,11 +377,14 @@ function PromptUrlsSection() {
<Sparkles className="w-6 h-6 text-cyan-400" /> <Sparkles className="w-6 h-6 text-cyan-400" />
</div> </div>
<div> <div>
<span className="inline-block px-3 py-1 bg-cyan-500/20 text-cyan-300 text-xs rounded-full mb-2">Unique</span> <span className="inline-block px-3 py-1 bg-cyan-500/20 text-cyan-300 text-xs rounded-full mb-2">
Unique
</span>
<h2 className="text-2xl font-bold mb-2">Prompt URLs Images via HTML</h2> <h2 className="text-2xl font-bold mb-2">Prompt URLs Images via HTML</h2>
<p className="text-gray-400"> <p className="text-gray-400">
Put a prompt in your <code className="text-cyan-300 bg-black/30 px-1 rounded">img src</code> and get a real image. No API calls. No Put a prompt in your{' '}
JavaScript. Just HTML. <code className="text-cyan-300 bg-black/30 px-1 rounded">img src</code> and get a
real image. No API calls. No JavaScript. Just HTML.
</p> </p>
</div> </div>
</div> </div>
@ -402,15 +392,22 @@ function PromptUrlsSection() {
<div className="bg-black/50 border border-indigo-500/20 rounded-lg p-4 font-mono text-sm overflow-x-auto"> <div className="bg-black/50 border border-indigo-500/20 rounded-lg p-4 font-mono text-sm overflow-x-auto">
<span className="text-gray-500">&lt;!-- Write this --&gt;</span> <span className="text-gray-500">&lt;!-- Write this --&gt;</span>
<br /> <br />
<span className="text-purple-400">&lt;img</span> <span className="text-cyan-300">src</span>= <span className="text-purple-400">&lt;img</span>{' '}
<span className="text-green-400">&quot;https://cdn.banatie.app/gen?p=modern office interior&quot;</span>{' '} <span className="text-cyan-300">src</span>=
<span className="text-green-400">
&quot;https://cdn.banatie.app/gen?p=modern office interior&quot;
</span>{' '}
<span className="text-purple-400">/&gt;</span> <span className="text-purple-400">/&gt;</span>
<br /> <br />
<br /> <br />
<span className="text-gray-500">&lt;!-- Get this: production-ready image, cached, CDN-delivered --&gt;</span> <span className="text-gray-500">
&lt;!-- Get this: production-ready image, cached, CDN-delivered --&gt;
</span>
</div> </div>
<p className="text-gray-500 text-sm mt-4">Perfect for static sites, prototypes, and AI coding agents that generate HTML.</p> <p className="text-gray-500 text-sm mt-4">
Perfect for static sites, prototypes, and AI coding agents that generate HTML.
</p>
</div> </div>
</div> </div>
</section> </section>
@ -438,8 +435,12 @@ function HowItWorksSection() {
return ( return (
<section className="py-20 px-6"> <section className="py-20 px-6">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<h2 className="text-3xl md:text-4xl font-bold text-center mb-4">Your prompt. Your control. Production-ready.</h2> <h2 className="text-3xl md:text-4xl font-bold text-center mb-4">
<p className="text-gray-400 text-center mb-16 max-w-2xl mx-auto">We handle the complexity so you can focus on building.</p> Your prompt. Your control. Production-ready.
</h2>
<p className="text-gray-400 text-center mb-16 max-w-2xl mx-auto">
We handle the complexity so you can focus on building.
</p>
<div className="max-w-4xl mx-auto"> <div className="max-w-4xl mx-auto">
<div className="grid md:grid-cols-4 gap-4 mb-8"> <div className="grid md:grid-cols-4 gap-4 mb-8">
@ -491,42 +492,48 @@ function KeyFeaturesSection() {
icon: AtSign, icon: AtSign,
iconColor: 'text-pink-400', iconColor: 'text-pink-400',
title: 'Reference Images', title: 'Reference Images',
description: 'Use @aliases to maintain style consistency across your project. Reference up to 3 images per generation.', description:
'Use @aliases to maintain style consistency across your project. Reference up to 3 images per generation.',
isUnique: false, isUnique: false,
}, },
{ {
icon: GitBranch, icon: GitBranch,
iconColor: 'text-purple-400', iconColor: 'text-purple-400',
title: 'Flows', title: 'Flows',
description: 'Chain generations, iterate on results, build image sequences with @last and @first references.', description:
'Chain generations, iterate on results, build image sequences with @last and @first references.',
isUnique: false, isUnique: false,
}, },
{ {
icon: Palette, icon: Palette,
iconColor: 'text-yellow-400', iconColor: 'text-yellow-400',
title: '7 Style Templates', title: '7 Style Templates',
description: 'Same prompt, different styles. Photorealistic, illustration, minimalist, product, comic, sticker, and more.', description:
'Same prompt, different styles. Photorealistic, illustration, minimalist, product, comic, sticker, and more.',
isUnique: false, isUnique: false,
}, },
{ {
icon: Globe, icon: Globe,
iconColor: 'text-green-400', iconColor: 'text-green-400',
title: 'Instant CDN Delivery', title: 'Instant CDN Delivery',
description: 'Every image gets production-ready URL. No upload, no optimization, no hosting setup needed.', description:
'Every image gets production-ready URL. No upload, no optimization, no hosting setup needed.',
isUnique: false, isUnique: false,
}, },
{ {
icon: SlidersHorizontal, icon: SlidersHorizontal,
iconColor: 'text-blue-400', iconColor: 'text-blue-400',
title: 'Output Control', title: 'Output Control',
description: 'Control aspect ratio, dimensions, and format. From square thumbnails to ultra-wide banners.', description:
'Control aspect ratio, dimensions, and format. From square thumbnails to ultra-wide banners.',
isUnique: false, isUnique: false,
}, },
{ {
icon: Link, icon: Link,
iconColor: 'text-cyan-400', iconColor: 'text-cyan-400',
title: 'Prompt URLs', title: 'Prompt URLs',
description: 'Generate images via URL parameters. Put prompt in img src, get real image. Built-in caching.', description:
'Generate images via URL parameters. Put prompt in img src, get real image. Built-in caching.',
isUnique: true, isUnique: true,
}, },
]; ];
@ -534,8 +541,12 @@ function KeyFeaturesSection() {
return ( return (
<section className="py-20 px-6"> <section className="py-20 px-6">
<div className="max-w-6xl mx-auto"> <div className="max-w-6xl mx-auto">
<h2 className="text-3xl md:text-4xl font-bold text-center mb-4">Built for real development workflows</h2> <h2 className="text-3xl md:text-4xl font-bold text-center mb-4">
<p className="text-gray-400 text-center mb-16 max-w-2xl mx-auto">Everything you need to integrate AI images into your projects.</p> Built for real development workflows
</h2>
<p className="text-gray-400 text-center mb-16 max-w-2xl mx-auto">
Everything you need to integrate AI images into your projects.
</p>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{features.map((feature, i) => ( {features.map((feature, i) => (
@ -552,7 +563,11 @@ function KeyFeaturesSection() {
</div> </div>
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<h3 className="font-semibold text-lg">{feature.title}</h3> <h3 className="font-semibold text-lg">{feature.title}</h3>
{feature.isUnique && <span className="px-2 py-0.5 bg-cyan-500/20 text-cyan-300 text-xs rounded">Unique</span>} {feature.isUnique && (
<span className="px-2 py-0.5 bg-cyan-500/20 text-cyan-300 text-xs rounded">
Unique
</span>
)}
</div> </div>
<p className="text-gray-400 text-sm">{feature.description}</p> <p className="text-gray-400 text-sm">{feature.description}</p>
</div> </div>
@ -581,7 +596,9 @@ function IntegrationsSection() {
<section className="py-20 px-6"> <section className="py-20 px-6">
<div className="max-w-6xl mx-auto text-center"> <div className="max-w-6xl mx-auto text-center">
<h2 className="text-3xl md:text-4xl font-bold mb-4">Works with your tools</h2> <h2 className="text-3xl md:text-4xl font-bold mb-4">Works with your tools</h2>
<p className="text-gray-400 mb-12 max-w-2xl mx-auto">Use what fits your workflow. All methods, same capabilities.</p> <p className="text-gray-400 mb-12 max-w-2xl mx-auto">
Use what fits your workflow. All methods, same capabilities.
</p>
<div className="flex flex-wrap justify-center gap-4 mb-8"> <div className="flex flex-wrap justify-center gap-4 mb-8">
{tools.map((tool, i) => ( {tools.map((tool, i) => (
@ -599,12 +616,15 @@ function IntegrationsSection() {
<div className="max-w-2xl mx-auto mt-8 p-4 bg-slate-900/60 border border-indigo-500/15 backdrop-blur-[10px] rounded-lg"> <div className="max-w-2xl mx-auto mt-8 p-4 bg-slate-900/60 border border-indigo-500/15 backdrop-blur-[10px] rounded-lg">
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
<strong className="text-white">Banatie Lab</strong> Official web interface for Banatie API. Generate images, build flows, browse your <strong className="text-white">Banatie Lab</strong> Official web interface for Banatie
gallery, and explore all capabilities with ready-to-use code snippets. API. Generate images, build flows, browse your gallery, and explore all capabilities
with ready-to-use code snippets.
</p> </p>
</div> </div>
<p className="text-gray-500 text-sm mt-6">Perfect for Claude Code, Cursor, and any AI-powered workflow.</p> <p className="text-gray-500 text-sm mt-6">
Perfect for Claude Code, Cursor, and any AI-powered workflow.
</p>
</div> </div>
</section> </section>
); );
@ -625,11 +645,14 @@ function ShapeTheFutureSection() {
<div className="relative my-[60px]"> <div className="relative my-[60px]">
<section className="shape-future bg-[#2a2a2a] relative z-[2]"> <section className="shape-future bg-[#2a2a2a] relative z-[2]">
<div className="relative z-[6] py-[60px] px-10 text-center max-w-[700px] mx-auto"> <div className="relative z-[6] py-[60px] px-10 text-center max-w-[700px] mx-auto">
<h2 className="shape-future-title text-5xl font-semibold text-[#f5f5f5] mb-4 leading-tight">Shape the future of Banatie</h2> <h2 className="shape-future-title text-5xl font-semibold text-[#f5f5f5] mb-4 leading-tight">
Shape the future of Banatie
</h2>
<p className="text-[1.05rem] text-[#a0a0a0] mb-6 leading-relaxed"> <p className="text-[1.05rem] text-[#a0a0a0] mb-6 leading-relaxed">
We&apos;re building this for developers like you. Early adopters get direct influence on our roadmap suggest features, vote on We&apos;re building this for developers like you. Early adopters get direct influence on
priorities, and help us build exactly what you need. our roadmap suggest features, vote on priorities, and help us build exactly what you
need.
</p> </p>
<div className="flex flex-wrap gap-6 justify-center text-[0.95rem] text-[#888]"> <div className="flex flex-wrap gap-6 justify-center text-[0.95rem] text-[#888]">
@ -666,10 +689,30 @@ function GeminiSection() {
]; ];
const capabilities = [ const capabilities = [
{ icon: Type, title: 'Perfect Text Rendering', description: 'Legible text in images — logos, diagrams, posters. What other models still struggle with.' }, {
{ icon: Brain, title: 'Native Multimodal', description: 'Understands text AND images in one model. Not a text model + image model bolted together.' }, icon: Type,
{ icon: Target, title: 'Precise Prompt Following', description: 'What you ask is what you get. No artistic "interpretation" that ignores your instructions.' }, title: 'Perfect Text Rendering',
{ icon: Image, title: 'Professional Realism', description: 'Photorealistic output that replaces stock photos. Not fantasy art — real, usable images.' }, description:
'Legible text in images — logos, diagrams, posters. What other models still struggle with.',
},
{
icon: Brain,
title: 'Native Multimodal',
description:
'Understands text AND images in one model. Not a text model + image model bolted together.',
},
{
icon: Target,
title: 'Precise Prompt Following',
description:
'What you ask is what you get. No artistic "interpretation" that ignores your instructions.',
},
{
icon: Image,
title: 'Professional Realism',
description:
'Photorealistic output that replaces stock photos. Not fantasy art — real, usable images.',
},
]; ];
return ( return (
@ -683,8 +726,9 @@ function GeminiSection() {
<h2 className="text-2xl md:text-3xl font-bold">Powered by Google Gemini</h2> <h2 className="text-2xl md:text-3xl font-bold">Powered by Google Gemini</h2>
</div> </div>
<p className="text-gray-400 max-w-2xl mx-auto"> <p className="text-gray-400 max-w-2xl mx-auto">
We chose Gemini because it&apos;s the only model family that combines native multimodal understanding with production-grade image We chose Gemini because it&apos;s the only model family that combines native
generation. Two models, optimized for different needs. multimodal understanding with production-grade image generation. Two models, optimized
for different needs.
</p> </p>
</div> </div>
@ -702,7 +746,8 @@ function GeminiSection() {
</div> </div>
</div> </div>
<p className="text-gray-400 text-sm mb-4"> <p className="text-gray-400 text-sm mb-4">
Optimized for speed and iteration. Perfect for rapid prototyping and high-volume generation. Optimized for speed and iteration. Perfect for rapid prototyping and high-volume
generation.
</p> </p>
<ul className="space-y-2 text-sm"> <ul className="space-y-2 text-sm">
{flashFeatures.map((feature, i) => ( {flashFeatures.map((feature, i) => (
@ -728,7 +773,8 @@ function GeminiSection() {
</div> </div>
</div> </div>
<p className="text-gray-400 text-sm mb-4"> <p className="text-gray-400 text-sm mb-4">
Maximum quality and creative control. For production assets and professional workflows. Maximum quality and creative control. For production assets and professional
workflows.
</p> </p>
<ul className="space-y-2 text-sm"> <ul className="space-y-2 text-sm">
{proFeatures.map((feature, i) => ( {proFeatures.map((feature, i) => (
@ -745,7 +791,9 @@ function GeminiSection() {
{/* Shared Capabilities */} {/* Shared Capabilities */}
<div className="border-t border-yellow-500/20 pt-8"> <div className="border-t border-yellow-500/20 pt-8">
<h4 className="text-center font-semibold mb-6 text-gray-300">Why Gemini outperforms competitors</h4> <h4 className="text-center font-semibold mb-6 text-gray-300">
Why Gemini outperforms competitors
</h4>
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-4"> <div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-4">
{capabilities.map((cap, i) => ( {capabilities.map((cap, i) => (
<div key={i} className="text-center p-4"> <div key={i} className="text-center p-4">
@ -762,7 +810,8 @@ function GeminiSection() {
{/* #1 Ranking Note */} {/* #1 Ranking Note */}
<p className="text-center text-gray-500 text-sm mt-8"> <p className="text-center text-gray-500 text-sm mt-8">
<Award className="w-4 h-4 inline mr-1 text-yellow-400" /> <Award className="w-4 h-4 inline mr-1 text-yellow-400" />
Gemini 2.5 Flash Image ranked #1 on LMArena for both text-to-image and image editing (August 2025) Gemini 2.5 Flash Image ranked #1 on LMArena for both text-to-image and image editing
(August 2025)
</p> </p>
</div> </div>
</div> </div>
@ -796,7 +845,8 @@ function FinalCtaSection() {
<div <div
className="absolute top-0 left-0 right-0 h-0.5 pointer-events-none" className="absolute top-0 left-0 right-0 h-0.5 pointer-events-none"
style={{ style={{
background: 'linear-gradient(90deg, transparent 0%, rgba(34, 211, 238, 0.3) 25%, rgba(34, 211, 238, 0.6) 50%, rgba(34, 211, 238, 0.3) 75%, transparent 100%)', background:
'linear-gradient(90deg, transparent 0%, rgba(34, 211, 238, 0.3) 25%, rgba(34, 211, 238, 0.6) 50%, rgba(34, 211, 238, 0.3) 75%, transparent 100%)',
}} }}
/> />
@ -804,12 +854,15 @@ function FinalCtaSection() {
<div <div
className="absolute inset-0 opacity-50 pointer-events-none" className="absolute inset-0 opacity-50 pointer-events-none"
style={{ style={{
backgroundImage: 'radial-gradient(circle at 20% 50%, rgba(34, 211, 238, 0.15) 0%, transparent 40%), radial-gradient(circle at 80% 50%, rgba(34, 211, 238, 0.1) 0%, transparent 35%)', backgroundImage:
'radial-gradient(circle at 20% 50%, rgba(34, 211, 238, 0.15) 0%, transparent 40%), radial-gradient(circle at 80% 50%, rgba(34, 211, 238, 0.1) 0%, transparent 35%)',
}} }}
/> />
<div className="relative z-10 max-w-3xl mx-auto text-center"> <div className="relative z-10 max-w-3xl mx-auto text-center">
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-6 text-white">Ready to build?</h2> <h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-6 text-white">
Ready to build?
</h2>
<p className="text-cyan-100/70 text-lg md:text-xl mb-10 max-w-2xl mx-auto"> <p className="text-cyan-100/70 text-lg md:text-xl mb-10 max-w-2xl mx-auto">
Join developers waiting for early access. We&apos;ll notify you when your spot is ready. Join developers waiting for early access. We&apos;ll notify you when your spot is ready.
</p> </p>
@ -822,7 +875,9 @@ function FinalCtaSection() {
<ArrowRight className="w-5 h-5 transition-transform group-hover:translate-x-[5px]" /> <ArrowRight className="w-5 h-5 transition-transform group-hover:translate-x-[5px]" />
</button> </button>
<p className="text-cyan-200/50 text-sm mt-8">No credit card required Free to start Cancel anytime</p> <p className="text-cyan-200/50 text-sm mt-8">
No credit card required Free to start Cancel anytime
</p>
</div> </div>
</section> </section>
); );

View File

@ -196,6 +196,9 @@ importers:
'@banatie/database': '@banatie/database':
specifier: workspace:* specifier: workspace:*
version: link:../../packages/database version: link:../../packages/database
lucide-react:
specifier: ^0.400.0
version: 0.400.0(react@19.1.0)
next: next:
specifier: 15.5.4 specifier: 15.5.4
version: 15.5.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) version: 15.5.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@ -9192,6 +9195,10 @@ snapshots:
dependencies: dependencies:
react: 18.3.1 react: 18.3.1
lucide-react@0.400.0(react@19.1.0):
dependencies:
react: 19.1.0
magic-string@0.30.19: magic-string@0.30.19:
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5