May 1, 2026, nine in the morning, Karlín. STRV, third floor, Event Space. Entry cards. Twenty teams unpacking MacBooks across the tables. Nobody talks loudly, everyone knows that by five in the afternoon they need to ship an app someone will actually use.
Our team has three people and one plan: build a loyalty app for a real café, not a fictional client off a brief slide. The question was whether seven hours was enough for a barista who'd never seen the app to figure it out in 30 seconds.
What we shipped and what I'd do differently next time. Below.
Expo × STRV Hackathon — what it actually was
Organized by Expo and STRV together. Their engineers were on site, drifting around the room as mentors, answering questions.
The full day ran from 9:00 to 19:00. Registration in the morning, ceremony in the evening. The build window was a hard 10:00–17:00, seven hours, followed by a demo video submission. Out of twenty teams, one to three people each, the jury picked a top 5 to present live in front of the audience.
The brief: build a real mobile app for a business that doesn't have one. Mandatory stack: Expo (React Native). Claude Code credits available. The paid tier most people never touch in regular work.
Prizes: $10,000 in Expo credits (about a year of EAS for a team that builds regularly), tickets to App.js Conf and a trophy with a blog feature on the Expo site.
Atmosphere closer to professional than party. Competition, not afterwork.

Who we built for — PFERDA
When you have seven hours and want to build something that actually makes sense, the first decision is: for whom. We went with PFERDA z.ú. (a Czech non-profit) that runs training workplaces for people with mental disabilities and mental illness.
Specifically, the Láry Fáry cafés in Náchod, Rychnov nad Kněžnou and Trutnov, Pekárna Na Plechu and the Láry Fáry cleaning company. The cafés are staffed by real employees: Renča, Nelča, Petr, Patrik, Karel, Lukáš, Petra. People who'd struggle to find work elsewhere, yet they serve customers, make coffee and communicate completely normally.
This choice had a practical dimension too. Most small cafés never get an app built: development is expensive and ROI is unclear. For a non-profit, doubly so. And yet the customer who comes back every morning for an espresso is exactly the one a digital stamp makes sense for: no paper card in your wallet, no "I don't have it on me, can you give it to me next time?".
The intent was simple. Ship something the café could actually use. Not demo-into-the-trash. Something where the customer scans a QR code, gets a stamp and the barista doesn't need five minutes to learn where to tap.
What we built in 7 hours
Seven hours are the competition hours: build window 10:00–17:00. The repo starts with a commit at 10:23 and the last competition commit landed shortly before the deadline. The final period in the commit history is at 21:05, that was post-judging work, finishing the demo video and cosmetics for ourselves. The judges didn't see it. We'd otherwise be looking at it at home and crying.
The base is an 8-stamp loyalty card. You collect stamps, on the eighth one you get a reward. The classic model that works in every other café in Prague, just without the paper card you can never find.
The customer opens the app, shows their phone at the till, the barista switches her phone into barista mode through a PIN gate, generates a QR code and the customer scans it via expo-camera. The stamp gets added, an animation runs on the screen and the loyalty card updates in the background. When there are eight stamps, the reward unlocks.
Second layer: Apple Wallet pass. The customer adds the card to Wallet with one tap, so they don't even need to open the app anymore. Just show Wallet at the till and scan the QR. Push notifications alert them when they're one stamp short of a reward or when a reward is about to expire.
16 screens total. Onboarding (three steps), location picker, the loyalty card itself, scan and stamp animation. Plus achievements, settings and a page about PFERDA. The backend runs on Supabase: seven Edge Functions, among them redeem-stamp, generate-barista-code, generate-wallet-pass, display-qr and get-loyalty. Storage holds reward images and wallet pass templates.
One key decision that paid off. Zero-auth. Instead of email and password, just device_id and AsyncStorage. A full auth flow with OTP and recovery reliably eats two hours you simply don't have. For production it's wrong: when the customer reinstalls their phone, they lose their stamps. For a 17:00 deadline, right.
We didn't take the brand from the website but built a new one: PFERDA Orange (#E97817), Sage Green and Soft Cream. We informally called the design "Artisanal Premium". In practice that means a serif display font on headlines, hand-tuned spacing instead of the default Tailwind 4/8 grid and iconography with a thin stroke (1.5px) instead of fully filled shapes. The goal: an app a café with its own visual identity would adopt, not just a chain template.

