Tushar Lachman
Melbourne · RMIT ’27
SOCIAL MOBILE APPShipped Android APK

Locked In — Social Fitness App

A squad-based workout tracker my friends actually installed.

Locked In — Social Fitness App — screenshot
5k
lines of typescript
2
platforms — apk + web
1
screenshot to log a session

Watch it run

02 TAKES
TRAILERThe short, edited version♪ SOUND ONTwenty-five seconds of the thing that makes it work: the weekly leaderboard re-ranking the squad, a session posted and commented on, a watch screenshot turned into stats, and the roast waiting for whoever trained nothing.
FULL WALKTHROUGHThe unedited takeThe app driven end to end on a phone, uncut and at real speed: sort the week by points, duration and calories, open a row into its session log, read a story and its comments, see who watched yours, log a session from a watch screenshot and then build one by hand, find someone outside the squad, and finish in the group chat and the notifications.

Every feature, step by step

05 FEATURES · 11 SCREENS · OPEN ONE

The week, and who won it

02 STEPS
The whole point of the app is the table at the bottom of the feed. Training alone is easy to skip; being seventh is not.

Stories, and who watched them

02 STEPS
A session posts as a story that expires. It is the part people actually open, so it carries the likes, the comments and — if it is yours — the list of who has seen it.

Two ways to log a session

03 STEPS
Manual entry is where a fitness app dies. The first path is a screenshot and nothing else; the second is for the sessions no watch recorded.

The squad

02 STEPS
A closed group rather than a network: you see the people you follow, and nobody else sees you.

Talking about it, and being told off

02 STEPS
The two things that bring people back: the group chat, and the app noticing when you have done nothing.

Every person in these captures is invented. Locked In is a social app, so its database is mostly other people — my friends’ names, their photographs and their actual sessions — and none of them agreed to appear on a public portfolio. So the squad here is made up, and so is everything attached to them: the workouts, durations, calories, points, leaderboard positions, comments, chat messages and notifications. The avatars are generated from each invented name’s initials rather than sourced from anywhere, and the images on the sessions are drawn from that session’s own numbers rather than being photographs of anyone. The uploaded watch screenshot is generated too, and says so on its face. Nothing came out of the real project: the web build under capture is compiled with synthetic Supabase credentials, the harness replaces fetch before any application code runs so the app issues exactly the queries it always does and gets invented rows back, and every request to a real Supabase host is intercepted and counted — a run that let one through would say so. Gemini is not called either; the extraction you see running is the app’s real code path against a stubbed reply. My own name is the one real thing left, and only because it is already the title of this site. The repository is not modified at all, and beyond the invented data nothing is retouched — every screen, control and state is the app exactly as it runs.

WHY IT EXISTS

Training alone is easy to skip, so I built the accountability in. Locked In is part workout log, part social feed: you post a session, your squad sees it, and the leaderboard keeps everyone honest. Shipped as a real Android APK through EAS with a web build on Vercel.

How it’s put together

L00
React Native on Expo SDK 54
L01
Supabase Auth · Storage · Realtime
L02
Row-level security on every table
L03
Postgres triggers → Expo Push via pg_net
L04
Gemini vision extraction from a screenshot
L05
EAS Build → Android APK
L06
Vercel web build on push to main

Built with

React NativeExpoTypeScriptSupabaseGemini APIEAS BuildVercel
PERIOD
April — May 2026
ROLE
Solo — design, build, ship
SOURCE
View on GitHub ↗

The hard parts

08 NOTES
1

Around 5,000 lines of TypeScript across twelve modules — feed, profile, posting, search, inbox, chat, notifications, auth — on Supabase Auth, Storage, Realtime subscriptions and row-level security.

2

Gemini vision reads a workout screenshot straight from your smartwatch app and auto-fills activity, distance, duration, pace and calories. No manual entry, because manual entry is where a fitness app dies.

3

Push notifications are sent by the database, not the app: a Postgres trigger calls the Expo Push Service through pg_net, so a like or a comment notifies whether or not anyone has the app open.

4

Web push is deliberately not implemented. It is fragile enough on iOS Safari that shipping it would have meant supporting something that quietly fails for half the squad.

5

Schema changes are additive on purpose. Old APKs are already on people’s phones and will ignore a new column, but a rename or a drop breaks them — so nothing gets renamed once it has shipped.

6

Realtime is opt-in per table through the supabase_realtime publication, so a new table has to be added deliberately rather than silently broadcasting.

7

Distributed as an Android APK via EAS Build, with the web version auto-deploying to Vercel on push to main.

8

Written up with developer onboarding docs covering environment setup, release builds and schema-migration practice, so friends could contribute without me in the room.

Want the parts that aren’t on this page — the architecture arguments, the things that broke, a live walkthrough?

NEXTKitchen OS