Brief in β N scored ad variants out β best three ship. Salvo is a batch creative
factory built on Genblaze + Backblaze B2:
give it a creative brief, it fans out N ad-image variants through one real Genblaze
Pipeline, stores every variant (with provenance) through a B2 object sink, scores them
with an explainable, deterministic ranking, and surfaces the top 3 to ship.
flowchart TD
A([Brief]) --> B["N Γ MockAdProvider steps<br/>one PNG + headline each"]
B -->|"genblaze Pipeline.astream(max_concurrency=N)<br/><b>real fan-out</b>"| C["ObjectStorageSink<br/>LocalDirBackend Β· HIERARCHICAL<br/>campaigns/{date}/{run}/β¦"]
C -->|"read_manifest(verify=True)<br/><b>provenance read back</b>"| D["ranking.rank_variants(brief, variants)<br/><b>explainable scores</b>"]
D --> E([Top-3 β the three highest-scoring variants])
Every variant is scored on three transparent signals, and each score ships with a plain-English breakdown of exactly how it was reached:
| Signal | Weight | What it measures |
|---|---|---|
| Brief coverage | 0.45 | how many of the brief's keywords the headline actually uses |
| Headline length | 0.25 | closeness to a 22β42 character scannable sweet spot |
| Engagement index | 0.30 | a deterministic pseudo-signal seeded from the content hash |
Honesty note. The engagement index is not real click/CTR data β it is a deterministic stand-in seeded from the content hash so the ranking is reproducible offline, and every reason string says so. No fabricated metrics are presented as real.
Salvo runs with zero credentials by default. OFFLINE=1 (the default) uses a mock
image provider that emits real PNG bytes (via a dependency-free raw-PNG encoder β no
Pillow, no ffmpeg) and an on-disk LocalDirBackend that implements Genblaze's documented
StorageBackend interface. The full pipeline β fan-out, storage, manifest verification,
ranking β exercises real Genblaze code paths without touching the network.
Setting B2_KEY_ID / B2_APP_KEY switches storage to a real Backblaze B2 bucket via
Genblaze's S3StorageBackend; the app auto-detects credentials at startup.
uv sync --extra dev
OFFLINE=1 .venv/bin/python -m pytest # 37 tests, all green
OFFLINE=1 .venv/bin/python -m uvicorn app.main:app --port 8000Then open http://localhost:8000/console β type a brief, hit Generate, and watch the scored variant grid render with the top 3 highlighted.
| Method | Path | Purpose |
|---|---|---|
GET |
/healthz |
liveness + mode + genblaze version |
POST |
/campaigns |
{ "brief": "...", "n": 6 } β variants + ranking + top-3 |
GET |
/campaigns/{id} |
fetch a completed campaign |
GET |
/campaigns/{id}/variants/{i}.png |
a variant's PNG bytes |
GET |
/console |
the operator console |
curl -X POST localhost:8000/campaigns \
-H 'content-type: application/json' \
-d '{"brief":"eco water bottle for hikers","n":6}'37 pytest tests (OFFLINE=1 .venv/bin/python -m pytest) covering: the campaign runs
offline end-to-end, the ranking is deterministic + explainable, the top-3 are the three
highest scorers, manifest provenance verifies, stored variant PNGs are valid, and the
FastAPI surface (health, create/fetch, PNG serving).
Dockerized for Railway (Dockerfile + railway.json, healthcheck /healthz, binds
0.0.0.0:$PORT). The image installs dev dependencies on purpose β Genblaze's OFFLINE mock
engine imports pytest at module load, so it is a runtime dependency of the demo path.
Built for the Backblaze Generative Media Hackathon on Genblaze + Backblaze B2. Thanks to the sponsors β Backblaze for B2 object storage and provenance, and GMI Cloud for FLUX image inference (the real-generation provider behind the pipeline):
MIT Β© 2026 Edy Cu