Ad Genie: AI-Powered Ad Creation Platform
Inspiration
The inspiration for Ad Genie came from a simple observation: creating high-quality advertisements requires a diverse skill set — copywriting, visual design, video production, audio engineering, and platform-specific optimization. Small businesses and solo creators often lack the budget to hire agencies or the time to master multiple tools. We asked: What if a single AI system could generate a complete, platform-ready ad campaign from just a text brief?
The breakthrough came with the emergence of Pollinations.ai — a free, no-API-key-required generative AI service offering image (Flux), video (Minimax/Hailuo), and audio (TTS) generation. This democratized access to multimodal generation and became our primary provider, with premium fallbacks (OpenAI Sora, ElevenLabs, GMI Cloud) for users needing higher fidelity.
What it does
Ad Genie is an end-to-end AI ad generation pipeline that transforms a natural-language brief into production-ready assets:
| Asset Type | Primary Provider | Fallback Providers | Output |
|---|---|---|---|
| Images | Pollinations (Flux) | GMI Cloud (Seedream/Flux), OpenAI (gpt-image-1, DALL·E 3) | 1024×1024 – 1920×1080 |
| Video | Pollinations (Minimax-video-01-live) | GMI Cloud (Seedance, Kling), OpenAI (Sora) | 1080×1920, 4–12s |
| Audio | Pollinations (TTS) | ElevenLabs (v3), OpenAI (tts-1-hd), Stability (Stable Audio) | MP3/WAV, voiceover + music |
| Copy | OpenRouter (DeepSeek V4) | OpenAI (GPT-4o) | Headlines, body, CTAs, scripts |
Key features:
- 🎯 Campaign workflow: Brief → Business profile → Asset variants → Library
- 🔐 Auth + per-user isolation: Supabase Auth + Row-Level Security
- ☁️ Durable storage: Backblaze B2 (S3-compatible) with signed URLs
- ⚡ Async generation: Genblaze Python service (FastAPI + Uvicorn) handles long-running video/audio jobs
- 🎨 Platform presets: TikTok (9:16), Reels (9:16), YouTube (16:9), Feed (1:1, 4:5)
- 📊 Analytics-ready: SHA-256 hashes, latency tracking, retry logic
How we built it
Architecture
graph LR
A[User Brief] --> B[TanStack Start Frontend]
B --> C[Supabase Auth & DB]
B --> D[Server Functions]
D --> E[Genblaze Service :8000]
E --> F[Pollinations.ai]
E --> G[OpenAI / GMI / ElevenLabs]
E --> H[Backblaze B2]
H --> I[Signed URLs → Frontend]
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | TanStack Start (React 19, Vite, SSR), Tailwind CSS 4, Radix UI |
| Backend | TanStack Start server functions, Supabase (PostgreSQL + Auth + RLS) |
| Generation | Python Genblaze service (FastAPI, Uvicorn, httpx, pydantic) |
| Storage | Backblaze B2 via aws4fetch (SigV4 signing) |
| AI Providers | Pollinations.ai (primary), OpenAI, GMI Cloud, ElevenLabs, Stability, OpenRouter |
| Infra | Netlify (frontend), Docker/VM (Genblaze), Supabase Cloud |
Core Components
1. Provider Abstraction (src/lib/adforge.functions.ts)
const GENBLAZE_PROVIDERS = {
image: [
{ provider: "pollinations", model: "flux", free: true },
{ provider: "gmicloud", model: "seedream-5.0-lite" },
{ provider: "openai", model: "gpt-image-1" },
],
video: [
{ provider: "pollinations", model: "minimax-video-01-live", free: true },
{ provider: "gmicloud", model: "seedance-2-0-260128" },
{ provider: "openai", model: "sora-2" },
],
audio: [
{ provider: "pollinations", model: "tts-1", tier: "standard", free: true },
{ provider: "elevenlabs", model: "eleven_v3", tier: "premium" },
{ provider: "openai", model: "tts-1-hd", tier: "professional" },
],
};
2. Pollinations Direct Path (bypasses Genblaze for speed)
if (provider === "pollinations") {
if (assetType === "video") {
const url = `https://gen.pollinations.ai/video/${encodeURIComponent(prompt)}?model=minimax-video-01-live&duration=${durationSec}`;
// fetch → B2 PUT → return signed key
}
// ... image & audio similar
}
3. B2 Storage with SigV4 (src/lib/b2.server.ts)
function client() {
return new AwsClient({
accessKeyId: env("B2_KEY_ID"),
secretAccessKey: env("B2_APPLICATION_KEY"),
region: env("B2_REGION"), // eu-central-1 (AWS-compatible for signing)
service: "s3",
});
}
4. Genblaze Service (python-genblaze/genblaze_service.py)
class GenerationRequest(BaseModel):
prompt: str
provider: str
model: str
asset_type: Literal["image", "video", "audio"]
width: int = 1024
height: int = 1024
duration: Optional[int] = None
# ...
@app.post("/generate/async")
async def generate_async(req: GenerationRequest):
run_id = str(uuid4())
background_tasks.add_task(execute_generation, req, run_id)
return {"run_id": run_id, "status": "pending"}
@app.get("/generate/status/{run_id}")
async def generation_status(run_id: str):
# returns { status, assets: [{url, mime_type, sha256}] }
## Challenges we ran into
### 1. **OpenAI Billing Hard Limits** 💳
> `Error code: 400 - Billing hard limit has been reached`
OpenAI's `gpt-image-1` and Sora require prepaid credits with strict limits. This forced us to make **Pollinations the default** and build intelligent fallback chains.
### 2. **Genblaze `file://` URI Handling on Windows** 🪟
Python's `Path.resolve()` on `file:///C:/...` URIs fails. Fixed in `genblaze_core/storage/transfer.py`:
```python
# Before (broken on Windows)
Path(unquote(parsed.path)).resolve()
# After (correct)
from urllib.parse import url2pathname
Path(url2pathname(unquote(parsed.path))).resolve()
3. Sora SDK Videos Object Bug 🐛
OpenAI's Python SDK returns a Videos object without .content. Patched genblaze_openai/provider.py:
# Download via HTTP instead of relying on .content
async with httpx.AsyncClient() as client:
resp = await client.get(video.url)
resp.raise_for_status()
content = resp.content
4. B2 Region Validation 🌍
aws4fetch rejects eu-central-003 (B2-specific). Solution: use AWS-compatible region eu-central-1 for signing only; actual endpoint comes from B2_ENDPOINT.
5. Supabase Project Mismatch 🔄
.env pointed to empty project shnmfnweneysrsxrdcdm while real project is nxkjjwxlgnizqsrvegba. Caused blank images (RLS blocked inserts). Fixed by aligning env vars.
6. Dual Python Site-Packages 📦
Genblaze installed in both venv/ and WindowsApps global site-packages. Both must be patched for fixes to take effect.
Accomplishments that we're proud of
| Achievement | Impact |
|---|---|
| Pollinations as universal free tier | Zero-cost image/video/audio for all users |
| End-to-end video pipeline | Sora job eaad1ca9 → 12.8 MB MP4 → B2 → signed URL ✅ |
| Unified provider abstraction | Single API for 6+ AI providers with automatic fallback |
| Windows-compatible Genblaze | Fixed file://, Sora SDK, region signing — runs natively |
| Per-user asset isolation | RLS + signed URLs = zero data leakage |
| Async generation with polling | Long video jobs don't block UI; status endpoint + WebSocket-ready |
| SHA-256 integrity + latency tracking | Every asset verifiable; performance measurable |
What we learned
Free tiers unlock adoption — Pollinations removed the biggest barrier (API keys + billing). Users try the product instantly.
Provider diversity = resilience — No single provider is 100% available. Fallback chains with automatic retry are essential.
Windows Python paths are treacherous —
file://URIs, dual site-packages, and WindowsApps Python require explicit handling.Signed URLs > public buckets — B2 +
aws4fetchSigV4 gives secure, expiring access without CORS headaches.Async first, sync later — Video generation takes 30–180s. Designing for async from day one prevented major refactors.
Environment parity matters —
.envmust match across frontend, server functions, and Genblaze service.
What's next for Ad Genie
Near Term (v1.1)
- [ ] Webhook callbacks from Genblaze → frontend (replace polling)
- [ ] Asset variants UI — A/B test multiple generations per brief
- [ ] Brand kit — Logo, colors, fonts injected into prompts automatically
- [ ] Cost tracking — Per-provider, per-campaign spend dashboard
Medium Term (v1.5)
- [ ] Video understanding — Analyze generated videos for brand safety / quality scoring
- [ ] Multi-language TTS — Pollinations voices + ElevenLabs multilingual
- [ ] Template marketplace — Community-contributed prompt templates
- [ ] Direct social posting — Meta, TikTok, YouTube API integration
Long Term (v2.0)
- [ ] Agentic campaign optimizer — Auto-iterate based on performance data
- [ ] Custom model fine-tuning — LoRA on brand assets for consistent style
- [ ] Real-time collaboration — Multiplayer editing with conflict resolution
- [ ] Enterprise SSO + audit logs — SAML/OIDC, SOC2 compliance
Built With
- aws4fetch
- backblaze-b2
- deepseek
- docker
- elevenlabs
- fastapi
- generative-ai
- gmi-cloud
- netlify
- openai
- openrouter
- pollinations-ai
- postgresl
- python
- react-19
- sora
- stability-ai
- supabase
- tailwindcss-4
- tanstack-start
- typescript
- uvicorn
- vite
Log in or sign up for Devpost to join the conversation.