This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
I built unPhone for my friends, and honestly for me too. We're all one tap away from a chatbot that's always awake, never judges, and always has something to say. It's easy to tell an AI about a bad week before telling a person. Real conversations feel riskier: what if it's awkward, what if I don't know what to say, what if no one asks?
unPhone is an app that gets people off their screens and into real conversations that feel easier, safer, and more supportive. The AI inside it is a coach that sends you toward people. It's never a companion to talk to.
One rule shapes everything: you only earn XP by meeting someone in person. Talking to the AI earns nothing.
- Check-in: two people scan each other's QR codes. Each phone signs a confirmation with the other person's ID, and XP only lands when both confirm.
- Conversation coach: before a hangout, it finds openers for the situation and Gemma tailors them. Afterwards, a private three-tap reflection gives you two sentences of feedback.
- Rehearsal: practice a hard conversation with Gemma playing the other person, then get a quest to try it with a real one.
- Quests: small daily real-world challenges at your comfort level, verified by offline GPS or a check-in with the friend you did them with.
- Listening Circle: 3–5 people, phones face-down, a timer per speaker, gentle nudges for the listeners, and one question at the end: did you feel heard?
- The game: your hero faces Grumblegloom the Scroll Ogre, who hoards glowing screens. Your stats come only from real life, so the only way to beat him is to go outside.
- Safety: a 988 button on every screen, and crisis wording is handled by fixed rules, not the model.
It solves a simple problem for my friends: it makes the first step toward a real person a little smaller, and it rewards taking it.
Demo
*Demo Video: *
Try it on Android: Download the APK
Install it, open it, and allow installs from your browser when asked. Rehearsal and tailored openers download the on-device Gemma model (2.6 GB, one time, Wi-Fi recommended) from inside the app.
Code
unPhone
An app that gets people off their screens and into real conversations that feel easier, safer, and more supportive.
The AI is a coach that sends you toward people. It is never a companion to talk to. Everything runs on the phone: no account, no sign-up, no server holding your data.
What's in the app
| Feature | What it does | AI on the phone |
|---|---|---|
| Check-in | Two people scan each other's QR. Each phone signs a confirmation containing the other's ID, and XP is added only when both confirm within 2 minutes. 50 XP for a new person, 20 for a repeat meeting, once per person per day. | none |
| Quests | A daily quest at your comfort level (1 to 5). Solo quests are verified by GPS (offline, against bundled spots or anywhere you haven't done a quest). Social quests complete through a check-in. | none |
| Conversation coach | Before a hangout: hybrid search |
How I Built It
Everything a user says or does stays on their phone. No account, no sign-up, no server holding anyone's data. Your identity is an Ed25519 key pair created on first launch.
Open-source AI, running on the device
- Gemma 4 E2B (open weights, Apache 2.0) runs fully on-device through LiteRT-LM, Google's open-source on-device runtime, via a small Kotlin native module bridged into React Native. It loads on first use (GPU, falling back to CPU) and unloads after two idle minutes to save battery and heat. It powers opener tailoring, rehearsal role-play, post-hangout feedback and Listening Circle nudges. On my Galaxy S21 FE a rehearsal reply takes about 2 seconds, offline.
- MediaPipe's Universal Sentence Encoder creates 100-dimension embeddings on the phone. I checked that the phone produces the same vectors as my Mac for the same sentence, so the library and user searches share one space.
- SQLite with FTS5 and sqlite-vec (via op-sqlite) does hybrid search on the phone: keyword ranks and vector ranks merged with Reciprocal Rank Fusion. Searching "coffee" finds café openers even though none of them contain the word.
Guardrails for a small model
Every prompt asks for short output, replies are trimmed to two sentences, and Gemma's JSON is parsed defensively (code fences, numbered lists, stray markdown). If Gemma is slow or returns junk, the app quietly falls back to the human-written library, so the UI never hangs. Crisis wording is caught by fixed rules before the model is ever called.
Tiger Data holds the public content library
At build time, a Python script used Claude to generate 394 openers, quests and listening phrases, tagged by type and comfort level, and embedded them with the same encoder the phone uses. They live in one Tiger Data Postgres table with pgvector (HNSW index) and a generated tsvector column (GIN index), so one table serves both halves of hybrid search. The phone gets a snapshot. No user data ever touches the database: Tiger Data is the shared, public half, and the phone is the private half.
Signed check-ins without a server
Each phone's QR carries its public key and a random nonce. After scanning, a phone signs from | to | their nonce | timestamp with tweetnacl. XP is awarded only when a valid signature addressed to you, for this session, arrives within two minutes. Replays, stale QRs, tampered signatures and confirmations meant for someone else are rejected.
Shipping it
The APK fetches Gemma once through Android's DownloadManager (background, resumable, saved as a .part file and renamed only when complete). After that, everything works offline.
Testing
I ran the whole app in Jest against a real SQLite engine with FTS5 and sqlite-vec loaded, with Gemma, the camera and GPS simulated: 16 end-to-end flows, from onboarding through check-ins, quests, the ogre battle, the model download and a migration of an older database. With only one phone, a small Python script plays the second phone during check-in testing.
Stack: React Native 0.87 (TypeScript), Kotlin, LiteRT-LM, MediaPipe Tasks, op-sqlite + sqlite-vec, tweetnacl, react-native-vision-camera, Tiger Data (Postgres + pgvector).
Why Does Open Innovation Matter?
Because the whole point of unPhone is that nobody should be watching.
Someone rehearsing a hard conversation, or writing "it felt awkward and I talked too much" after a hangout, is being vulnerable. With a closed API, every one of those words leaves the phone, gets logged on someone else's server, and costs money per request. Open weights changed what I could promise: Gemma runs on the device, offline, for free, forever. There's no usage bill that grows with every lonely user, no outage that breaks the app, and no terms of service that can change underneath it.
And there's a fitting irony: the model is good at conversation, and the app uses it to teach you to need it less.
Prize Categories
- Gemma
- Tiger Data


Top comments (1)
Damn! This is really interesting 🔥 Gonna try this out!