Automation · AI tooling
A resumable Python pipeline that produced 68 style-matched illustrations on local hardware — averaging 9 KB each, with the licensing actually checked.
Aigaku needed an illustration for every vocabulary example. Commissioning them was too slow, stock art would not match, and a hosted image API meant paying per regeneration during the many rounds it takes to get a style right. I built the pipeline instead.
A vocabulary app with 68 example words needs 68 illustrations that look like they belong to the same set. Mixed sources look broken, and the images sit inside a mobile APK, so every kilobyte is a download the user pays for.
The real cost of image generation is not the final render — it is the twenty throwaway attempts before the style is right. Per-call pricing makes iteration the expensive part, which is exactly backwards.
The boundaries that shaped every decision that followed.
Several popular image models are research-only or non-commercial, and sibling models in the same family often differ. The licence had to be confirmed before the output could ship in a paid app.
Generating a full set in one sitting is not realistic. The pipeline had to be resumable, skip work already done, and never require a code change to add more.
These assets ride inside the APK alongside audio and stroke data. A conventional PNG set would have been an unacceptable share of the download.
Images are produced against a FLUX.2-klein-4B model served locally. I verified the Apache-2.0 licence directly from the model snapshot and the published model card before committing to it, and documented the check — because other variants in the same family carry non-commercial terms and the difference is easy to miss.
Consistency comes from a single style constant applied to every prompt, rather than per-image prompt tuning. Changing the look of the whole set is a one-line change and a re-run.
Abstract vocabulary — morning, night, time — produces mush from a literal prompt, so those route through an explicit subject dictionary. Grammatical particles are skipped outright. And because generated text is reliably wrong, the style constant forbids lettering entirely.
The pipeline skips any image already on disk, with flags to limit a run, target specific keys, or force regeneration. Runs are cheap to stop and restart, which is what makes iterating on style practical.
Each run regenerates a Dart index of available images. The app decides between an illustration and a fallback icon by looking that set up, so adding images never touches application code — the pipeline and the app stay decoupled.
512 px WebP output lands between 4 and 12 KB per illustration. The entire 68-image set is 624 KB — small enough to bundle without a second thought.
Tell me what you are building and where it is stuck. I will tell you honestly whether I am the right person for it — and roughly what it would take.
Mobile · Android release
A Flutter learning app with stroke-order grading, spaced repetition, AdMob and Google Play Billing 8 — running entirely on-device.
Web · Infrastructure
A containerised Next.js + Payload CMS template with automatic SSL, shared Postgres, off-site backups and a documented restore path.