A dashboard that says what needs doing next.
A club owner signs in and sees what is outstanding: an entry still to be paid, a course coming up, a certificate ready to download.

Clubs, coaches, cheerleaders, competitions, judging, qualifications, certifications and payments on one data model. From club registration to competition-day paperwork, with no spreadsheets and no paper forms.

The UK Cheerleading Association runs an entire sport: community clubs and school programmes, coaches and cheerleaders, competitions and judging, coaching qualifications, exams and certifications. For years all of it lived in spreadsheets, email threads and paper forms that didn't talk to each other.
01Clubs registered by hand.
02Every roster change after the deadline meant another round of emails and another version of the spreadsheet.
03The running order was assembled in Excel, and judges were handed score sheets printed from it, in folders.
04Coaching certificates were issued and verified on trust.
05Payments arrived through a patchwork of methods and rarely matched who owed what.
06And records for school cheerleaders, children under 18, needed real protection, not a shared folder.
What was needed was a platform that knows the rules of the sport itself.
What was needed was a platform that knows the rules of the sport itself.
For clubs
A club owner signs in and sees what is outstanding: an entry still to be paid, a course coming up, a certificate ready to download.

The age-division rule sits above the list, each athlete's age on the cut-off date is worked out for them, and a team that cannot compete is flagged long before competition day.

It ends in a card payment, or an invoice for schools. Every entry keeps its own record of who was on it and what has been paid.

For the association
Community clubs and school programmes have different roles and ways of paying, but share one data model. Schools get invoices with a purchase order and Sage reference; community clubs pay by card.

Stripe Checkout online, Stripe Terminal at the competition, invoicing for schools. All three land in the same ledger, and every change leaves an audit trail.

The running order is built by dragging category blocks into place, and start times recalculate with every move. Score sheets per judge, packing lists and envelopes generate from it.

Staff see every candidate's result and issue the certificate from the same place, and a public register lets anyone check a coach's qualification.

The backend is a NestJS application split by domain: each domain has its own module, controller and service, and the business rules live in the services. Controllers stay thin: validate, call, shape the response.
PostgreSQL through Prisma. 50+ entities hold the whole sport in one schema: club, team, cheerleader, coach, competition, entry, payment, qualification, certificate, ticket. 51 versioned migrations, 1,600 lines of schema.
BullMQ on Redis separates slow work from the HTTP request. Sending an email is a job, not a block, with retries and a record of failed jobs.
Google Cloud Storage with signed URLs. Private documents are read through a time-limited link and never become public.
JWT authentication, roles and policies at route level, and record ownership on top: a club sees its own club, not somebody else's.
Sensitive fields for school cheerleaders are AES-256 encrypted before they reach the database, with a key that never leaves the backend.
The first generation ran on the Strapi headless CMS. When the scope outgrew it, we built a second generation on NestJS and Prisma and moved onto it domain by domain, with the application running the whole time. The move was completed in September 2026.
dry runChanges nothingEvery domain's migration script runs first without touching data.
--saveWrites a reportA record of exactly what would happen, before it happens.
--applyPerforms the moveThen an audit script compares the old and new state.
A behaviour-parity report and a cutover runbook covered every step, with a way back if it was needed. What moved includes what nobody sees: media from Cloudinary to GCS, certificates, historical payments, entries, users and roles.
The platform runs the sport day to day. Clubs register themselves and enter competitions without back-and-forth. Competition day assembles from the running order, and judges get paperwork that generates itself.
Coaches earn qualifications and walk away with a certificate anyone can check in the register. Schools are invoiced cleanly, community clubs pay by card, and whatever is left is settled with a card reader at the competition, all in the same ledger.
“TherraCode built the system our sport never had. Clubs, competitions and coaching qualifications finally live in one place - and we trust it.”
Tell us what you're building. We'll come back within one business day with a clear plan, and the two people who will build it.