SOCIAL PLATFORM · iOS & ANDROID
Locava
Locava is a vertical feed of real places posted by real people, not tour guides. You see how far each spot is from you, filter by what you are actually in the mood for, save places into collections, and go. I built it end to end and took it through launch.
View on the App Store
- 10k+
- organic users, zero paid acquisition
- ~50%
- weekly retention
- 8,000+
- posts created by users
- 742k
- lines of TypeScript across the monorepo
FEATURE BY FEATURE
What Locava actually does

01
Map discovery
Every post is a pin with its own photograph, so the map reads as places rather than dots. Filter chips narrow by activity, the counter tells you how much is actually out there, and current conditions sit in the corner because weather decides most of these trips.
BUILT WITH
@rnmapbox/maps on device, with geo queries served from Firestore behind composite indexes and cached in Redis so panning does not become a billing event.

02
Mixes for you
Instead of one algorithmic feed, discovery is broken into named mixes: Hiking, Park, Beach, Cafe, Sunset, View, plus a nearby mix and a row of what friends are posting. It gives people a reason to browse when they do not have a specific search in mind.
BUILT WITH
On-device Google ML Kit image labelling tags media as it is created, and a 768-dimensional vector index over those embeddings powers retrieval per mix.

03
The post, and how far away it is
A post is full-bleed media with the caption set over it, and the primary action is not a like. It is Visit now, with the travel time already computed. That single label is the product thesis: a place you cannot reach is not a recommendation.
BUILT WITH
expo-image and expo-av for media, with travel time resolved against the viewer's location and the palette pulled from the image so the card has colour before the photo decodes.

04
Directions, without leaving
Choosing to go is where most discovery apps hand you off to another app and lose you. Here the route, the mode (drive, walk, transit, bike, rideshare), the ETA and multi-stop editing all happen in place, then hand off only at the moment you actually start moving.
BUILT WITH
Native map routing with a preview layer over Mapbox, so the comparison between modes happens locally rather than as five round trips.

05
Sharing is the loop
Nobody goes anywhere alone, so a post shared into a DM renders as the post, playable, tappable, with its distance intact, rather than as a dead link. Most of Locava's organic growth runs through this screen.
BUILT WITH
Firestore listeners for live threads, expo-notifications for push, and pre-generated video thumbnails so a shared clip has a poster frame immediately.

06
Profiles and collections
A profile is a record of where someone has actually been. Four views: grid, collections, saved and a personal map, so the same set of places can be browsed as a portfolio, a wishlist or a territory.
BUILT WITH
Fastify REST endpoints typed by the shared @locava/contracts Zod schemas, with read paths cached in Redis and writes fanned out through Cloud Tasks.

07
The web surface
The same places, on a desktop, for planning something longer than an afternoon, plus the admin and marketing surfaces the business needs to run.
BUILT WITH
Next.js talking to the same Fastify backend through the same contracts package, with the Firebase client SDK used directly only where it earns it.
01The problem
Finding somewhere genuinely worth going takes an hour of cross-referencing forums, Google Maps and a friend's half-remembered recommendation. And when you finally find it, it turns out to be four hours away.
Locava collapses that into one feed. Every post is a real place with a real distance attached, so the first question, can I actually get there today, is answered before you decide whether you care.
02How the system is shaped
Four codebases, deliberately separated. The mobile client is Expo and React Native with Expo Router. The backend is a Fastify service in TypeScript. The web surface is Next.js. And between them sits @locava/contracts, a package of Zod schemas that is the single source of truth for every request, response and entity shape.
That contracts package is the decision I would defend hardest. It means a change to an API shape is a change to a shared, typed, versioned artefact rather than a local edit that quietly breaks a client. Contract changes get treated like changes to a public API, because that is what they are.
Firestore and Firebase Storage are the source of truth, but nothing outside the backend's repository layer is allowed to touch them. Redis and an in-memory tier sit in front. That boundary is what makes it possible to change storage decisions later without rewriting two clients.
03Making the feed feel instant
The whole product lives or dies on one scroll. There are two feeds, Explore and Following, each with cursor pagination, in-flight request cancellation when you switch tabs, and guards against duplicate pagination when a fast scroll fires two loads at once.
Media is the expensive part, so it gets its own pipeline: sharp for server-side processing, presigned multipart uploads straight to S3-compatible storage, video thumbnails generated ahead of time, and dominant-colour extraction so a card has something to show in the moment before its image decodes.
04Instrument first, guess later
Logging, crash tracking, OpenTelemetry traces and usage dashboards went in before there was a launch date, with BigQuery behind them as the warehouse. That ordering is the single most useful decision I made. It turned roadmap arguments into questions with answers, and it is how one person debugs production without a team to page.
The test suite is the other half of that. 777 test files across the mobile client and the backend, which is the only reason I could keep shipping features while supporting live users alone.
05Where it got to
10,000+ organic users and 8,000+ user-generated posts with no paid acquisition, sustaining roughly 50% weekly retention. That traction is what closed the pre-seed round, and the team grew to eight — two full-time engineers and six interns — with sprint planning and code review.
06Built with
- TypeScript
- React Native
- Expo Router
- Fastify
- Next.js
- Zod
- Firestore
- Redis
- Google Cloud Run
- Cloud Tasks
- BigQuery
- Mapbox
- ML Kit
- sharp
- OpenTelemetry




// KEEP LOOKING



