Case Study · Spotlight 002

Show posters by real
humans, with receipts.

Flypost is a two-sided marketplace I designed, built, and shipped end-to-end. It pairs event promoters with verified human artists for original show posters — and attaches a provenance receipt to every commission, so the work is provably hand-made. Launching out of Edmonton's underground.

2-sided
Marketplace
Verified
Artist Provenance
0%
AI-Generated
Early
Access · Edmonton
Flypost home page — 'Human-made show posters, fast. Real artists, verified provenance, no slop.' with calls to browse artists or join as an artist.
publicThe Flypost landing, shipped — flypost.art
Why It Exists

The internet got flooded with slop.

Generated poster art is everywhere, and a promoter has no easy way to tell who actually drew the thing.

The problem

Show posters are how a scene shows its face — and the supply is now drowning in low-effort, AI-generated images. Promoters want original art from a real person on a real deadline; artists want commissions that aren't competing with a prompt. Neither side has a trustworthy place to meet.

The approach

Make authenticity the product. Every artist is a vetted human — verified identity, hand-made work — and every commission ships with a provenance receipt.

The guarantee isn't a marketing line — it's enforced by the workflow, from onboarding to delivery.

What I Built

A marketplace, end to end.

palette

Artist Directory

A browsable roster of vetted artists, each with starting price and turnaround. Promoters pick the hand they want.

verified

Verified Provenance

Identity verification at onboarding and a provenance receipt on every commission — proof the work is hand-made.

handshake

Commission Flow

A structured path from brief to delivered poster, with expectations on price and timeline set up front.

grid_view

The Wall

A public feed of shows and the posters made for them — the scene's portfolio, in one place.

how_to_reg

Artist Onboarding

A self-serve 'I'm an artist' path that brings new creators in through the same verification gate.

shield

Trust & Transparency

A clear, public stance on what the platform guarantees — no slop, no anonymous fronts, no AI passing as human.

How It Works

Brief to poster.

01

Browse the artists

A promoter finds a verified artist whose style, price, and turnaround fit the show.

02

Commission the work

They send a brief and commission directly. The artist makes an original, by hand.

03

Get it, with receipts

The finished poster is delivered with a provenance receipt — provably human, ready to flypost.

Under the Hood · Engineering

Hold a stranger's money, release it correctly, prove who did the work.

A two-sided marketplace that holds money in true per-order escrow and signs every delivery so it's provably hand-made — designed, built, tested, and shipped solo. The product story is above; this is the engineering, for whoever's deciding whether I can build the hard thing.

provenance_receipt.jsonsignature verified
{
"schema":"flypost.provenance/1",
"commission_id":"ord_3Qh…a91",
"artist":"verified:edm_…",
"artifact_sha256":"9f2c4b…d1e7",
"issued_at":"2026-06-13T22:55:19Z",
"public_key_spki":"MCowBQYDK2Vw…"
}
ed25519 · 3a91c0…7f4e ✓
canonical JSON, sorted keys · embeds its own public key · verifies with no server, no trust in me
TypeScriptNext.js · App RouterDrizzle + PostgresStripe Connected25519Cloudflare R2Vercel · Neon

Flypost takes a buyer's payment, holds it while a human artist makes a poster, and on approval pays the artist and keeps a fee — then hands over a receipt proving a person made it. Every word in that sentence is a place to get money or trust wrong. Here's how each one is built so it can't be.

briefcaptureawaiting artistin progressdraft1 revisionapprovereleasereceipt
Payments · Escrow

Per-order escrow, zero float.

// Stripe Connect, separate charges & transfers

The marketplace holds the buyer's funds until approval, then pays the artist their cut. The naive build routes everything through the platform balance and pays artists out of commingled money — which means the platform is floating cash it doesn't own and reconciliation is a guess.

I built it on separate charges and transfers, and funded each artist payout from its own charge via source_transaction. Every order's money is escrowed against the exact charge that created it: no commingling, no platform float, each order independently reconcilable down to the cent.

