Build Flair AI
KINDAreplaces $8/mosaves $96/yrback to the verdict
A local workspace for product scenes that drives your own model server, whose hard problems are keeping the real product pixels untouched, recording enough of each job that next month's rerun produces the same picture, and never letting a licence you did not read decide whether you can sell the result.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the service, the job queue and the compositing.
Get it python.org or your package manager. open ↗
Verify
python3 --version prints 3.12 or higher - installfree
Why This build submits jobs and stores provenance; it does not implement diffusion, and the backend is the one dependency it cannot work without.
Get it Install ComfyUI or an equivalent server that exposes a job API on your own machine. open ↗
Verify
A minimal workflow submitted over HTTP returns an image - have readyfree if you own it, hourly if rented
Why The memory estimate feature exists because the alternative is discovering the limit during a two hundred image batch.
Get it A card with the memory your chosen checkpoint needs, or a rented machine you control.
Verify
A single generation at your target resolution completes without swapping - have readyfree, subject to the licence
Why The licence determines whether the output can be used commercially, and the terms for some popular weights have been revised more than once.
Get it Download the weights and save the licence text and URL beside each file.
Verify
Every model in the registry has a licence, a source URL and a commercial flag - decidefree
Why These three decide what is shippable, what is deleted and what can run, and each is enforced in code.
Get it Write down the permitted mask difference, how long non-favourites are kept, and which projects are commercial.
Verify
All three appear in the configuration and in tests
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- models(id, filename, sha256, kind, licence, licence_url, commercial_ok, added_at) · kind is checkpoint, lora, vae or upscaler - projects(id, name, commercial, product_asset_id, created_at) · the commercial flag is what the licence gate reads - assets(id, project_id, kind, path, sha256, width, height) · kind is source_photo, mask, prop or reference - jobs(id, project_id, workflow_sha256, workflow_json, seed, sampler, steps, cfg, model_ids_json, backend_version, state, attempts, started_at, finished_at, last_error) - outputs(id, job_id, path, sha256, width, height, mask_diff_pct, sidecar_path, favourite, note) - batches(id, project_id, plan_json, total, completed, failed, created_at) · so a run that dies at image sixty knows which sixty exist - An output is shippable only when every model in its job is permitted for that project's commercial flag and its mask difference is under the stated threshold.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
APP_PORT | required | 8020 | Localhost only. There is no account system and there should not be. |
BACKEND_URL | required | http://127.0.0.1:8188 | Your own generation server. The only place jobs are ever submitted. |
DATABASE_PATH | required | ./data/studio.db | Projects, models, jobs, outputs and batch plans. |
OUTPUT_DIR | required | ./data/outputs | Images and their sidecars, kept together. |
OUTPUT_MAX_BYTES | required | 214748364800 | The disk ceiling. Retention runs against it rather than against hope. |
MASK_DIFF_THRESHOLD_PCT | required | 0.5 | Above this, the product pixels moved and the output is not shippable. |
JOB_TIMEOUT_SECONDS | required | 600 | One variant fails and the batch continues. |
RETAIN_NON_FAVOURITE_DAYS | required | 30 | Favourites are kept. The other thousands are not. |
The build, in order
A cutout that keeps the actual product
The generated scene changes everything except the item being sold.
Every rerun months later needs exactly this mask.
Files
src/masking.pyThe generated frame is a background, not a photograph of your goods.
Files
src/composite.pyThis is the automated version of a second pair of eyes.
Files
src/composite.pytests/test_mask_diff.py
done when · tick each as it passeswatch out- Running image-to-image over the whole frame at a strength high enough to make the background interesting also redraws the label, invents a plausible logo and smooths the texture of the material, and the result is a photograph of a product that does not exist. Generate the background, composite the real pixels back, and let the mask difference measurement be the thing that catches you rather than a customer.
Jobs you can actually run again
An output records everything needed to reproduce it, and says so when it cannot.
The graph is the recipe and the seed is one ingredient.
Files
src/jobs.pysrc/backend.pyNames are reused; contents are not.
Files
src/registry.pytests/test_rerun.pyAn honest mismatch is far more useful than a silent one.
Files
src/rerun.py
done when · tick each as it passeswatch out- Recording the seed and the prompt but not the workflow graph or the model file hashes gives you a rerun that looks like it should work and produces a different picture, because a node was updated, a LoRA was replaced with a same-named file, or the sampler default changed underneath you. Store the graph and the hashes, and treat a differing rerun as information rather than a failure to hide.
The licence gate and the missing-file problem
A model cannot run in a project its licence forbids, and a missing file is never a silent substitution.
A blank licence field is how a legal problem is stored.
Files
src/registry.pyThe warning is read once and dismissed forever.
Files
src/gate.pytests/test_licence_gate.pyThe backend's helpfulness is the problem here.
Files
src/jobs.py
done when · tick each as it passeswatch out- A workflow referencing a LoRA that is not installed often runs anyway, because the backend skips the node or falls back to the base model, so two hundred images are produced in the wrong style and nobody notices until they are compared against the first test image. Check every referenced model exists by hash before submitting, and refuse the job rather than letting the backend improvise.
Batches that survive the hardware
A run of two hundred variants can fail at sixty and continue from sixty.
The plan is what makes resume possible at all.
Files
src/batch.pyOne card, one job, and a stall that ends.
Files
src/batch.pytests/test_resume.pyOut of memory is a normal Tuesday, not an exception.
Files
src/backend.py
done when · tick each as it passeswatch out- Firing the whole batch at the backend at once means an out-of-memory failure halfway through takes the process with it, and since nothing recorded which variants had already been produced the only option is to run all two hundred again, several hours of a card you are paying for one way or another. Persist the plan first, execute one at a time, and make resume the default.
The contact sheet, the sidecar and the diskproduct builder
Choosing an image is fast, every exported file carries how it was made, and the disk has a ceiling.
Then you can answer the listing question in one click.
Files
src/views/sheet.tsxThe image and its provenance travel together or not at all.
Files
src/export.pytests/test_sidecar.pyA batch run is thousands of files you will never open again.
Files
src/retention.py
done when · tick each as it passeswatch out- Exporting a chosen image on its own separates it from every record of how it was made, so six months later the question of which model produced the listing photograph, and whether that model's licence allowed it, has no answer and the image cannot be regenerated at another size. Write the sidecar beside every export and keep them together.
That is the whole plan for Flair AI. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Training or fine-tuning a model.
- Any vendor's proprietary model or dataset.
- Hosted generation for other people.
- Generating the product rather than the scene.
- specialized product-photo workflow, templates, model quality, and hosted rendering
- frontier proprietary models
- hosted GPU capacity
- licensed training data
- moderation and fast global delivery
- A second backend behind the same job interface, once rerun comparison has run for a month
- Automatic prop and angle sets per product category, which are batch plans and nothing new
- Colour calibration against a reference card in the source photograph, which the mask work already makes possible
Need the files? The project pack on the verdict page hands your agent the whole brief · more generative media.