AI Workflows

AI Image Generator Tutorial with OpenAI Image API in Node.js

Learn to build an AI-powered image generator using OpenAI Image API and Node.js with this detailed guide.

5 min read

Learn how to create an AI-powered image generator using the OpenAI Image API and Node.js. This guide walks you through building a backend server, connecting to OpenAI's Image API, creating a simple frontend, and managing error handling effectively.

prerequisites

  • Node.js: Install the latest LTS version from Node.js.
  • OpenAI API Key: Generate keys by logging into the OpenAI platform.
  • Basic Knowledge: Familiarity with JavaScript, Node.js, and REST APIs.
  • Testing Tools: Use Postman or a similar HTTP client to test endpoints.

Setting Up the Project

This section covers initializing the project and installing required dependencies.

IT_GUIDES_COMPONENT_1 IT_GUIDES_COMPONENT_2

  • index.js: Main application logic.
  • .env: Environment variables file.
  • public/: Files for frontend (HTML, CSS, JS).
  • routes/: Express routes segregated.
  • controllers/: Business logic for OpenAI API calls.

Building the Backend

Set up the Node.js server to call OpenAI's Image API and return generated images.

steps

  1. In package.json, add "type": "module" for ES modules support:
    json
    {
      "name": "ai-image-generator",
      "version": "1.0.0",
      "type": "module",
      "scripts": {
        "start": "node index.js",
        "dev": "nodemon index.js"
      }
    }
  2. Write index.js using ES imports:
    javascript
    import express from 'express';
    import dotenv from 'dotenv';
    import openAIRoute from './routes/openaiRoute.js';
    
    dotenv.config();
    const app = express();
    const PORT = 5000;
    
    app.use(express.json());
    app.use(express.static('public'));
    app.use('/openai', openAIRoute);
    
    app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
  3. Create a .env file with your OpenAI API key:
    OPENAI_API_KEY=your_openai_api_key
  4. Write the route file routes/openaiRoute.js:
    javascript
    import express from 'express';
    import { generateImage } from '../controllers/openaiController.js';
    
    const router = express.Router();
    
    router.post('/generateImage', generateImage);
    
    export default router;
  5. Create controllers/openaiController.js:
    javascript
    import { Configuration, OpenAIApi } from 'openai';
    
    const config = new Configuration({
      apiKey: process.env.OPENAI_API_KEY,
    });
    
    const openai = new OpenAIApi(config);
    
    export const generateImage = async (req, res) => {
      const { prompt, size } = req.body;
      try {
        const response = await openai.createImage({
          prompt,
          n: 1,
          size: size === 'small' ? '256x256' : size === 'medium' ? '512x512' : '1024x1024',
        });
        const imageUrl = response.data.data[0].url;
        res.status(200).json({ success: true, data: imageUrl });
      } catch (error) {
        console.error(error.response?.data?.error?.message ?? error.message);
        res.status(400).json({ success: false, error: 'Image could not be generated.' });
      }
    };
  6. Run the server:
    bash
    npm run dev
    # Output: Server started on port 5000

Creating the Frontend

Design a simple user interface to interact with the backend.

steps

  1. Define basic HTML structure in public/index.html:
    html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>OpenAI Image Generator</title>
        <link rel="stylesheet" href="css/style.css" />
        <script defer src="js/main.js"></script>
    </head>
    <body>
        <main>
            <form id="image-form">
                <input type="text" id="prompt" placeholder="Enter a prompt..." required />
                <select id="size">
                    <option value="small">Small</option>
                    <option value="medium" selected>Medium</option>
                    <option value="large">Large</option>
                </select>
                <button type="submit">Generate</button>
            </form>
            <div id="output">
                <img id="image" src="" alt="Generated Image" />
                <p id="message"></p>
            </div>
        </main>
    </body>
    </html>
  2. Add basic styling in public/css/style.css:
    css
    body {
      font-family: Arial, sans-serif;
      text-align: center;
    }
    #output {
      margin-top: 20px;
    }
  3. Write client-side logic in public/js/main.js:
    javascript
    document.getElementById('image-form').addEventListener('submit', async (e) => {
      e.preventDefault();
    
      const prompt = document.getElementById('prompt').value;
      const size = document.getElementById('size').value;
      const messageElem = document.getElementById('message');
      const imageElem = document.getElementById('image');
    
      messageElem.textContent = 'Generating image...';
      imageElem.src = '';
    
      try {
        const res = await fetch('/openai/generateImage', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ prompt, size }),
        });
    
        const data = await res.json();
        if (!data.success) throw new Error(data.error);
    
        imageElem.src = data.data;
        messageElem.textContent = '';
      } catch (error) {
        messageElem.textContent = error.message;
      }
    });

Error Handling and Testing

After building the app, test the backend with Postman and handle errors effectively.

FAQ

How do I secure my OpenAI API key in this app?

Use an .env file to avoid hardcoding your API key in the source code. Ensure this file is added to .gitignore to prevent accidental sharing.

Can I use a framework like React for the frontend?

Yes. Replace the public folder structure with a React or Vue project and connect it to the Express backend. The API endpoints remain the same.

What image sizes are supported?

OpenAI supports 256x256, 512x512, and 1024x1024 resolutions. Map these to custom labels (e.g., small, medium, large) for easier user handling.

How can I handle rate limits for the OpenAI API?

Monitor the 429 status code in responses and implement retries or throttling mechanisms to avoid exceeding the API rate limits.