Inspiration
When I first saw the brief for this project, I knew immediately — I want to build this. It's a real niche without a solution: everyone builds "normal" dating apps, or apps to help van lifers, but nobody combines both. Traditional dating apps are focused on list views and cards, but van life is about the journey — I wanted an app where you can share your location, your route, and actually meet people on the road.
What it does
Van Match is a real-time social and dating app designed specifically for the van life community. It goes beyond swiping:
- Discover & Match — Swipe through nearby van lifers, filtered by shared interests. See their van setup, travel style (full-time, part-time, weekender), and what they're looking for (dating, friends, or both)
- Map Discovery — An interactive map showing cities with traveler counts, nearby activities, and friends' live locations. Drop a pin to search for people in any area
- Real-time Location Sharing — Matched users can share live GPS locations (updated every 5 seconds) for meetups and safety
- Activities — Create and join community events: surf sessions, hikes, campfire hangouts, van repair parties, road trips. Each activity gets an automatic group chat
- Help Marketplace — A two-sided board where users post "Need Help" or "Can Help" offers — from mechanical repairs to travel advice, with optional pricing and private chat
- Premium Subscriptions — Free tier with \( 10 \) likes/day, premium unlocks unlimited matching
How we built it
Architecture: SwiftUI with MVVM + Clean Architecture on iOS, Convex as the real-time backend, and Firebase Auth with Sign in with Apple.
SwiftUI Views → ViewModels → Repositories → Convex (Real-time DB)
The backend runs on Convex, which gave us real-time subscriptions out of the box — critical for live location streaming, instant messaging, and activity updates. The schema spans 16+ tables including users, likes, matches, messages, liveLocations, activities, helpPosts, and more.
Key technical decisions:
- Real-time location pipeline:
LocationService(CoreLocation) →LocationSharingService→ ConvexliveLocationstable → subscriber receives updates. Location points stream every 5 seconds with lat/lng, heading, and speed - Multi-type chat system: A single
messagestable handles DMs, activity group chats, and help marketplace chats via optional foreign keys — keeping the architecture clean while supporting three distinct chat contexts - Privacy-enforced queries: "Matches-only" activities are filtered server-side with bidirectional match verification
- RevenueCat webhooks via Convex HTTP endpoints sync subscription state (purchases, renewals, expirations) to the backend in real-time
- Invite code gating with rate limiting and entropy hardening to control community growth
iOS-specific highlights:
- Custom
@OptionalConvexInt/@OptionalConvexFloatproperty wrappers to handle Convex JSON numeric encoding - MapKit integration with custom annotations for cities, friends, and activities
- Background lifecycle management — location sharing gracefully pauses/resumes with app state
Challenges we ran into
Convex mobile SDK quirks — The Convex Swift client has no direct
querymethod. We had to wrap every one-time read in a subscription with.first()and manualAnyCancellablelifecycle management. This pattern was unintuitive and required careful memory management to avoid leaksReal-time location at scale — Streaming GPS every 5 seconds per active session creates significant write volume. We had to carefully design session lifecycle (start/stop/pause on background) to avoid unnecessary database writes while keeping the UX smooth
Multi-context chat — Supporting DMs, group chats, and help marketplace chats in a single message system required thoughtful schema design. Balancing normalization against query performance was an ongoing tradeoff
Map performance — Rendering city overlays with user counts, activity pins, friend annotations, and search radius simultaneously on MapKit required aggressive optimization — lazy loading, clustering, and careful annotation recycling
Subscription webhook reliability — Ensuring RevenueCat webhook events (renewals, expirations, billing issues) correctly sync premium status required idempotent handlers and careful state machine design on the backend
Accomplishments that we're proud of
- Live location sharing that actually works — 5-second GPS streaming between matched users with smooth map animations, heading indicators, and clean session management
- A complete community ecosystem — Not just matching, but activities, group chats, a help marketplace, and map discovery. Van lifers can find dates, travel buddies, surf partners, or someone to fix their transmission
- 16+ table schema powering a real production app with proper auth, blocking, reporting, invite gating, and subscription management
- Clean architecture at scale — MVVM + Clean Architecture with clear separation between Views, ViewModels, Repositories, and the Convex network layer. Every feature is modular and independently testable
- Privacy by design — Server-side auth enforcement on every query, user sanitization for non-friends, matches-only activity visibility, and invite-only access control
What we learned
- Convex is powerful for real-time apps — subscriptions, automatic caching, and the action/mutation/query model made complex features like live location sharing surprisingly manageable
- Van life is a real community with real needs — user research revealed that safety (location sharing), practical help (marketplace), and shared activities matter as much as dating
What's next for Van Match
- Route sharing — Let users share their planned travel routes so others can see who's heading their way
- Campsite reviews — Community-driven database of campsites, overnight parking spots, and van-friendly locations
- Safety features — Emergency SOS integration, trusted contact alerts, and meetup check-ins
- AI-powered matching — Using travel pattern analysis and interest compatibility to surface better matches beyond simple location proximity
CODES FOR LOGIN
Please pick randomly to avoid rate limiting
[
"VAN-E4C4VEUPRZAH",
"VAN-4HKQGC5HPUMY",
"VAN-QW2AC6WVCP78",
"VAN-YG4U4ZUAZBXF",
"VAN-TU3E5YZR8BQR",
"VAN-64QD67VKYNQV",
"VAN-GRZBPDXCU3WW",
"VAN-A266VZFN59JK",
"VAN-QEGBF5B97AAE",
"VAN-CHAU4DKH8KM9",
"VAN-2N45NZ7KSH64",
"VAN-MVC9Y23AQR7W",
"VAN-BZDBAHGP7KT4",
"VAN-S7K6TRYSSCEQ",
"VAN-27MTEG76FEYD",
"VAN-4HADAZ2QY28X",
"VAN-ABEVM3APZC3E",
"VAN-D3GYWCVGBQYZ",
"VAN-9FF25ECMSZWB",
"VAN-ABP3R22ZD367",
"VAN-5J9JPA5VQWFP",
"VAN-BKW5VCTQ84XM",
"VAN-47GR6BCJBF7Z",
"VAN-39HGJCVYG7U3",
"VAN-8JFTUXT7MMS3",
"VAN-DRETRNBWXNQG",
"VAN-W3AXF2JNQXTZ",
"VAN-XX82BSYZK576",
"VAN-ER39W6CMS7XJ",
"VAN-69N6ZWFMA276",
"VAN-BCBSJPUBGN54",
"VAN-646B7BJ56JBM",
"VAN-5ZGDGWBFDH85",
"VAN-V752CW83MVKJ",
"VAN-C5JPYMHP4QXC",
"VAN-CY56NYGV3BEK",
"VAN-PJE9ZCWMBGAX",
"VAN-7CGTMDYEYA4N",
"VAN-PVJTUXK6VB8G",
"VAN-Q3KN2YF49226",
"VAN-8GGR2N2VSJPP",
"VAN-WNTT8DUTH8PG",
"VAN-JNTAWEVW6PZC",
"VAN-Y5E4XSX3PZCR",
"VAN-SZSPZEFU3ZQD",
"VAN-3CP5N29TJUUP",
"VAN-YGHEQC8G4AKH",
"VAN-3CR3YZ5XEW5E",
"VAN-UNF75USVYUZV",
"VAN-K45R7EERVJF9",
]
Log in or sign up for Devpost to join the conversation.