Salvo
Backblaze Generative Media Hackathon · Genblaze + B2

One ad is a guess.
A salvo is a decision.

Brief in → N scored ad variants out — the best three ship. Salvo is a batch creative factory on Genblaze + Backblaze B2: one real pipeline fan-out, every variant stored with verified provenance, ranked by explainable, deterministic scores.

Zero credentials, zero signup — the OFFLINE demo is always green.

pytest tests green, OFFLINE
0/19
pytest tests green, OFFLINE
transparent scoring signals
0
transparent scoring signals
credentials needed to demo
0
credentials needed to demo
variants per salvo, top 3 ship
0
variants per salvo, top 3 ship
salvo — one API call, whole batchlive
$ 

The response shape is verbatim from the live API — try it yourself.

batch fan-outexplainable rankingverified provenancetop 3 shipoffline-first19 tests greenzero credentialsdeterministic scores
live fire exercise

Watch a salvo land

This is not a video. It runs a line-for-line port of salvo/ranking.py in your browser — same signals, same weights, same reason strings. Type any brief: the board is deterministic, so the same brief always lands the same way.

try:

Enter a brief and fire — variants pop in, the scan ranks the board, and the top three get the ring.

Honest scope: swatches stand in for the OFFLINE mock PNGs, and this demo seeds content hashes from each variant’s descriptor instead of server-side image bytes — the scoring math, reason strings, and tie-breaks are the real thing. The live console runs the full pipeline: Genblaze fan-out, object storage, manifest verification.

Fire one on the real API
the pipeline

Brief in.
Decision out.

Four moves, all real SDK code paths. The sponsor stack is the engine here, not a sticker: Genblaze owns the fan-out and the manifest, Backblaze B2 owns the bytes.

OFFLINE=1 (default) runs everything on a local StorageBackend.
B2_KEY_ID + B2_APP_KEY flips storage to a real Backblaze B2 bucket.

  1. 01

    Fan out

    Your brief becomes N variant steps — one PNG + headline each — fired in parallel through one genuine Genblaze pipeline. Not a for-loop of fakes.

    Pipeline.astream(max_concurrency=N)
  2. 02

    Store

    Every variant lands in object storage with hierarchical keys — campaigns/{date}/{run}/… — through Genblaze’s documented StorageBackend interface.

    ObjectStorageSink(backend, HIERARCHICAL)
  3. 03

    Verify

    The provenance manifest is read back and checked, content hashes and all. If it doesn’t verify, the run says so.

    read_manifest(verify=True)
  4. 04

    Rank & ship

    Explainable, deterministic scores order the board. The three highest scorers are the three that ship — with the reasoning shown, not hidden.

    rank_variants(brief, variants)
Animated pipeline diagram: one brief fans out into scored variants, the board is ranked, and the top three are ringed and stored on Backblaze B2 with a verified manifest
the same eight seconds that open the repo README — one brief, one salvo, top 3 sealed into B2
explainable by construction

Every score shows its work

Three transparent signals with fixed weights. Nothing is random: the same brief and variant always yield the same score and the same reasons — which is what makes the ranking testable and the demo honest.

0.00

Brief coverage

How many of the brief’s keywords the headline actually uses. An ad that ignores the brief is a bad ad, no matter how pretty — so coverage dominates.

0.00

Headline length

Closeness to a 22–42 character scannable sweet spot: long enough to say something, short enough to scan.

0.00

Engagement index

A deterministic pseudo-signal seeded from the content hash, so the ranking is reproducible offline. Explicitly not real click data — and labeled as such in every reason string.

what one variant’s reasons[] looks like

  • Brief coverage 2/4 keywords (eco, water) → +22.5 pts
  • Headline length 25 chars, inside the 22-42 sweet spot → +25.0 pts
  • Engagement index 0.91 (seeded from content hash, not real click data) → +27.3 pts

= 74.8 / 100 · same input, same output, every run — ties break on sha256 so ordering never wobbles

⚠ honesty note — quoted from the README

“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.
why it holds up

Built narrow. Built deep.

One flow — brief to shipped top three — done devastatingly well, on real sponsor SDK code paths instead of decoration.

A real fan-out, not a loop of fakes

All N variants run in parallel through one genuine Genblaze Pipeline.astream(max_concurrency=N) — the “batch factory” claim is backed by real SDK code paths, provenance-verified.

Green even when your provider dies

OFFLINE=1 is the default: a mock provider emits real PNG bytes through a dependency-free raw-PNG encoder — no Pillow, no ffmpeg, no network — while fan-out, storage, verification and ranking stay 100% real. The demo path is always green.

