Web: hangouts that plan themselves
Inspiration
As a friend group, we've struggled to actually hang out, because plans with friends usually die in the group chat. Nobody knows who's free, nobody wants to pick the spot, and nobody wants to be the one who organizes it. We all wanted to get together; the planning is what stopped us. Tools like Partiful and Timeful still need one person to start the event. We wanted to take that person out of the loop.
We also wanted to meet new people. Some of the best friendships start when a friend brings someone along, but that rarely happens when every plan stays inside the same group chat. We pictured each person's friends connecting to their friends' friends, a growing web of connections, and that's where the name comes from. In Web, friends can invite someone new into a hangout, so every plan is a chance for the web to grow.
What it does
Web eliminates most of the friction from planning.
- Finds the time. Web reads busy blocks from the calendars on your phone (never the event titles) and finds free windows that overlap across your squad.
- Proposes the hangout. Nobody has to create an event. Web suggests one by itself every week, or on demand with "Find a hangout now". A proposal looks like "Thu · 6:30–8:30pm · Dinner".
- Picks a fair spot. It offers three venues that match the group's favorites, budgets and vibe. They are ranked by fairness: the worst commute counts most, not the total. Each option shows a fact line such as "★4.6 · $$ · max 14 min travel" and a short AI-written blurb.
- Settles it with a vote. Voting is anonymous and happens in real time. Passing is fine too. The vote closes early once everyone has responded, and the card flips to Confirmed with each person's travel time and a map pin.
- Handles surprises. If the venue turns out to be closed, one tap swaps every phone to the backup venue.
How we built it
- Mobile: React Native with Expo SDK 57 and Expo Router, running in Expo Go on real phones.
- Server: Node, Express and TypeScript, with Socket.io for live updates. It's a single long-running deploy on DigitalOcean.
- Database: MongoDB Atlas through Prisma.
- Shared contract: a
packages/contractpackage holds zod schemas that both the app and the server import, so the API can't drift between them. - Google APIs: Places API (New) for venues and Routes API
computeRouteMatrixfor fair travel times. - AI at the edge only: the scheduling core is deterministic, unit-tested TypeScript.
- Decisions go through one gate,
askDecision, which tries three things in order: - Laya, our own fine-tuned model, which we host ourselves.
- Jev, if Laya fails.
- Deterministic code, if both fail.
- Gemini only writes text: venue blurbs and match reasons. It also generated the training scenarios for Laya.
- Decisions go through one gate,
- Team process: three people each ran two AI coding agents, across Claude, Gemini and Codex, all working in parallel on one repo. Every agent session started from a GitHub issue. Ownership lanes were set in CODEOWNERS, and CI checked every PR.
Challenges we ran into
- Time zones. Our first schema stored weekday plus UTC times, which broke at UTC midnight: at UTC−4, anything after 8pm local lands on the next UTC day. We rebuilt it around exact timestamps and compute free time on the fly.
- Calendar access. Apple has no server-side calendar API. We moved calendar reading onto the device with
expo-calendar, which removed the OAuth work and also keeps event text on the phone. - Legacy APIs. Google's Distance Matrix can't be enabled in new Cloud projects, so we moved to the Routes API partway through.
- Privacy per viewer. Each person needs to see a different version of the same hangout: anonymous votes, private passes, and invitees you can't see. That meant scoping every card and every socket event to the person viewing it.
- Coordinating six agents. Six agents writing to one repo at once caused merge conflicts, duplicate work and schema collisions. The shared contract package, one person owning the schema, and strict lanes are what made it work.
- Switching databases mid-hackathon to MongoDB Atlas.
Accomplishments that we're proud of
- The app proposes hangouts by itself, from nothing, on real phones, and the proposal shows up on every phone in real time.
- Privacy is built in:
- Event titles never leave the device.
- Home locations are rounded to about 100 m.
- Individual votes are never exposed.
- We fine-tuned and self-host our own decision model (Laya). It was trained on scenarios that Gemini and Jev both answered, and we measured it against held-out examples it never saw.
- We landed 220+ commits in 36 hours without the repo falling apart.
What we learned
- Put the logic in deterministic code and use AI only at the edge. Every AI call has a fallback, so the demo can't break because a model is having a bad day.
- A typed contract shared by the app and the server is what lets many agents build in parallel.
- Fairness beats efficiency. A trip that's shortest in total can still be miserable for one person.
- Cutting scope early (with YAGNI) is what got us to a working demo.
What's next for Web: hangouts that plan themselves
- Mixers. Suggest small group hangouts that bring together people who haven't met yet but share friends and interests, so the web grows beyond your current circle.
- Push notifications, so proposals reach you even when the app is closed.
- Server-side Google and Apple calendar sync, so availability stays up to date without opening the app.
- Smarter backup venues that take closure risk into account.
- Rides built into the plan, so getting there is covered too (this fits the Mobility track).
- A larger training set for Laya, so more decisions stay on our own model.
Built With
- digitalocean
- espress.js
- gemini-api
- google-places
- google-routes-api
- hugging-face
- ios
- jev
- kaggle
- laya
- mongodb
- node.js
- prisma
- react-native
- socket.io
- typescript
Log in or sign up for Devpost to join the conversation.