The Problem
Pickup soccer happens in messy reality — different fields, different days, different jerseys, different skill levels. Group chats and spreadsheets fall apart the moment one player drops out or the venue changes. Nine98 wanted pickup to work like a real product, on the surfaces players already use: WhatsApp for the conversation, a native app for everything else.
The native side needed real-time presence on jersey swaps, location-based game discovery on actual maps, and a profile system that captures match history without becoming a chore. The bot side needed to feel like a competent assistant — parse natural language scheduling, maintain a roster with a waitlist, and log post-game performance, all from a chat thread players never have to leave.
The Approach
Embedded team running weekly delivery against an EAS-driven multi-environment pipeline (development, preview, production). Domain-driven architecture with Result-typed business logic. Documented as we shipped — 13 docs covering auth, real-time architecture, jersey swap flows, and design system migration.
Native app: Expo SDK 53 with React Native 0.79 and NativeWind. Supabase for auth and Realtime subscriptions powers live jersey swap notifications. Google Maps integration handles location-based game discovery. Sentry tracks errors across both stores. Performance tuning pulled splash-to-home time below the threshold where players bounce.
Gaffer Bot turns WhatsApp into the booking surface. A Mastra agent on GPT-4o parses natural language scheduling ("Sun 3pm Hackney 7v7"), tracks IN/OUT/WAIT availability with automatic waitlist, lists upcoming games with roster counts, and records post-game performance — ratings, goals, assists. Baileys runs the WhatsApp WebSocket 24/7 on Railway. Convex serverless backend persists every game, RSVP, team assignment, and stat. A read-only React + Vite admin dashboard turns what the bot wrote into leaderboards.
Start a similar project.
Talk to us