Projects ai-image-generator

ai-image-generator

Live · sign-in required

Web interface and API for FLUX and GPT Image, with one archive for every image. A Claude skill drives it straight from a chat.

The input form: description, model choice with FLUX.2, aspect ratio, quality, count, format and up to four reference images.
Period
2022 – present
Role
Solo, concept to operations
Status
Live, behind single sign-on
Code
View code →

It started with two consoles, one per provider. Whatever I generated there was fleeting: an image stayed wherever it had been made, and from the next device I could not get at it. At some point that bothered me enough.

The ai-image-generator puts both providers behind the same interface and the same API. I pick a model, set the aspect ratio and the quality level, and optionally hand over reference images for the result to follow. The library is searchable by prompt and filterable by model, ratio and favourite. What an image cost is something both providers report themselves; it is kept and can be broken down by month and model.

These days I mostly don’t even open the interface. A Claude skill hands the prompt and reference images straight to my own API, and by the time I’m back in the session the finished image is already waiting. Installed as a plugin, it can do everything the interface can.

Stack
TypeScriptExpressTailwind CSSBFL FLUXOpenAI GPT ImageVitestDockerGitHub Actions

Decisions

The page asks again as soon as it’s visible

Put the installed web app into the background on a phone and the operating system freezes the running request, then drops it. The server carried on regardless and filed the finished image, but the interface reported an error all the same. Every job therefore gets an id assigned up front, and the page asks after it again as soon as it is visible.

One file for the whole library, but written atomically

The whole library, prompts and all, lives in a single JSON file. Stop the container mid-write (which is every deployment that lands during a running generation) and half a file was left behind, and with it everything was gone. Writing therefore goes to a file alongside first and is then renamed; an unreadable file is set aside at startup instead of overwritten, so the application does not end up in a restart loop.

Credits and dollars stay apart

One provider bills in credits of its own, the other in dollars. Pulling both into a single sum would mean inventing an exchange rate and showing a number nobody can trust. Costs are therefore kept per provider, and anything made before this change is shown as “unknown” rather than estimated.

This site in a different design

Same content, different look. You start on its home page, and every link stays in the chosen design.

What is this? About this site →