Introduction
AdStudio is an AI-powered advertisement generation platform built on Next.js. It allows anyone — from independent creators to large marketing teams — to generate stunning, professional ad images in seconds using a simple text prompt.
Under the hood, AdStudio uses Hugging Face Inference API to generate images and Cloudinary to store, manage, and deliver them at scale. There is no traditional backend database — everything is stored as metadata inside Cloudinary.
Instant Generation
Ad images in 10–25 seconds via HF Stable Diffusion.
5 Visual Styles
Minimalist, Bold, Luxury, Playful, Corporate.
Ad Dashboard
View, preview, and manage all your generated ads.
AdStudio is currently in v1.0. The API is stable for all features documented here.
Quick Start
5 minGet your first AI-generated ad in under 5 minutes. Follow these steps:
Create an account
Open the Ad Studio
Write your prompt
A premium noise-cancelling headphone for professionals.
Target audience: remote workers aged 25–40.
Highlight: 40-hour battery life and studio-quality sound.Choose a visual style
(Optional) Upload a reference image
Click Generate
Your ad is automatically saved to Cloudinary and appears in your /dashboard. No manual saving needed.
Authentication
AdStudio uses Clerk for authentication. All pages under /dashboard, /studio, and /preview require a signed-in user.
Unauthenticated users are automatically redirected to /sign-in. After signing in, they are returned to the page they originally requested.
Auth Routes
/sign-inSign in with email or Google/sign-upCreate a new account/dashboardProtected — requires auth/studioProtected — requires authAPI routes (/api/*) do not enforce Clerk authentication directly — they rely on server-side environment variable secrets. Never expose your HUGGINGFACE_API_KEY or CLOUDINARY_API_SECRET to the client.
Ad Studio
The Ad Studio (/studio) is the core generation interface. It combines a prompt input, style selector, optional reference image upload, and the generated result viewer.
Prompt Input
A text area for your product/campaign description. Be as detailed as possible — include target audience, platform, and key selling points.
Image Uploader
Optional. Upload a PNG/JPEG/WEBP reference image (max 10MB). It is uploaded to Cloudinary (/uploads), then passed to Hugging Face as base64 data.
Generate Button
Triggers a POST to /api/generate. Disabled during loading. Shows a spinner while Hugging Face processes.
Result Viewer
Displays the generated image inline. Shows the Cloudinary URL, the prompt used, and a "View in Dashboard" link.
Generation typically takes 10–25 seconds. The API call is synchronous — the route handler waits for Hugging Face to respond before returning. Always show a loading state in custom integrations.
Visual Styles
AdStudio supports five visual styles, each with a unique prompt template sent to Hugging Face:
Minimalist
Clean white space, simple typography, single focal point, minimal color palette (2–3 colors). Perfect for SaaS, lifestyle, and luxury goods.
Bold
High contrast, strong typography, vivid saturated colors, dramatic composition. Ideal for consumer electronics, sports, and events.
Luxury
Dark moody backgrounds, gold/silver accents, elegant serif typography, cinematic lighting. Best for premium products, jewelry, watches.
Playful
Bright fun colors, rounded shapes, whimsical elements, energetic composition. Great for food, kids products, and entertainment.
Corporate
Professional blue/grey palette, clean layout, trustworthy imagery, clear hierarchy. Perfect for B2B, finance, and professional services.
// Style identifier sent to /api/generate
// Valid values:
const styles = ['minimalist', 'bold', 'luxury', 'playful', 'corporate']
await fetch('/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'Your product description',
style: 'bold' // one of the above
})
})Reference Images
You can upload a reference image to guide Hugging Face's output. This is useful for maintaining brand consistency, matching a specific visual direction, or using an existing product photo as context.
Upload Flow
Upload the image (POST /api/upload)
multipart/form-data request with the file. The server uploads it to Cloudinary and returns the URL.const formData = new FormData();
formData.append('file', fileInput.files[0]);
const res = await fetch('/api/upload', {
method: 'POST',
body: formData
});
const { data } = await res.json();
// data.url → Cloudinary URL
// data.publicId → Cloudinary public IDPass URL to /api/generate
referenceImageUrl in the generate request.await fetch('/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'Premium headphones for remote workers',
style: 'minimalist',
referenceImageUrl: data.url // from step 1
})
})Supported formats: JPEG, PNG, WEBP. Maximum file size: 10MB. Images are stored in Cloudinary's adstudio/uploads/ folder.
Dashboard Overview
The Dashboard (/dashboard) is your central gallery for all generated ads. It fetches up to 20 most recent ads from Cloudinary via GET /api/ads.
Gallery View
Responsive grid showing all generated ads with thumbnail, prompt summary, and creation date.
Auto-refresh
Dashboard fetches fresh data on every page load. Ads appear within seconds of generation.
Ad Cards
Each card shows the image, style used, and date. Click to open the full preview page.
Managing Ads
All ads generated through AdStudio are stored in Cloudinary with rich metadata. Each ad includes:
{
"url": "https://res.cloudinary.com/.../adstudio/generated/abc123",
"publicId": "adstudio/generated/abc123",
"context": {
"prompt": "Premium headphones for remote workers",
"style": "minimalist",
"created_at": "2026-04-05T12:00:00Z",
"source": "huggingface"
}
}You can use the Cloudinary URL directly in your campaigns, landing pages, or social media posts. All images are served through Cloudinary's CDN with automatic optimization (f_auto,q_auto).
Ad Preview
Each ad has a dedicated preview page at /preview/[id] where [id] is the URL-encoded Cloudinary public ID.
The preview page is a Server Component — it fetches the ad data server-side for fast first load and proper SEO metadata.
# Example preview URL:
/preview/adstudio%2Fgenerated%2FxyzABC123
# Decoded public ID:
adstudio/generated/xyzABC123The preview page uses GET /api/ads/[id] internally. It returns the full ad metadata including the original prompt, style, and generation timestamp.
POST /api/generate
CoreThe primary generation endpoint. Calls Hugging Face AI and saves the result to Cloudinary.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
| prompt | string | required | Product/campaign description. Be as specific as possible. |
| style | string | required | Visual style: minimalist | bold | luxury | playful | corporate |
| referenceImageUrl | string | optional | Cloudinary URL of a reference image uploaded via /api/upload |
// Request
const response = await fetch('/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'A premium skincare serum targeting women 30–50. Highlight: anti-aging, dermatologist tested.',
style: 'luxury',
referenceImageUrl: 'https://res.cloudinary.com/...' // optional
})
});
// Response (success)
{
"success": true,
"data": {
"url": "https://res.cloudinary.com/.../adstudio/generated/abc123",
"publicId": "adstudio/generated/abc123",
"metadata": { "prompt": "...", "style": "luxury", "created_at": "..." }
}
}
// Response (error)
{
"error": "The prompt was flagged by safety filters. Please revise your description."
}Latency
POST /api/upload
Upload a user reference image to Cloudinary. Must be called before /api/generate if you want to use a reference image.
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | File (FormData) | required | Image file. Supported: JPEG, PNG, WEBP. Max size: 10MB. |
const formData = new FormData();
formData.append('file', file); // File object from <input type="file">
const response = await fetch('/api/upload', {
method: 'POST',
body: formData // do NOT set Content-Type header manually
});
// Response (success)
{
"success": true,
"data": {
"url": "https://res.cloudinary.com/.../adstudio/uploads/xyz",
"publicId": "adstudio/uploads/xyz",
"width": 1024,
"height": 1024
}
}GET /api/ads
Returns the 20 most recently generated ads from Cloudinary, tagged adstudio-generated. Used by the Dashboard page.
const response = await fetch('/api/ads');
const { data } = await response.json();
// data is an array of ad objects:
[
{
"url": "https://res.cloudinary.com/.../abc",
"publicId": "adstudio/generated/abc",
"context": {
"prompt": "...",
"style": "bold",
"created_at": "2026-04-05T10:00:00Z"
},
"created_at": "2026-04-05T10:00:00.000Z"
},
...
]The endpoint returns a maximum of 20 ads. Pagination support is planned for v1.1.
Environment Variables
All environment variables must be defined in your .env.local file. Never commit this file to version control.
# Clerk (Authentication)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
CLERK_SECRET_KEY=sk_live_...
# Cloudinary (Image storage)
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=123456789012345
CLOUDINARY_API_SECRET=your_api_secret
# Hugging Face (AI generation)
HUGGINGFACE_API_KEY=hf_...| Variable | Exposure | Where to get it |
|---|---|---|
| NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY | Client + Server | clerk.com → API Keys |
| CLERK_SECRET_KEY | Server only | clerk.com → API Keys |
| CLOUDINARY_CLOUD_NAME | Server only | cloudinary.com → Dashboard |
| CLOUDINARY_API_KEY | Server only | cloudinary.com → Dashboard |
| CLOUDINARY_API_SECRET | Server only | cloudinary.com → Dashboard |
| HUGGINGFACE_API_KEY | Server only | huggingface.co/settings/tokens |
HUGGINGFACE_API_KEY and CLOUDINARY_API_SECRET are server-only. Never prefix them with NEXT_PUBLIC_ or use them in client components.
Rate Limits & Quotas
Rate limits are enforced at two levels:
Free Plan
5 ad generations per calendar month. Resets on the 1st of each month.
Professional Plan
Unlimited generations. Subject to Hugging Face API fair-use policy.
Hugging Face API Quotas
Hugging Face enforces rate limits on the free tier. On HTTP 429 errors, AdStudio returns a user-friendly "try again" message.
Cloudinary Upload Size
Reference images: 10MB max. Generated images: typically 1–4MB (losslessly stored).
If you hit the Hugging Face quota limit, wait a few minutes and try again. Enterprise plans include priority queue access.