
Build a DALL-E 3 Image Generator App With Next.js
By Mia Thompson
6 min read
DALL-E 3 produces stunning images from text prompts. Build a polished image generation app with prompt history, style presets, and image gallery using Next.js and the OpenAI API.
What We're Building
A full-stack image generator with: a prompt input with style presets, image generation via DALL-E 3, a gallery of generated images stored in Postgres, and download functionality. This is a practical starting point for any AI-powered image feature.
The Generation API Route
// app/api/generate-image/route.ts
import OpenAI from 'openai';
import { db } from '@/lib/db';
const openai = new OpenAI();
export async function POST(request: Request) {
const { prompt, style, size } = await request.json();
// Enhance prompt with style modifier
const styleModifiers: Record<string, string> = {
photorealistic: 'photorealistic, high detail, 8K resolution',
illustration: 'digital illustration, vibrant colors, clean lines',
'3d-render': '3D render, cinema 4D, octane render, soft lighting',
watercolor: 'watercolor painting, soft washes, artistic',
};
const enhancedPrompt = style
? `${prompt}. Style: ${styleModifiers[style] ?? style}`
: prompt;
const response = await openai.images.generate({
model: 'dall-e-3',
prompt: enhancedPrompt,
n: 1,
size: size ?? '1024x1024',
quality: 'hd',
response_format: 'url',
});
const imageUrl = response.data[0].url!;
const revisedPrompt = response.data[0].revised_prompt;
// Store in database
const saved = await db.generatedImage.create({
data: {
prompt,
revisedPrompt,
imageUrl,
style,
size: size ?? '1024x1024',
},
});
return Response.json({ id: saved.id, imageUrl, revisedPrompt });
}
The Image Generator UI
'use client';
import { useState } from 'react';
const STYLES = [
{ id: 'none', label: 'No Style' },
{ id: 'photorealistic', label: 'Photo' },
{ id: 'illustration', label: 'Illustration' },
{ id: '3d-render', label: '3D Render' },
{ id: 'watercolor', label: 'Watercolor' },
];
export function ImageGenerator() {
const [prompt, setPrompt] = useState('');
const [style, setStyle] = useState('none');
const [imageUrl, setImageUrl] = useState('');
const [revisedPrompt, setRevisedPrompt] = useState('');
const [loading, setLoading] = useState(false);
async function generate() {
if (!prompt.trim()) return;
setLoading(true);
setImageUrl('');
const res = await fetch('/api/generate-image', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt, style: style === 'none' ? null : style }),
});
const data = await res.json();
setImageUrl(data.imageUrl);
setRevisedPrompt(data.revisedPrompt);
setLoading(false);
}
return (
<div className="max-w-2xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-6">AI Image Generator</h1>
<textarea
value={prompt}
onChange={e => setPrompt(e.target.value)}
placeholder="Describe the image you want to create..."
className="w-full p-3 border rounded-lg h-24 resize-none"
/>
<div className="flex gap-2 my-3">
{STYLES.map(s => (
<button
key={s.id}
onClick={() => setStyle(s.id)}
className={`px-3 py-1 rounded-full text-sm border transition-colors ${
style === s.id ? 'bg-blue-600 text-white border-blue-600' : 'hover:bg-gray-50'
}`}
>
{s.label}
</button>
))}
</div>
<button
onClick={generate}
disabled={loading || !prompt.trim()}
className="w-full py-3 bg-blue-600 text-white rounded-lg font-semibold disabled:opacity-50"
>
{loading ? 'Generating... (30-60s)' : 'Generate Image'}
</button>
{loading && (
<div className="mt-6 aspect-square bg-gray-100 rounded-xl animate-pulse flex items-center justify-center">
<p className="text-gray-400">DALL-E 3 is painting your image...</p>
</div>
)}
{imageUrl && !loading && (
<div className="mt-6">
<img src={imageUrl} alt={prompt} className="w-full rounded-xl shadow-lg" />
{revisedPrompt && (
<p className="mt-3 text-sm text-gray-500">
<strong>Revised prompt:</strong> {revisedPrompt}
</p>
)}
<a
href={imageUrl}
download="generated.png"
className="mt-3 inline-block px-4 py-2 bg-gray-800 text-white rounded text-sm"
>
Download
</a>
</div>
)}
</div>
);
}
Key DALL-E 3 Tips
- DALL-E 3 rewrites your prompt for better results — always log
revised_prompt - Use
quality: "hd"for production; it's twice the cost but significantly better - 1024x1792 and 1792x1024 are great for portrait/landscape use cases
- DALL-E 3 costs $0.040 per standard image, $0.080 per HD — factor this into your pricing
Get weekly highlights
No spam, unsubscribe anytime.
AI ChatbotSponsored
Chatbase
Build AI chatbots for your website in minutes. Train on your docs, FAQ, and PDFs.
Open SourceSponsored
Cal.com
Open source scheduling — self-host your booking system, replace Calendly. Free & privacy-first.



Comments (0)
Sign in to comment
No comments yet. Be the first to comment!