Back to Our Work
Featured Case Study

Legion Comps

A UK prize competition platform where every draw can be checked by anyone — including the people who lost. Storefront, payments, draw engine, fulfilment, and back office, designed and built from scratch.

legioncomps.co.uk
Custom platform Django & HTMX Open banking payments Regulated sector Cloud hosting
18
Django apps
1,750+
Automated tests
3
Payment providers
0
Trust required
Legion Comps competition listing page showing live competitions with ticket prices, sold percentages and draw dates

The competition listing — capped ticket pools, instant-win badges, live countdowns, and a free postal entry route on every card.

The Brief

An off-the-shelf competition site couldn't do this

Legion Comps runs prize competitions for Warhammer and tabletop hobbyists — painted armies, boxed sets, gift cards, and cash. It's a crowded market, and the thing that separates a good operator from a bad one is whether entrants believe the draw was straight.

That belief can't come from a promise on an About page. It has to come from something an entrant can check themselves, after the fact, without trusting anyone. So the whole platform was built around one idea: publish the proof before the draw, reveal the secret after it, and let anyone do the maths.

The rest of the build followed from that — including the payment stack, because the card processors most sites reach for prohibit prize competitions outright.

The hard parts

  • Fairness has to be provable

    "We picked a random number" is worth nothing. The winner selection has to be reproducible by a stranger.

  • A free entry route with genuinely equal odds

    Free postal entries can't be a token gesture — they have to land in the same draw pool, weighted the same.

  • Mainstream card processors say no

    Prize competitions sit outside the acceptable-use policy of the obvious payment provider, so the money had to move a different way.

  • One person has to be able to run it

    Setting up competitions, running draws, notifying winners, printing labels and posting prizes — all from one back office.

What I Built

A whole business, not a website

Eighteen Django apps covering everything from the basket to the courier label.

The competition engine

Capped ticket pools, per-person entry limits, scheduled open and close windows, sale-state badges, and category filtering. Tickets are generated up front so the pool is fixed before a single one is sold.

Instant wins

Prizes attached to individual tickets and revealed the moment a ticket is opened. Winning positions are drawn at ticket generation and committed to before sales open, so nothing can be moved once entries start arriving.

Basket, checkout & payments

A multi-item basket with competition-scoped discount codes, and three payment routes — TrueLayer open banking as the primary, plus DNA Payments and Checkout.com for cards.

Free postal entry

A no-purchase route by post that carries exactly the same weight in the draw. Pending entries are auto-included before close, so an admin backlog can never quietly exclude a lawful free entrant.

Fulfilment & dispatch

Prize inventory, winner dispatch, courier integration and shipping labels, with tracking written back against the win — so the promise made at checkout is closed out on record.

The admin portal

A purpose-built back office: build a competition, run the draw stage, publish winners, manage the waitlist, and pull sales and compliance reports — with an AI assistant that answers reporting questions in plain English.

The Centrepiece

Don't trust us. Check it.

Every draw publishes a cryptographic commitment before ticket sales begin, and reveals the secret behind it afterwards. Anyone can re-run the selection and get the same winner — or catch us if they don't.

1

Commit, before anyone buys

A random draw secret is generated when the competition is created. Its SHA-256 hash is published immediately — the secret itself stays hidden.

2

Anchor the hash to the Bitcoin blockchain

The commitment is timestamped through OpenTimestamps and confirmed into a Bitcoin block. Entrants can download the proof file and verify the date independently — our own server logs prove nothing on their own.

3

Freeze the entry pool

At close, every valid entry — paid and postal — is snapshotted and hashed. The full entry list is downloadable as a CSV so the pool can be rebuilt line by line.

4

Reveal, and show your working

The secret is published after the draw. The winner is selected by sha256(draw_secret:pool_hash:counter) with rejection sampling — no modulo bias, and repeatable by hand.

Legion Comps draw verification page showing the winning ticket, entry count, commitment hash and the four steps needed to reproduce the result

The public verification page every completed draw gets — commitment hash, revealed secret, winner index, and the exact steps to reproduce it.

Compliance

The rules live in the software

Prize competitions are governed by the Gambling Act, the CAP Code and consumer protection law. Written into terms and left to staff discipline, those rules get broken on a busy day. Written into the code, they can't be.

Tickets can't be cheaper than a stamp

The platform refuses to create a competition priced below the current second-class stamp, because a free postal entry has to be no worse value than paying. It's a hard validation error, not a note in a policy document.

Postal entries are never left behind

Valid postal entries are automatically pulled into the draw pool before it closes, so a backlog in the office can't cost a free entrant their place. Staff can void one after review — but never by inaction.

A guardrail on instant-win mix

Industry guidance says instant-win draws shouldn't make up the majority of what's live. The system watches the ratio and warns the operator at the moment a new competition would tip it over.

Responsible play, built in

Spend limits, cooling-off periods, self-exclusion and 18+ age checks, with an audit log behind them so any decision can be reconstructed later.

Legion Comps competition page showing the prize, live countdown, ticket selector, tickets sold progress and the free postal entry option

A competition page — live countdown, ticket picker, and the free entry route given the same prominence as the paid one.

Under the Hood

Boring technology, carefully assembled

Nothing exotic — Django doing what Django is good at, with HTMX for interactivity instead of a front-end framework. The interesting engineering went into the draw, the money, and the parts that have to be right at 2am when a competition closes on its own.

The stack

Django Django Ninja API PostgreSQL Redis Django-Q2 workers HTMX Tailwind CSS Docker TrueLayer OpenTimestamps
  • Background workers handle draws, notifications, reporting and blockchain anchoring, so nothing heavy happens inside a web request
  • A strict nonce-based Content Security Policy with no inline scripts — unusual for a site this interactive, and worth the effort where money changes hands
  • Row-level database locking around ticket allocation, so two people clicking at the same moment can never buy the same ticket
  • Over 1,750 automated tests and a push-button deploy — every merge builds a container image and ships it to production
The Takeaway

Most businesses don't need a blockchain. They do need this.

Legion Comps is an extreme example, but the shape of the problem is ordinary: a business with rules it can't afford to get wrong, a process no off-the-shelf product understands, and one person who has to run all of it without a team behind them.

That's what custom software is for — encoding the parts of your business that matter most, so they happen the same way every time. Whether that's a draw, a quote, a compliance check, or a handover between two systems that have never spoken to each other.

Got something this awkward
to build?

Tell me what you're trying to do and I'll tell you honestly whether custom software is the right answer — and roughly what it would take. Free chat, no obligation.