Tech stack — why Expo + Supabase was the right call
Specifically:
- Expo SDK 55 + Expo Router (file-based routing)
- React Native 0.83 + TypeScript strict
- NativeWind v4 (Tailwind syntax in RN)
- Supabase (Postgres + Storage + Edge Functions + RLS)
- TanStack Query v5 (server state)
- Zustand v5 (UI state)
- Reanimated v4 (animations)
expo-camera(QR scan),expo-notifications,expo-haptics,expo-wallet-passreact-native-qrcode-svg(barista mode generation)
We pick the stack on a single criterion: nothing can slow us down. A few concrete moments where it paid off.
A NativeWind class string Karel copied from a web PoC of a café card worked in RN with no changes. No translating CSS to StyleSheet.create. File-based routing in Expo Router means you don't write router config: drop a file into a folder and you have a screen. I shipped the first redeem-stamp Edge Function with a single supabase functions deploy while Libor was wrapping up the onboarding screen. We wrote RLS policies during lunch in the Supabase console, not in migration files.
EAS Build got the app onto TestFlight by lunchtime. Seventeen minutes from eas build --profile preview to a TestFlight notification on the phone. That's the difference between "you'll see it in the simulator" and "put it in the barista's hand."
Team
Three people at one table. For seven hours, nobody looked at their phone for an off-topic message.
- Jakub Kontra (article author)
- Libor Zahradka
- Karel Hojda
Libor and Karel chewed through the backend and screen flow, I was finishing the app shell, animations and polish. At this pace you can't split roles on paper: you sit down at the table, say who has what in flight, and then you stay out of each other's way.
Important number: 7 hours × 3 people = 21 person-hours. On your own you've got seven and what comes out is a Figma screenshot you send to the chat with the caption "if there had been time".
What I'd do differently next time
One concrete learning I keep coming back to. Set up the dev environment for the whole team in advance, before the hackathon, not on site.
The first hour we were dealing with things that have nothing to do with the app. Node versions (everyone had a different one — from 20 to 22, someone via nvm). Xcode simulator that hadn't been updated for half a year on someone's machine. Expo Go logins across accounts. Env variables on Supabase. Apple Developer team invites just to be able to build to TestFlight at all.
That's 1/7 of the time, so 14% of the budget. 14% of features the judge won't see, because you didn't get to discover them in code.
Next time we'll do it differently. A shared setup script in a common repo, tested the day before by at least one person who just clicks through it. A pre-prepared Supabase project with seed data, shared env variables in 1Password and Apple Developer access for all three people, not on the morning of. And a thirty-minute sync the day before, where everyone verifies the app launches on their simulator. Without this, everything else is just wishful thinking.
Seven hours is a short stretch. Setup isn't "warmup" before the race. It's pure lost minutes that could've gone into features. And at a hackathon you don't have a retro where you say "next time better". Either it shows up in the app for the judge, or it doesn't.
What to take away
We didn't win. We didn't make it into the top 5. And yet this is one of the few hackathons where I feel we actually built something. An app a barista in Náchod can figure out in 30 seconds.
Here's what I'm taking from that day. A hackathon only makes sense when there's a real user on the other end. A fictional persona off a brief slide won't push a team into hard decisions (zero-auth, one brand, no nice-to-have screens). And winning a hackathon and getting value from a hackathon are two different things. The app is in the repo and can ship to a café. No jury awards or revokes that.
Thanks to STRV for a space with a "build, don't perform" atmosphere, and to Expo for the organization and credits. Most of all, thanks to PFERDA z.ú. — non-profits that employ people with disabilities are the reason it makes sense to show up to hackathons for free. And thanks to Libor and Karel; on my own in seven hours I'd have built the onboarding screens and instead of the loyalty card screen I'd be crying over Apple Wallet docs.
Building a company that needs an app? Or just want to talk through the Expo + Supabase stack? me@jakubkontra.com.


