A team could sign up without paying. Which meant nobody knew who was actually coming until the last minute.
The tournament had been running on a Google Form. A team filled it in and was registered — but registration and payment were separate steps, so the form told the organiser who was interested, not who was in.
Everything after that was manual. Contact each team. Ask for a bank transfer or Bizum. Wait. Check the bank account. Cross-reference it against the form. Chase whoever hadn't paid. Repeat until the deadline.
Some teams paid in five minutes. Others took thirty. Some had to be chased repeatedly if they wanted to play at all. With around thirty teams, that's thirty separate conversations and a reconciliation that never quite finished.
Two systems that never agreed
- Team fills in a Google Form
- Organiser contacts the team
- Team pays by transfer or Bizum — or doesn't
- Organiser checks the bank account
- Organiser matches the payment to the form entry
- Organiser chases whoever is missing
One action
- Team picks its category
- Team pays through Stripe
- Stripe sends its own receipt
- The entry lands in the sheet, already paid
Payment is the registration
The single change everything else follows from. A team that hasn't paid isn't on the list, so the organiser never has to reconcile two systems or decide whether an unpaid entry counts. It also removes the awkward part of the job: chasing friends and neighbours for money.
One payment link per category
Stripe Payment Links, one per category, instead of a single checkout with a selector. It meant a team could not pick the wrong category or the wrong price, and it kept the payment logic independent of the line-up: categories can be added or adjusted from the Framer panel without anyone opening the code.
A spreadsheet, on purpose
Entries land in a Google Sheet, which for this job is the database. Every participant's details arrive structured and in one place, sortable and filterable, and anyone in the organisation can open it on the day without asking permission or learning a new tool.
Nothing here came out of a template. Every interface piece was drawn first, then written as its own code component.
Drawn in Figma, rebuilt in code
The navigation bar, the countdown to the tournament date, the registration form, the team carousel and the grid background were each designed first and then written as a Framer code component — not assembled from ready-made blocks.

A tree someone else can read
Frames and stacks named and nested so the file makes sense to whoever opens it next, including me six months later.

Stripe links as a setting, not a constant
One Stripe Payment Link per category, each one a field in the component's property panel. Swapping a link or changing a price is typing in a box — no code, no deploy.
Stripe handles the checkout, the card data and the receipt, so no payment details ever touch the site.

Straight into the organisation's own sheet
Google Apps Script writes each completed registration into a Google Sheet owned by Mitus Sports. The destination is a prop too, so pointing the form somewhere else needs nobody to open the code.
That's the difference between a site someone owns and a site they depend on me for.













Around thirty teams, three categories, one weekend in Sádaba.
Thirty teams registered and paid without a single message asking anyone for money.
The tournament went ahead with its entries closed and paid, and the organisers spent the run-up organising a tournament instead of reconciling a spreadsheet against a bank account.
For me it was the first time wiring separate platforms into one working flow — a Framer site, a payment provider and a spreadsheet that had to agree with each other, with real money moving between them and a date that couldn't slip. Getting that right end to end, on the first attempt, is the part of this project I'd point to.
It also settled how I think about the tools a project should use. The right stack here wasn't the most capable one; it was the one the client could still operate the day after I stopped working on it.
Design, front-end build, payment setup and data pipeline by me. Tournament organisation, categories and pricing by Mitus Sports.