How to Use freestylefly/awesome-gpt-image-2 for Batch Image Generation

freestylefly/awesome-gpt-image-2 enables batch image generation by submitting multiple asynchronous requests to the APIMart API, polling each taskId until completion, and collecting the resulting image URLs.

The open-source freestylefly/awesome-gpt-image-2 repository provides a complete Vercel-based pipeline for generating images at scale. It leverages the APIMart asynchronous API to process hundreds of generation jobs without blocking your application, making it ideal for batch workflows that require high-throughput image creation.

Architecture Overview for Batch Processing

The repository implements a full-stack pipeline where batch operations rely on three core components working together asynchronously:

  • api/generate-image.js – The server-side endpoint that receives generation requests, reserves credits in Supabase, and forwards jobs to APIMart
  • src/apimartClient.js – Client-side utilities including submitPlatformGeneration and pollApimartTask for managing task lifecycles
  • api/generation/status.js – The status endpoint that queries APIMart for real-time task updates

According to the source code in api/generate-image.js, each submission creates a reservation record in the generation_reservations table and returns a unique taskId. The system never blocks while waiting for image generation; instead, you poll the taskId later to retrieve results when APIMart finishes processing.

Submitting Multiple Generation Requests

Preparing Your Job List

A batch workflow starts with an array of case IDs and prompts. Each object in your array represents one image generation job that the system will track independently.

const jobs = [
  { caseId: 1, prompt: 'A futuristic city skyline at sunset, photorealistic' },
  { caseId: 166, prompt: 'Twelve Gold Saints playing cards, stylized illustration' },
  { caseId: 310, prompt: 'Snack brand technical breakdown, clean infographic' }
];

Parallel Submission with submitPlatformGeneration

The submitPlatformGeneration function in src/apimartClient.js handles the HTTP POST to /api/generate-image. For batch processing, map your jobs array to parallel promises to maximize throughput:

import { submitPlatformGeneration } from './src/apimartClient.js';

async function submitBatch(jobs, accessToken) {
  const submitPromises = jobs.map(job =>
    submitPlatformGeneration({
      caseId: job.caseId,
      prompt: job.prompt,
      language: 'en',
      accessToken
    })
  );

  const submissions = await Promise.all(submitPromises);
  console.log('Submitted tasks:', submissions.map(s => s.taskId));
  return submissions; // Array of { taskId, status } objects
}

The function returns immediately with a taskId for each job, allowing you to fire dozens or hundreds of requests without waiting for image generation to complete.

Polling and Retrieving Results

Using pollApimartTask for Status Monitoring

Once you have your taskIds, use the pollApimartTask helper (implemented at lines 15-52 in src/apimartClient.js) to monitor each job until it reaches a terminal state (completed or failed). This helper automatically handles rate-limit retries when APIMart returns APIMART_RATE_LIMITED status.

import { pollApimartTask, fetchPlatformTask } from './src/apimartClient.js';

async function pollAllTasks(submissions, accessToken) {
  const results = await Promise.all(
    submissions.map(async ({ taskId }) => {
      const fetchTask = () => fetchPlatformTask(taskId, accessToken, 'en');
      const finalTask = await pollApimartTask(fetchTask);
      return { taskId, status: finalTask.status, result: finalTask };
    })
  );
  return results;
}

Extracting Image URLs from Completed Tasks

After polling completes, filter for successful generations and extract the image URLs from the output array. According to the APIMart specification referenced in the source code, completed tasks store the image URL at result.output[0].url.

const results = await pollAllTasks(submissions, accessToken);
const completed = results.filter(r => r.status === 'completed');

console.log('Generated images:', completed.map(c => c.result.output[0].url));

Optional Local Storage Helpers

The repository includes browser storage utilities to persist pending tasks and generated images between sessions. These helpers use APIMART_PENDING_STORAGE_KEY and GENERATED_TESTS_STORAGE_KEY to manage localStorage entries.

import { 
  savePendingGeneration, 
  getPendingGeneration,
  clearPendingGeneration 
} from './src/apimartClient.js';

// Cache a pending task immediately after submission
savePendingGeneration(caseId, { taskId, status: 'submitted' }, localStorage);

// Retrieve later to avoid duplicate API calls
const pending = getPendingGeneration(caseId, localStorage);

These utilities automatically prune expired entries and are defined at lines 54-99 in src/apimartClient.js.

Server-Side Batch Implementation

For automated batch processing (such as Vercel cron jobs), you can run the same workflow inside a serverless function. The following example uses the Supabase client from src/supabaseClient.js to authenticate requests:

import { getSupabaseClient } from './src/supabaseClient.js';
import { submitPlatformGeneration, pollApimartTask, fetchPlatformTask } from './src/apimartClient.js';

export default async function batchHandler(req, res) {
  const supabase = getSupabaseClient();
  const { data: { access_token } } = await supabase.auth.getUser();

  const caseIds = [1, 166, 310];
  const tasks = await Promise.all(
    caseIds.map(id => submitPlatformGeneration({
      caseId: id,
      prompt: `Concept art for case ${id}`,
      language: 'en',
      accessToken: access_token
    }))
  );

  // Sequential polling example for rate-conscious environments
  const results = [];
  for (const { taskId } of tasks) {
    const final = await pollApimartTask(
      () => fetchPlatformTask(taskId, access_token, 'en')
    );
    results.push(final);
  }

  res.json({ completed: results.filter(r => r.status === 'completed') });
}

Summary

  • Submit jobs in parallel using submitPlatformGeneration from src/apimartClient.js to receive unique taskIds for each generation request
  • Poll asynchronously with pollApimartTask, which handles rate limits and retries automatically
  • Retrieve results from the output[0].url property of completed task objects
  • Track credits via the generation_reservations table in Supabase, managed by api/generate-image.js
  • Persist state optionally using the localStorage helpers to cache pending and completed generations

Frequently Asked Questions

How does the batch workflow handle API rate limits?

The pollApimartTask function in src/apimartClient.js specifically checks for APIMART_RATE_LIMITED status responses and implements retry logic with exponential backoff. When APIMart signals rate limiting, the poller waits before retrying the status check, ensuring your batch process continues without manual intervention.

What is the maximum number of images I can generate in one batch?

The repository itself does not impose a hard limit on batch size; your concurrency is bounded only by your APIMart credit balance and any rate limits imposed by the APIMart platform. Because the architecture is fully asynchronous, you can submit hundreds of jobs simultaneously and poll them independently as resources allow.

How do I track the status of individual tasks in a batch?

Each submission returns a unique taskId that identifies the job in APIMart's system. Use fetchPlatformTask (which queries the /api/generation/status.js endpoint) to check current states, or use pollApimartTask to block until a specific task completes. The Supabase generation_reservations table also maintains a record linking your case IDs to their respective APIMart task IDs.

Can I run batch generation from a serverless function?

Yes. The client utilities in src/apimartClient.js work identically in serverless environments like Vercel Functions. Import submitPlatformGeneration and pollApimartTask directly into your API route handlers, authenticate with a Supabase token via getSupabaseClient from src/supabaseClient.js, and execute the same parallel submission and polling logic you would use in a browser.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →