-
-
Join with the 6-character code your housemate shares in the group chat.
-
Quarters: fair rent, decided together. Live, multiplayer and provably fair, with no sign-up.
-
New split: iOS-style form with home name, rent, currency and one room per housemate.
-
Invited housemates pick a name and take a seat. Live presence shows who's here.
-
Locked in and sealed. The live roster shows 2 of 3 ready, and the reveal is automatic.
-
Validation: you can't lock in until your bids add up to the rent. The server checks it too.
-
Private bidding: drag a slider and the other rooms rebalance, so bids always add up to the rent.
-
One tap on Re-bid starts a fresh private Round 2 for everyone.
-
How it works: create a split, everyone bids privately at the same time, then reveal and agree.
-
Reveal on every screen at once: your room, everyone's price, and the house vote.
-
Real three-browser recording: Adeel, Sara and Bilal each see their own view of the same live room.
-
Everyone agreed. The split is final, and you can copy a summary for the group chat.
-
Phone-first: landing page, agreed split and the new-split form at 390px.
-
Why it's fair: the maximin envy-free rule. The swap test shows nobody would rather trade rooms.
-
The proof: each person's own room is the best cell in their row, so nobody would swap.
Inspiration
Every shared flat starts with the same awkward conversation: who gets the big room, and how much more should they pay? Most groups split rent evenly (unfair to whoever gets the box room) or haggle in a group chat, where the loudest person anchors everyone else. Economists solved the maths years ago with envy-free rent division, but the tools are single-player: each person fills in a form alone. We wanted the decision to happen the way it does in real life, together, at the same moment, with everyone's consent.
What it does
Quarters is a live, multiplayer room for deciding rooms and rent.
- One housemate creates a split (total rent and room names) and shares a 6-character link.
- Everyone joins. Live presence shows who's online, who's still bidding and who has locked in.
- Each person privately splits the total rent across the rooms according to what each room is worth to them. Sliders rebalance so bids always add up to the rent.
- Bids stay sealed on the server until the last seat locks in, so nobody can anchor on anyone else. Then Quarters reveals the result to everyone at once.
- The result gives each person a room and a price, plus a "Why nobody should want to swap" table. It shows, for every person and every room, how good that room would be for them at its price. Each person's own room is the best in their row.
- The house votes. If everyone agrees, the split is final. If anyone hits Re-bid, a new private round starts for everyone.
How we built it
- Fairness engine (
src/fair.ts) implements the maximin envy-free rule from Gal, Mash, Procaccia & Zick, "Which is the Fairest (Rent Division) of Them All?":- rooms are assigned to maximise total stated value
- a linear program then picks, among all envy-free prices that sum to the rent, the ones that maximise the minimum utility (value − price)
- Realtime: Supabase Realtime presence for who's online and broadcast for instant state sync, with a polling fallback.
- Backend: Postgres on Supabase. Clients get no direct table access (RLS on, no policies). Six
SECURITY DEFINERSQL functions do everything:- create a room, join, submit bids, edit bids, vote, read state
- each player holds a random secret that every write checks
- bids and secrets never leave the database before the reveal
- rent sums and room counts are validated server-side
- the reveal and the "everyone agreed" state are triggered atomically by the database
- Frontend: React 19 + Vite + TypeScript, with hand-built design tokens, light and dark themes, responsive down to phone width, keyboard-focus styles and reduced-motion support. Deployed on Vercel.
Challenges we ran into
- Keeping bids honest in a multiplayer app. Hiding other people's bids in the UI isn't enough if the API returns them. We moved every read and write behind SQL functions, so sealed bids are enforced by the database, not the client.
- Sliders that always add up. Moving one room's slider spreads the difference proportionally across the other rooms, with cent-level rounding fixes, so the "adds up to the rent" constraint is never broken.
- Rounding vs. fairness. LP prices are real numbers and rent is paid in cents. We round, then correct the drift so prices still sum exactly to the rent, and the UI reports any residual envy (it stays ≤ 1–2 cents).
Accomplishments that we're proud of
- A fairness guarantee each housemate can check in the swap table, not just a number to trust.
- The algorithm passes 200 randomised instances (2–6 people) for envy-freeness and exact rent sums.
- A three-browser end-to-end test (one on a phone viewport) passes against the live deployment: create → join → bid → automatic reveal → dispute → round 2 → unanimous agreement.
Code: https://github.com/adeelfalaksher900-creator/quarters · Live: https://quarters-rent.vercel.app
Testing & security
- Automated QA sweep (
e2e/qa.mjs, run against the live site), 44 checks, all passing:- every page at desktop and phone width, with no horizontal overflow
- axe-core accessibility audit; contrast and keyboard issues found and fixed
- input validation (rent, duplicate room names, blank or duplicate player names)
- a 2-room split with an uneven rent ($1,999.99) whose prices still sum to the cent
- full-room and late viewers, a seat that survives a reload
- an 8-person split that reveals in under 1 second
- Three-browser end-to-end test of the full create → join → bid → reveal → re-bid → agree loop on production.
- Security:
- clients can't touch tables directly (RLS on, no policies); every action goes through 6 audited SQL functions that check a per-seat secret
- bids are verifiably absent from the API until the reveal
- server-side validation of all inputs, plus a global throttle on new splits
- a private "Open on another device" link keeps the seat key in the URL fragment, which browsers never send to a server
- 0 npm vulnerabilities
What we learned
- Fair-division theory is mature and practical. The hard part is the social layer: simultaneity, privacy and consent.
- Pushing authorisation into Postgres functions gives a tiny, auditable trust boundary for an app with no accounts.
What's next for Quarters
- Budget caps per person (recent research extends maximin rent division with budget constraints)
- Shared costs beyond rooms (parking spots, chores with credits)
- Exportable agreement PDF
- Optional accounts so a split survives a cleared browser
Built during the TRMI × LovHack weekend. We used AI coding agents as permitted by the event rules.
Built With
- javascript-lp-solver
- linear-programming
- playwright
- postgresql
- react
- supabase
- supabase-realtime
- typescript
- vercel
- vite

Log in or sign up for Devpost to join the conversation.