Found in test, not prod: same-day releases were failing balance_insufficient — transfers draw from available balance, and the buyer's charge was still pending. source_transaction draws from the specific charge instead. The naive version would have quietly needed a float to mask it.
Payments · Correctness

The idempotency trap.

Money operations need idempotency keys so a retry can't double-pay. The obvious key — release-{orderId} — is wrong, and subtly so: Stripe replays a key's result, including its failures. A release that failed once (artist not yet verified) became permanently unretryable — the static key replayed the original failure forever.

I replaced it with a per-order Postgres advisory lock (pg_advisory_xact_lock) that serializes releases, plus an adopt-or-create pattern keyed on the charge's transfer_group: any prior money movement is detected and adopted, never duplicated. A failed release now parks the order in a clean approved state, retryable from the operator console.

The kind of bug a test suite earns its keep on. It never reached a real charge.
Concurrency

A race that can't double-spend.

Accept, decline, expire and cancel all touch the same money. An artist accepting a commission at the exact instant a timeout sweeper tries to refund it is a real race — with real dollars on both sides.

Every state transition is a conditional UPDATE with the guard in the WHERE clause, so a transition physically can't fire twice. The refund path re-reads order state under the advisory lock before it creates a Stripe refund. The sweeper can never refund an order the artist just accepted; the accept can never land on one just refunded. Correctness by construction, not by hoping the timing works out.

Cryptography · Trust

Provenance you can verify.

Every delivered poster ships with a provenance receipt: a canonical-JSON record (sorted keys, deterministic bytes) signed ed25519 with the platform key. The record embeds its own SPKI public key, so a receipt verifies standalone — no server, no env, no trust in me required. The order page verifies the signature live and demonstrates tamper-detection.

Orders that carry a receipt are undeletable at the database layer (foreign-key RESTRICT) — provenance can't be quietly rewritten. "Made by a human" stops being a marketing line and becomes a signature anyone can check.

Architecture

One identity, three systems.

A single artist onboarding feeds three things that usually sprawl into three integrations:

  • Payouts — Stripe Connect Express, so KYC, bank details and verification are offloaded; the platform requests only the transfers capability and never touches card data.
  • Tax — CRA Part XX reporting: the TIN is captured at onboarding, encrypted at the app layer with AES-256-GCM in a versioned v1:iv:ct:tag format built for key rotation, with only the last four digits ever client-visible.
  • Provenance — that same verified identity is the signer on the artist's work.

One verified identity, three obligations, captured once and kept consistent.

Discipline

Correctness over convenience, in the small places too.

  • Live preconditions. Release checks capabilities.transfers === "active" against Stripe at release time — the flag that actually governs a transfer — rather than trusting a cached DB flag that lags verification.
  • Bounds in SQL. The one-revision limit lives in the query (revisions_used < revisions_included in the WHERE), not in app code where a double-submit could slip the gate.
  • Self-healing webhooks. Payment capture has a reconcile-on-page-load fallback — which earned its keep the day a misconfigured webhook secret silently dropped events and payments kept clearing anyway.
Testing

Tested against the real Stripe API.

A 48-check smoke suite runs against the live Stripe test API — not mocks. It asserts the money invariants (commission + payout always equals the poster price, to the cent), signs / verifies / tampers provenance receipts, round-trips storage, then drives two complete order lifecycles through the real webhook handler: payment intent → capture → assign → draft → bounded revision → approve → a real Transfer verified for amount and destination → receipt verification → completion. Plus decline-and-refund checked against the Stripe API, and the negative cases. If the payments logic is wrong, the suite fails before anything ships.

Hire

Got a marketplace in mind?

Full-stack SaaS, document-processing pipelines, AI-augmented tools, internal platforms. Free 20-minute discovery call, projects from $2,500 CAD.

steven.sutankayo@novaconvert.ca