authentiCITY

A map of your city that fills in as you live in it. Drop events for friends or strangers, and claim the streets you actually walk.

Inspiration

Setting up events and meeting people can be daunting. It is hard to stay connected when everyone is spread across the city, and group chats are where plans go to die. We wanted something that puts your friends and the things they are doing on a single map, so making plans feels less like organising and more like looking out a window.

The territory idea came from the same place. If the app already knows where you go, exploring your own city should feel like it counts for something.

What it does

Events on a shared map. Drop a pin anywhere in Sydney with a title, time, place, photo, and a category (nature, landmark, community, waterfront, or food). Events are public by default so anyone can find them, or you can make them friends-only. Anyone who can see an event can RSVP, and the host sees who is coming.

Friends by code. Every account gets a short share code. Add someone by their code and you unlock their private events and their live location. Tap a friend to open their profile and see what they are hosting and what they are going to, then jump straight to any of it on the map.

Live location. Flip on live sharing and your friends see you move in real time. Turn it off and you disappear immediately.

Territory capture. The app records the path you walk and paints it into a territory polygon on the map. The more of the city you actually cover, the more of the map is yours, and you compete with friends for area.

How we built it

We built it with Cursor and Codex, working mostly in Expo Go and React Native.

The app is Expo SDK 54 with React Native and TypeScript, using Expo Router for file-based navigation. It runs on iOS, Android, and the web from one codebase, with platform-specific files where the platforms genuinely differ; native maps go through react-native-maps, while web talks to the Google Maps JavaScript API directly.

Firebase Firestore handles everything live: events, friends, friend codes, and location updates all stream in over realtime listeners. When Firebase keys are not configured, the whole app falls back to on-device storage so it still runs offline. There is also a small optional Express server for storing event photos locally during development.

The look is deliberately voxel and pixel-art: 3D-ish pin and control art, the Press Start 2P font, and a bottom sheet built on pan gestures that you can drag to expand or flick away, with haptics on every snap. Everything is themed through one set of semantic color tokens, so dark and light mode both work properly instead of one being an afterthought.

Challenges we ran into

SDK 54 versus 57. This was the big one. Parts of the team were on different Expo SDK versions, and the APIs had moved underneath us. Reanimated's worklet scheduling was renamed, StyleSheet.absoluteFill stopped typechecking when spread, and several component props were valid in one version and gone in the other. Getting everyone onto a single SDK meant a round of dependency pinning and a pass over every file that touched the changed APIs.

Web was a different animal. Firestore threw benign abort errors that surfaced as full-screen red overlays, and the app tried to reach a local photo server that was not always running, which killed the page with Failed to fetch. We fixed both by making the local server genuinely optional and letting the web build fall back to browser storage.

Merging parallel work. Multiple people building on top of the same map screen at the same time meant real conflicts, including a UI refresh landing on main while a feature branch was rewriting the same components.

Accomplishments that we're proud of

We came up with a good idea and executed it pretty decently. Specifically:

  • It genuinely runs on all three platforms rather than being a phone app with a broken web build.
  • It degrades gracefully. No Firebase keys, no photo server, no location permission — the app still works, just with less.
  • The territory feature turns passive GPS data into something that feels like a game.
  • The pixel art and custom drag sheet give it a real identity instead of looking like default components.

What we learned

Design for the platform split early. The moment we accepted that native and web need different map implementations and wrote .web.tsx variants, the whole codebase got simpler than when we were trying to force one path to serve both.

Every external dependency should have an off switch. The bugs that cost us the most time were not logic errors, they were the app assuming a server or an API key was there. Building fallbacks in from the start would have saved hours.

Pin your SDK version on day one. Almost none of our lost time was spent on features; it was spent reconciling versions that had drifted apart.

Small, frequent merges beat big ones. The conflicts that hurt were the ones where two people had independently rewritten the same screen over a couple of days.

And AI-assisted development changes where the effort goes. Writing the code was rarely the bottleneck — deciding what to build, and reviewing what came back, was.

What's next for authentiCITY

Make territory a real game. Leaderboards, scoring by area covered, contested zones where two people's territories overlap, and weekly resets to keep it live.

Notifications. Tell people when a friend hosts something nearby, when someone RSVPs to their event, or when a friend takes territory from them.

Discovery. A browsable feed of public events happening near you, so the app is useful before you have added a single friend.

Real accounts and hardened rules. Proper authentication and tightened Firestore security rules so private events are enforced on the server, not just filtered on the client.

Built With

+ 1 more
Share this project:

Updates