The Problem
The product launched as a no-code MVP - fine for proving the concept, but 2,500 users and real Stripe payment flows exposed every ceiling it had. The business needed a proper engineering foundation: mobile-first, role-based access, QR event check-ins, and payments that actually held up under load.
What I Built
Co-founded the company and owned the engineering end-to-end. Rebuilt the no-code MVP into a React Native mobile app, a Next.js admin dashboard, and a Firebase backend handling real-time updates and role-based access - migrated the live user base with zero service disruption.
Designed the Firestore data model for events, tickets, attendees, and memberships. Chose React Native + Expo over a web wrapper - performance on mid-range Android mattered for the Helsinki user base.
Firebase Authentication for social login, Stripe for ticket purchases. Spent time on the webhook layer before launch - duplicate events, failed charges, and refund flows are the edge cases that kill trust in production.
Built the Next.js dashboard used daily by business owners: event management, attendee lists, QR check-in tracking, and refund processing - all hitting the same Firestore backend as the mobile app.
Wrote integration tests across the payment and auth flows. My QA background caught a race condition in concurrent ticket purchases and a webhook idempotency issue before either reached production.
What Happened
8,000+ users onboarded across iOS, Android and web
50+ Helsinki businesses live with membership perks
30+ events run with near zero payment processing failures
Stripe webhooks handled - duplicate prevention, failed charges, refund flows all covered before launch
In the Wild
In Hindsight
The Firestore schema made sense early on but got awkward once the event and membership models grew. Relational reporting queries were painful to approximate with Firestore's document model. If starting over: Supabase (Postgres) from day one.