Provenance you can verify

Every variant is stored with a manifest that gets read back via read_manifest(verify=True). manifest_verified: true, or the run says otherwise.

Ranking that shows its work

Three transparent signals, fixed weights, plain-English reasons on every score — deterministic end to end.

B2 is one env-var away

Set B2_KEY_ID / B2_APP_KEY and storage flips from the local backend to a real Backblaze B2 bucket via Genblaze’s S3StorageBackend — auto-detected at startup.

Proof lives in the repo

19 pytest tests green with zero credentials, Dockerized with a /healthz healthcheck, live on Railway behind api.salvo.edycu.dev.

receipts, not reviews

The variants speak for themselves

No invented praise, no stock-photo customers. These cards quote the ranking engine’s own reason strings from a representative run — fire the demo above and generate your own.

Nothing here is random: the same brief + variant always yields the same score — which is what makes the ranking testable and the demo honest.

salvo/ranking.py

module docstring, in the public repo

74.8
Brief coverage 2/4 keywords (eco, water) → +22.5 pts

Variant #0 — “Eco, reimagined for water”

Rank #1 · shipped

70.6
Headline length 29 chars, inside the 22-42 sweet spot → +25.0 pts

Variant #4 — “Your water, upgraded with eco”

Rank #2 · shipped

67.3
Engagement index 0.66 (seeded from content hash, not real click data) → +19.8 pts

Variant #1 — “The water built for bottle”

Rank #3 · shipped

63.1
Brief coverage 2/4 keywords (bottle, hikers) → +22.5 pts

Variant #2 — “Bottle: hikers without compromise”

Rank #4 · benched

$ OFFLINE=1 .venv/bin/python -m pytest → 19 passed

end-to-end offline run · deterministic ranking · top-3 selection · manifest provenance · valid PNGs · the whole FastAPI surface

all green
no hand-waving

Asked by
skeptics

The questions that decide whether a “generate N variants” tool is real. Salvo answers all of them in code.

No — and Salvo says so everywhere. The engagement index is a deterministic pseudo-signal seeded from the content hash so the ranking is reproducible offline. Every reason string carries the label “seeded from content hash, not real click data”. No fabricated metrics are presented as real.
No. OFFLINE=1 is the default: a mock image provider emits real PNG bytes and an on-disk backend implements Genblaze’s documented StorageBackend interface, so the full pipeline runs with zero credentials and zero network. Setting B2_KEY_ID / B2_APP_KEY switches storage to a real Backblaze B2 bucket via Genblaze’s S3StorageBackend — auto-detected at startup.
One real Genblaze Pipeline fans out all N variant steps in parallel via astream(max_concurrency=N), stores them through an ObjectStorageSink with hierarchical keys, and reads the provenance manifest back with verify=True. The batch claim is backed by real SDK code paths.
Three transparent signals with fixed weights — brief coverage (0.45), headline length (0.25), engagement index (0.30) — and every score ships with a plain-English breakdown of exactly how it was reached. It is also deterministic: same brief + variant, same score, same reasons, every run; ties break on sha256 so ordering never wobbles.
In OFFLINE mode they are honest placeholders: deterministic PNG swatches from a dependency-free raw-PNG encoder (no Pillow, no ffmpeg). Real generation (GMI FLUX / DALL·E) is a provider-key swap behind the same Pipeline surface — the seam already exists, and the console labels the placeholder variants as such.
Five endpoints: GET /healthz (liveness + mode + genblaze version), POST /campaigns (brief in → variants + ranking + top-3), GET /campaigns/{id}, GET /campaigns/{id}/variants/{i}.png, and GET /console — the operator console. Interactive docs are live.
uv sync --extra dev, then OFFLINE=1 .venv/bin/python -m pytest (19 tests, all green), then OFFLINE=1 .venv/bin/python -m uvicorn app.main:app --port 8000 and open localhost:8000/console — type a brief, hit Generate, watch the scored grid render with the top 3 highlighted.
Dockerized and deployed on Railway with a /healthz healthcheck, behind the custom domain api.salvo.edycu.dev. MIT licensed, source on GitHub.

zero credentials · zero signup · offline demo is live right now

Fire your first
salvo.

Type a brief. Get a ranked batch with the reasoning shown. Ship the top three — with a verified manifest behind every variant.

or fire from your terminal — no signup, no keys
$ curl -X POST https://api.salvo.edycu.dev/campaigns \
  -H 'content-type: application/json' \
  -d '{"brief":"eco water bottle for hikers","n":6}'