This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass.
What I Built
It's 4 PM on a Saturday. Someone in the group chat writes "we should go for a walk". Three people react with a thumbs up. Nobody goes.
Flare turns one photo into a plan to meet. You take a photo of where you are, and Gemma 4, an open model on my laptop, writes the invite: "Meet by the quiet water's edge". Friends tap I'm in in private, and everyone sees the count, never who. It lights only if enough can come. If too few say yes in 30 minutes, it shrinks to a smaller plan nearby instead of dying. Then it deletes itself. And it keeps working where the signal ends.
Most of us have people close by, in group chats and small communities, and we still stay in, because asking means pinging everyone and waiting. I wanted one tap that says "I'm up for meeting, nearby, now." And for someone who's lonely, a quiet way to tell people they trust "I'd like some company," without anyone seeing who said no.
"Last week I was busy working from home and haven't really got a chance or felt free to go out … I got this and saw that he was nearby next to me and used this, and we met to talk about flare … it really felt this is good for friends and people to go out"
A friend, after field test 2
Of the 813 Week 1 entries I scanned, fewer than 1% get a group out together.
For a friend with low vision, Gemma turns the photo into a line their screen reader speaks, and the compass talks them in.
Nothing to install. You and your friends open a link. Gemma runs on my laptop, so nobody needs a GPU, a key or an account.
When the signal ends. Once it's lit, the compass needs no signal. The invite fits a 200-byte text for SMS or iPhone satellite texting; friends reply "IN" and the code, and the host counts them. Taps made offline send when signal returns.
Why it matters
A plan in a group chat dies when nobody wants to be the one who says yes first, and Flare's private count is built for exactly that.
Source: Kannan and Veazie, 2023, SSM Population Health, from the American Time Use Survey. More on the site.
At a glance
| What happens | Measured | Proof |
|---|---|---|
| A photo becomes the invite and a line to hear | 39/40 scenes right, 3.0 s median, Gemma 4 E4B | Gemma |
| You say it instead, and Gemma writes it | 3.3 s in desktop browsers, no audio kept | Gemma |
| A plan that gets smaller instead of failing | 11 of 12 lit (Simulation: 48 friends) | Testing |
| Everything about the meetup deleted | within 5 min; worst case 90 s | Privacy |
| Real friends on the live app | 3 people, 1 gathering, live audit pass | Testing |
Demo
- Try it with no setup: flare-outside.onrender.com/app/demo/. Nothing is sent. In 60 seconds: tap I'm in as Amor, Skip 30 min to watch it shrink, then Find them.
- The app: flare-outside.onrender.com/app/. The site: flare-outside.onrender.com, Lighthouse 100 on all five pages.
- Telegram: @FairlaneFlareBot.
- Small things: Again resends your last Flare in one tap. I'm here fires by itself within 30 m, with a 10 s Undo.
One evening, in four frames:
Too few said yes, so it shrinks, then lights: 60 fps at 4x CPU slowdown in Chrome.
How I tested it
Field test 1, Sun Oct 11, 8:20 PM: 2 real friends on the live app: 3 responses, 1 Spark, 6 bugs, all fixed below.
Field test 2, Mon Oct 12, 12:38 AM, the first real meetup: sent, a nearby friend's yes at 12:39 (it needed 2, so it lit), I'm here at 12:40. We met in person and talked; We're done at 12:43, and it was gone from the public audit within 2 minutes (notes).
| What | How | Result |
|---|---|---|
| The full loop | Chrome at iPhone size against the real server, the real Gemma 4 hub and Postgres | 10 end-to-end suites pass, including the field run (27/27) |
| Real phones | A device-check page on an iPhone 16 Pro Max and an iPhone 13: compass, haptics, sound | 3 compass bugs found and fixed |
| Simulation: 48 friends | 48 made-up friends in 4 groups against the real server (GIF) | 11 of 12 lit; median 14.75 min to Lit; all 12 deleted after, audit pass |
| Accessibility | axe on 88 page views (22 pages, 2 widths, light and dark) | 0 findings; every target 44 px or more |
The fresh-eyes testers are AI agents with no context, not people.
| Round | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| Score out of 10 | 5 | 6 | 5 | 6 | 6 | 6 |
Round 6 scored 6/10, and a recheck after its fixes scored 7/10. That tester liked the private yes and the "only if enough come" rule, but would still use a WhatsApp poll for a normal meetup: it sits in the chat, and losing an invite on reload put it off.
Flare is for "anyone free right now?". A poll still wins for a planned meetup. Telegram is how Flare lives in the chat.
Code
Code: github.com/Hotragn/flare
AGPL-3.0. Using Flare needs nothing, and hosting your own copy has three levels: no AI keys (you write the words), a free Google AI Studio key (Gemma 4 in the cloud), or Ollama on your own machine (the photo never leaves it).
How I Built It
Method
I'm one founder running Claude Code sessions in roles: research, product, design, architecture, specialists, QA. The architect froze 14 interfaces first, so specialists built against contracts. Decisions live in 31 ADRs, and 159 requirements are traced to code and tests by trace.py. Every push runs a secret scan, lint, types (with svelte-check), 830 unit and contract tests and the build.
Disclosure: I built this with Claude Code; a manager session, acting as my CTO, sent many prompts. Product and privacy calls were mine. Claude Code sessions drafted this post from the repo's evidence; I checked every claim and supplied the why, the field notes and my friend's words.
Architecture
The phone talks only to the server on Render. My Mac dials out over a WebSocket, so nothing on it is open to the internet. When the Mac is off, Gemma 4 on Google AI Studio answers.
Gemma 4 sees, hears and writes
Gemma 4 E4B (gemma4:e4b-it-q4_K_M) runs in Ollama on my Mac. On my test set: 39 of 40 scenes right, 3.0 s median, valid JSON 20 of 20. It also writes the Plan ladder, the smaller plans a Flare can shrink to: 13 of 13 valid, and 95% came back within 5.5 s (report).
It hears too: a 10 s voice clip becomes "Meet at the pond bench" in 3.3 s, on my laptop.
Smaller models, same test set:
| Model | Where | Result | Shipped? |
|---|---|---|---|
| Gemma 4 E4B, Q4_K_M | Ollama on my Mac | 20/20 JSON, 39/40 scenes, 3.0 s | Yes |
| Gemma 4 E2B, ONNX q4f16 | Chrome, WebGPU | 2.3 s, but 29/40; it invents water and sunsets | No: needs a 1.17 GB GPU buffer, iPhone Safari caps at 1 GiB |
| SmolVLM-500M | Chrome and Safari | 16/40 scenes, 6/20 misleading | No |
| Qwen3-0.6B (conditions) | Safari | 26/40 | No: rules got 40/40 in under 1 ms |
Naming nearby sounds didn't ship: Gemma heard birds in nearly every clip.
The model picks the words; code owns the facts. Every answer passes enforce(): six words at most, no names, no invented places. If it's slow, you type.
The rest of the stack
- Google AI Studio. Gemma 4 26B A4B covers when my laptop is off: 1.4 s a Plan, thinking minimal.
- Mastra. An agent drafts the Plan ladder with four local tools. Across two runs of 13 asks, p95 stayed within 0.3 s of the old route (5.1 vs 5.5 s, then 5.6 vs 5.3 s), and the weather was right 7/7. Live since Oct 12; the first draft took 10.6 s, which Sentry flagged as 271% over its 2.85 s average.
- Tinker. A $2.40 Qwen3.5-4B LoRA read 38 of 40 new phrasings but is too big for a phone; its mistakes lifted the phone's rules from 20/40 to 30/40, blind.
- ElevenLabs. 54 compass lines recorded once: 698 characters, offline, no names.
- Sentry. Agent Tracing follows every AI job, model call and guard. A test fails if our words or ids reach Sentry. It caught the 10.6 s cold start and agent spans sharing a trace.
- Telegram. The bot posts a card with the six words, the spot and the host's first name, never who said yes; it's deleted at Gone.
On the live server, Sentry's Agent Activity view shows each tool, the Gemma call and the guard with timings, and the span panel says "No input for this span". Our words never reach Sentry.
Privacy, built in
- The count, never who. The server sees counts and labels like
c3. - The key lives in the link. It sits in the
#fragment, which browsers never send. Names, places, photos and Sparks are sealed on the phone with AES-256-GCM. - Gone within 5 minutes of the end (the sweeper's worst case is 90 s by design): the Flare, its photo and every yes, checked by an audit route. On Render's free plan, a server that's asleep deletes it the moment it wakes.
- Preview cards show the brand and a count, nothing else.
What I got wrong
My own test found the hardest ones:
- As the host, after sending, all I could see was a lot of animation. It was unclear whether my friends would come, and whether ElevenLabs had worked.
- "Pocket it" felt like a button I had to press. Nothing said to wait until my friend arrives, or that the app should stay open even in my pocket.
- On the friend's side, it showed the place and buttons to finish fast, without saying what each step is for.
- Remember this passed every automated check, then failed on my iPhone: "Couldn't write it down." The logs show no upload. My tests had faked the mic. "Say it" for a Spark failed the same way in Safari, so both are off. I expected a card of the day, with the voice only by choice.
The phone's recorder failed, so here is what the same server code makes from a 46 s recording of me in Telugu and English: Scribe 1.5 s, Gemma's line 2.8 s. Gemma's line is close but calls it a discussion and a device.
The same code on 45 s of a public meeting recording (AMI Meeting Corpus, ES2002a, CC BY 4.0): Scribe found 2 speakers in 1.7 s, and Gemma's line took 2.3 s.
Field test 1 found these:
- The headline and sheet covered 73% of the photo. Now 0%, checked by a new gate on 3 viewports.
- "After 10min" read as 10 AM. Now "you can come in 10 min" (blind set 30/40, unchanged).
- Share did nothing in Brave: the tap was lost after an await. It runs in the tap now, with a Copy link fallback.
- Returning phones got old pages from the service worker; a new one now takes over at once (two-build test, 8/8).
- Round 6 caught 4 more, fixed before the freeze: the invite lost on reload, "Sent." before sharing, size buttons hidden at 375×667, and location asked twice.
Honest limits
- Not yet tested on a trail or over a real satellite link.
- The mic on an iPhone: it failed there twice tonight; voice input was tested only in desktop browsers.
- No background location or mic. An iPhone web app can't use either.
- Two real tests so far. One short meetup in person, indoors or nearby, not yet an outdoor walk.
- In a small group, the count can give away who said yes.
Next steps
- Once lit, show the host who's coming, with each yes-sayer's OK.
- A host status line: "1 friend coming. Keep Flare open; your phone can stay in your pocket."
- "My usual" conditions, repeating Plans, in-app golden-hour nudges.
Why Does Open Innovation Matter?
Open won on three things. Privacy: the photo and your voice go only to my laptop. Cost: $0 a photo. Debugging: I could see the 1.17 GB GPU buffer that keeps E2B off iPhone Safari. Open lost on speed: on my busy laptop, a 5-photo check had a 4.0 s median and one took 11.9 s. And the fallback is a cloud: when my Mac is off, Plan drafts come from Google AI Studio, and a photo goes there only if the host taps Ask cloud Gemma.
My Agent Session
Prize Categories
- Gemma: sees (39/40), hears (3.3 s) and writes, with code checking every answer. Details
- Tinker: a $2.40 LoRA read 38/40 and taught the rules 20/40 to 30/40, blind. Details
- ElevenLabs: a compass voice for 698 characters that sends nothing. Details
- Mastra: four local tools; across two runs of 13 asks, p95 stayed within 0.3 s of the old route (5.1 vs 5.5 s, then 5.6 vs 5.3 s), and the weather was right 7/7. On live since Oct 12. Details
- Sentry Agent Tracing: every AI job traced; a test proves our words never leave. Details







![Why Object.keys(user) Returns string[], Not (keyof User)[]: TypeScript Means It](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2q4w48b9bzs43tynyhsf.png)
