The problem
Adult colouring apps ship fixed catalogues, and printable marketplaces have no instant create. The gap is on-demand line art that is actually pleasant to colour — nothing to win, no feed to keep up with.
What it does
Describe a page in text, speak it, or upload a photo; about thirty seconds later you get clean line art to colour digitally or download as a high-resolution PDF sized for A4 or Letter. Brushes, fills, patterns, ambient sound, and a Magic Brush that reveals pre-computed per-region colours in several moods.
How it's built
A density gate that rejects the model’s output
The image model routinely ignores guidance and produces 200–500 regions of filigree that is miserable to colour. So generated pages are forced to monochrome, their fillable regions counted with the same detector that builds the region map, and anything outside a sensible range is rejected and re-rolled before it can be marked ready.
The canvas is the loader, and the stream is detached
A row is inserted, then the fully-baked prompt is posted to the worker, which returns immediately and runs the image stream in a detached promise — so refreshing or closing the tab cannot kill generation. Each partial frame is uploaded and passed through, so the page fills in as it renders.
One pure engine, two renderers
The colouring engine is pure TypeScript, forbidden from importing React, Next.js, React Native, Skia, browser globals or a database client. Canvas 2D on web and Skia on mobile both consume it behind a single surface adapter, with shared logic owning replay scaling so both reproduce a stroke identically.
A classifier routing four image providers
Every request runs a fast extract returning named subjects, a route and an anonymised description. Real people route to one provider pair with names scrubbed, fictional or brand IP routes to another, and everything else takes the default path — because each provider refuses a different category, and a static rule set cannot keep up.
The hard part
Making a stochastic model produce reliably colourable output. The original prompt overshot into individual strands and ornamental fine art; the diagnosis was that this was a guidance problem rather than a model problem, and the resolution was a programmatic density gate with a re-roll rather than another round of prompt-tweaking. Prompts are a request. A gate is a wall.
Stack
- Next.js
- React Native
- Expo
- gpt-image-2
- Stripe
- RevenueCat
Built, shipped and maintained by me. Try Coloring Habitat, or see the rest of the work.
