
Creating an AI Image Generator with DALL-E API and NextJS 13
Introduction
Starting November 3, the neural network DALL-E 2 previously only accessible through restricted web interfaces, is now available in a public beta. This means developers can now use the neural network in their own applications to create images from natural text. This post will cover the steps to create a full-stack application that can interface with the API and generate some cool photos in our own web interface using the latest NextJS stack. The final app will look something like this:
What is DALL-E 2?
DALL-E 2 is a neural network trained on a massive data set of pairs of text and images scraped from the internet that is now competent enough to generate brand-new images from natural language/text. The model is capable of combining unrelated and abstract concepts to render any style of image. Here are some images generated by DALL-E 2 that gives a good idea of what the model is able to do.
An expressive oil painting of a basketball player dunking, depicted as an explosion of a nebula
a bowl of soup that is also a portal to another dimension, digital art
The model uses a process called "Diffusion" that draws a completely new picture starting from dots and incrementally changing the patterns until it resembles an image that is recognizable.
A bit About Next.js
Before we start, let's cover the latest iteration of Next.js from Vercel which lets you create a full-stack application with ease with features including server side rendering, client side rendering, out-of-the-box typescript support, all without much or any configuration. Other benefits include folder path based routing and seamless integration with vercel which lets you deploy directly from you Github account in a matter of seconds. The latest iteration (v13) adds supports fro React server components, ability to stream UI components incrementally, and turbopack, a Rust-based Webpack alternative . We'll be utilising some of the new features in this application.
Getting Started
Prerequisites
First, we'll need to have at least Node.js 14 installed on our systems (https://nodejs.org/en/download). Next, create a directory for your project and in this command in the terminal to initialise a node project.
npm init -y
Next, we'll need to install the project dependencies.
npm i [email protected] [email protected] [email protected] [email protected] openai
Add an app
folder in the root directory and create a page.js
file with the following contents.
export default function(){
return <div>Hello world!</div>
}
We'll modify the contents later on.
Next, create a next.config.js folder with the following configuration.
module.exports =
{ experimental: { appDir: true } }
This will allow us to play with the latest Next 13 features, including the app folder layout.
Finally to run the application add a dev, build and start script inside the package.json
file, which should look like this:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
The final folder structure should look something like this (don't worry about the layout.js
, as Next.js is smart enough to create one for you)
Now, to run the project simply type the command npm run dev
which should start a local dev server at localhost:3000
which should show you the web application. Another benefit of Next.js is that it supports Hot Module replacement out of the box enabling you the develop without having to refresh the app.
Code for Image Generation
page.js will contain the main component of the code and pages/api
folder will contain the API that is responsible for generating the images and returning back to the client. This is where the full stack capabilities of Next.js shine, being able to do both frontend and backend from the same folder without needing much configuration.
In the page.js
folder, we will add the following code:
'use client';
import { useState } from 'react';
export default function SearchPage() {
const [prompt, setPrompt] = useState('');
const [imageURL, setImageURL] = useState('');
const [loading, setLoading] = useState(0);
const handleSubmit = async (event) => {
event.preventDefault()
setLoading(1);
const response = await fetch('/api/image', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt
})
});
const imageResponse = await response.json();
// setImageURL(imageResponse.imageURL)
console.log(imageResponse);
setImageURL(imageResponse.imageURL);
setLoading(0);
}
if (loading) {
return <Loading></Loading>
}
if (imageURL !== '' && loading === 0) {
return (
<div className="imageContainer">
<img src={imageURL}></img>
</div>
)
}
return (
<div>
<div className="search-box">
<form onSubmit={handleSubmit}>
<button className="btn-search"><i className="fa fa-search"></i></button>
<input type="text" id="prompt" name="prompt" className="input-search" onChange={(e) => setPrompt(e.target.value)} placeholder="Generate Image with AI ..."></input>
</form>
</div>
</div>
)
}
function Loading(){
return <div>Loading...</div>
}
We'll go through the main parts of the code:
use client
ensures that the component loads on the client instead of being server rendered. (Another neat feature that NextJS provides)handleSubmit
function is responsible for calling the API endpoint that we will create later on. This simply takes the form input with the nameprompt
and passes it along to the API.- The response will then be displayed as an image tag in the React component.
Next, we'll create a file called image.js
inside /pages/api/image.js
. Any js files inside the api
folder will be treated as an API endpoint. Inside we create our endpoint with the code below:
import { Configuration, OpenAIApi } from "openai";
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
export default async function handler(req, res) {
if (!req.body.prompt) return res.status(400).json({message: 'Pass in prompt field for image generation'});
const openai = new OpenAIApi(configuration);
const response = await openai.createImage({
prompt: req.body.prompt,
n: 1,
size: "1024x1024",
});
if (!response.data) throw new Error('Unable to get image');
console.log('received url ' + response.data.data[0].url);
res.status(200).json({ imageURL: response.data.data[0].url })
}
This is taking the prompt value from the API request and using the OpenAI SDK to generate the image and get its URL which we will pass back to the client. (Note that this will require an API key provided by OpenAI which is a simple endeavor, https://openai.com/)
Additionally, we have the option to add CSS to improve the layout of the project. This repository will have the complete CSS setup: https://github.com/nipeshkc7/dalle-nexjs-app
Deploying to vercel
Finally, to deploy to vercel, we'll need to setup a Github repository for the project. Then after signing up and vercel easily integrates with Github and deploys your site. It also takes care of the build process seamlessly. This is a major advantage of using Vercel for NextJS applications.
The deployment will then give you a live URL which you can now access from anywhere.
Concluding notes
With the deep integration of vercel, Next.js and Github, deploying full-stack applications can be done in a matter of minutes. We can also add databases into the mix through services like https://planetscale.com/ or https://pocketbase.io/ which is more ideal for side projects.
Resources
- Source code: https://github.com/nipeshkc7/dalle-nexjs-app
- Live demo: dalle-nexjs-app.vercel.app
Also, find me on @hackernoon, @github and @medium