
Hi, welcome here In this tutorial, we are going to build an image generator app with OpenAi’s Dall e 2 API and Next Js. The prerequisites for this project are as follows:
- Node.js should be installed in your system.
- Create a brand new Next Js project. Just copy the code below:
npx create-next-app my-app
JavaScriptThe brand-new project should look like this:

Here is your index.js file, copy the code below and paste it into index.js. Don’t forget to add your API key.
import Head from 'next/head'
import { useState } from 'react'
import axios from 'axios';
export default function Home() {
const [token, setToken] = useState("your-api-key")
const [prompt, setPrompt] = useState("")
const [number, setNumber] = useState(4)
const [results, setResults] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState(false)
const [type, setType] = useState("png")
function generateImages () {
if (token != "" && prompt != "")
{
setError(false);
setLoading(true);
axios.post(`/api/images?t=${token}&p=${prompt}&n=${number}`).then(
(res) => {
setResults(res.data.result);
setLoading(false);
}
)
.catch((err) => {
setLoading(false);
setError(true);
});
} else {
setError(true);
}
}
function download(url) {
axios.post(`/api/download`, {url: url, type: true}).then(
(res) => {
const link = document.createElement("a");
link.href = res.data.result;
link.download = `${prompt}.${type.toLowerCase()}`;
link.click();
}
)
.catch((err) => {console.log(err);})
}
return (
<div className="container">
<Head>
<title>Next Image Generator</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="main">
<h1 className="title">
Create images with
<span className="titleColor">NextJs + Dalle2</span>
</h1>
<p className="description">
<input
id="prompt"
type="text"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
placeholder="Enter your query"
/>
<input
id="number"
type="text"
value={number}
onChange={(e) => setNumber(e.target.value)}
placeholder="Enter the number of images"
max="10"
/>
<button onClick={generateImages}>
Generate
</button>
</p>
<div>
Download as: {" "}
<select className="dSelect" id="type" value={type} onChange={(e) => setType(e.target.value)}>
<option className="dOption" value="webp">Webp</option>
<option className="dOption" value="png">Png</option>
<option className="dOption" value="jpg">Jpg</option>
<option className="dOption" value="avif">Avif</option>
</select>
{" "}
You can download the image with a single click
</div>
<br />
{error ? ( <div className="error">Something went wrong. Try again.</div> ) : ( <></> )}
{loading && <p>Loading...</p>}
<div className="grid">
{
results.map((result) => {
return (
<div className="card">
<img
className="imgPreview"
src={result.url}
onClick={() => download(result.url)}
/>
</div>
)
})
}
</div>
</main>
</div>
)
}
JavaScriptHere is your code for the globals.css file:
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
body {
color: white;
background: black;
}
}
/* lets add the styling */
input {
font-size: 16px;
padding: 10px;
margin: 10px;
border: none;
outline: none;
margin-bottom: 10px;
border-radius: 3px;
}
button{
font-size: 16px;
padding: 10px;
border: none;
border-bottom: 5px solid #ccc;
margin-bottom: 10px;
border-radius: 6px;
color: rgb(15, 15, 15);
transition: all 0.3s ease-in-out;
}
button:hover {
background-color: rgb(15, 15, 15);
cursor: pointer;
color: white;
}
.dSelect{
font-size: 16px;
padding: 10px;
margin: 10px;
border: none;
border-bottom: 1px solid #ccc;
margin-bottom: 10px;
border-radius: 3px;
outline: none;
}
.dOption{
font-size: 16px;
padding: 10px;
margin: 10px;
border: none;
border-bottom: 1px solid #ccc;
margin-bottom: 10px;
border-radius: 3px;
outline: none;
}
.container {
color: white;
padding: 0 2rem;
background-image: linear-gradient( 135deg, #25bce2 10%, #FCFF00 100%);
}
.main {
min-height: 100vh;
padding: 4rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.titleColor {
color: rgb(15, 15, 15);
}
.title {
margin: 0;
line-height: 1.15;
font-size: 4rem;
color: white;
}
.title,
.description {
text-align: center;
}
.description {
margin: 3rem 0;
line-height: 1.5;
font-size: 1.5rem;
}
.grid {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
max-width: 1200px;
}
.card {
padding: 1rem;
text-align: left;
color: inherit;
text-decoration: none;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;
max-width: 400px; /* 300px for 3 in a row */
}
.imgPreview {
width: 100%;
border-radius: 5px;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
line-height: 1.42857143;
list-style: none;
box-sizing: border-box;
outline: 0;
text-decoration: none;
position: relative;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
background: #FFF;
border: none;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.671);
pointer-events: auto;
cursor: pointer;
transition: all .5s ease-in-out;
}
.imgPreview:hover,
.imgPreview:focus,
.imgPreview:active {
transform: scale(1.1);
cursor: pointer;
/* transition-duration: 1s; */
}
CSSAfter creating a Next Js project, make two files in the API directory (download.js and images.js). Copy the code below, and past it to the corresponding files:
The code for the ‘images.js’ is as follows:
export default async function handler(req, res) {
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: req.query.t,
});
const openai = new OpenAIApi(configuration);
const response = await openai.createImage({
prompt: req.query.p,
n: parseInt(req.query.n),
size: "1024x1024",
});
console.log(response.data.data);
res.status(200).json({ result: response.data.data })
}
JavaScriptThe code for the ‘download.js’ is as follows:
import axios from 'axios';
import sharp from "sharp";
export default async function handler (req, res) {
const url = req.body.url;
const type = req.body.url;
const response = await axios.get(url, {responseType: "arraybuffer"})
const base64 = Buffer.from(response.data, "binary").toString("base64");
if(type == 'png') {
const png = await sharp(Buffer.from(base64, "base64")).png().toBuffer();
const pngBase64 = Buffer.from(png, "binary").toString("base64");
res.status(200).json( { result: `data:image/png;base64,${pngBase64}`});
} else if (type == 'jpg'){
const jpg = await sharp(Buffer.from(base64, "base64")).jpg().toBuffer();
const jpgBase64 = Buffer.from(jpg, "binary").toString("base64");
res.status(200).json( { result: `data:image/jpg;base64,${jpgBase64}`});
} else if (type == 'avi'){
const avif = await sharp(Buffer.from(base64, "base64")).avif().toBuffer();
const avifBase64 = Buffer.from(avif, "binary").toString("base64");
res.status(200).json( { result: `data:image/avif;base64,${avifBase64}`});
} else {
const webp = await sharp(Buffer.from(base64, "base64")).webp().toBuffer();
const webpBase64 = Buffer.from(webp, "binary").toString("base64");
res.status(200).json( { result: `data:image/webp;base64,${webpBase64}`});
}
}
JavaScriptAfter writing the code into the files (don’t forget to save it ?,) you can run the command below:
npm run dev
JavaScript