Blog
engineering · · 6 min
Building a checkout system at 16
800 people, a line that kept growing, and a checkout app nobody could stand waiting on. I was 16 and thought I could build something better. So I asked. What followed was a 1,000 CHF budget, a printer hack at 2 in the morning, and a TWINT button I forgot to build.
I was standing next to the till, watching. 800 people pushed through the room, the line kept growing, and on the tablet in front of me the cashiers were fighting their way through an app with bad UX.
The system wasn't even old. But it was unmaintainable, thin on features, and the developer who built it had run out of time for it. It worked, and working is a low bar.
I was 16, there every month for this youth event at the church, and usually you just help out where you can. That evening I wasn't thinking about helping out. I was thinking I could build something better.
So at the next event, I asked.
The message that started it
I went to the lead organiser with a concrete proposal, not a vague "I've had an idea." A new checkout system. Mobile ordering so nobody has to queue. A hardware concept that fits the budget. I'd take all of it, from the consulting to the last line of code.
What I left out: that I'd never built anything like it. That I had no idea how you talk to a thermal printer. That the whole thing was one big experiment for me.
The answer came fast. He was in. When can we start?
Now I had to deliver.
Before a single line of code
The first real conversation happened on site, right after an event. We went through what the system had to do, what was annoying about the current setup, what was missing, what would be nice to have.
But the lead organiser wasn't the only one I talked to. I asked the cashiers directly: what do you actually need? What costs you time? Where does the old app get in your way? Their answers were worth gold. Things I'd never have spotted myself, small frustrations that had built up over months.
That was about two weeks of planning before I wrote the first line. It wasn't a clean cut, though. While I was coding, questions kept coming up, and short messages and quick decisions went back and forth. The system didn't grow in isolation.
What made it work: I got to decide almost everything myself. Technology, architecture, design. That kind of trust is rare, and it's what made the project possible.
1,000 francs, no room to move
The budget was the first reality check. Under 1,000 CHF for everything: two tablets, two card readers, two printers, stands. At normal prices, impossible. So I started doing the math.
A Samsung Galaxy Tab A9+ instead of an iPad, because Android let me write a native app and pull in the SumUp SDK directly. A SumUp Air instead of pricier terminals, because Bluetooth meant no cables and less chaos.
The printer is where it got interesting. Classic thermal printers for POS systems start at 150 CHF. I found the Phomemo T02 for 30. The catch: it's really only meant to be driven from its own app, not by a developer. So I spent two evenings digging through GitHub, and eventually found an open-source library that had reverse-engineered the thing. Direct print commands over Bluetooth. It worked.
Under 1,000 CHF, with budget to spare.
Under the hood
The software was the part I'd been looking forward to. Go for the backend, because I wanted something lean that wouldn't fall over under load. Next.js for the web app. A native Kotlin app that reaches the POS frontend through a WebView.
On infrastructure I got lucky: the organisation had Azure non-profit credits. Container Apps were a perfect fit, because the system is under load once a month and costs nothing the rest of the time.
The database was a compromise I didn't love. I wanted PostgreSQL: transactions, consistency, everything an ordering system wants. But Cosmos DB with the MongoDB API scales to zero, so no requests means no cost. I put availability ahead of consistency. Not ideal for an ordering system, but realistic for this budget.
"Where's TWINT?"
First live test. The room fills up, the first orders come in, everything runs. I'm standing next to it, watching every interaction. Then a customer pays with TWINT and the cashier turns to me:
"Where's TWINT?"
I froze. I'd forgotten it completely. In my head there was only cash and card, since TWINT used to run over QR codes. But here half the room pays with TWINT, and the cashiers needed a button to close those orders.
I pulled out my laptop, wrote the button, tested it locally, and deployed, while 300 people around me ordered their food.
It worked. But that moment stuck.
What I didn't see coming
The WiFi caused the next round of trouble. The connection between the tablets and the SumUp terminals kept dropping, with delays of several seconds. My theory: both terminals ran on the same SumUp account. When the rush eased and we switched one station off, the connection went stable immediately. Note for next time: dig into it properly, and maybe run separate accounts.
Mobile ordering was meant to land in January. Stripe was integrated, the app was ready, we were set for the next step. Then a message from the lead organiser: problems with verification. Details I won't get into here, but the conclusion was clear. We needed a different payment provider.
The migration to Payrexx is running now. It's a delay, but also time I'm using to sharpen other parts of the system. Slower is sometimes better.
What's left
150 orders per event. 800 visitors. A system the cashiers describe as intuitive. Not bad for a 17-year-old with 1,000 CHF and no real backup plan.
But the numbers aren't really the point. The point is that I asked. I saw a problem nobody had named as one, and I asked whether I could solve it.
A lot of people my age wait. For university, for the first job, for someone to say: now you're ready. I stopped waiting.
If you're reading this and wondering how you get to work on projects like these: look around. An outdated tool, an annoying process, anything that eats time or money. Then ask, directly. And if you offer it for free, nobody says no.
The knowledge comes from doing it. Not before.
L
Levyn Schneider