A PWA for honest conversations: 6 rounds, 200+ questions, circle / pairs / reflection mechanics, adjustable candour, offline and serverless online mode by room code. Concept, game script, content, design and front end.
Tabletop "get closer" games are sold as card decks: beautiful but inconvenient. You carry them around, the questions never change, and the depth can't be tuned to the company — what's fine with a close friend is awkward among near-strangers.
I wanted the same experience — a circle of people, a question, the silence before the answer — without the physical box. That's how "Intimacy" appeared: an app that opens from a link on a phone and leads a group through a conversation from the first, light questions to truly vulnerable ones.
"Design not an app with questions but the script of an evening. The interface is the host: it sets the pace, keeps the turn order, goes quiet in time and never pulls attention to itself."
Three design requirements: the screen must not interfere with eye contact; the game must work without a facilitator; depth must be adjustable.

The game is built as a rising arc of closeness. Each round has its colour, mechanic and level of candour:
The colour sequence from red to violet works as a progress scale: you can see where you are in the evening without reading a single number.

Monotony kills these games faster than bad questions. So there are three interaction formats: circle (one answers, everyone listens), pairs (the app splits the group into pairs and reshuffles them between sub-rounds) and (the final round, the answer addressed to yourself).
Within a round a player draws several cards face down, flips them with a tap and picks the one they're ready to answer. The right to choose removes the feeling of interrogation and leaves the person in control.
The most delicate round, "Intimacy", isn't fixed. Before it starts the group picks a level — soft, medium or explicit — and the deck builds cumulatively for it. The whole round can be skipped with one tap. This answers the genre's main risk: one wrong card can shut a person down for the rest of the evening.

Remote play works like play at the table. One participant creates a room and gets a six-digit code — easy to read aloud on a video call; the others enter it and join from their phones.
Technically it's peer-to-peer (WebRTC via PeerJS) with the host as the source of truth: game state lives on the room creator's device and is broadcast to everyone; players' actions come back to it. The project has no back end of its own — no accounts, no database, no one's answers on anyone else's disk. For a game about vulnerability that's part of the promise.
// multiplayerManager.ts — host: subscribe to Zustand → broadcast to all peers
function startHostSync() {
storeUnsubscribe = useGameStore.subscribe((state, prevState) => {
const changed = SYNC_FIELDS.some((key) => state[key] !== prevState[key]);
if (changed && hostInstance) {
hostInstance.broadcast({ type: 'state-update', state: getStateSyncPayload(state) });
}
});
}
A built-in deck editor lets you change, delete or add questions in any round and restore the original deck with one button. The game can be adapted to a specific group, a therapy circle or your own event.

After each round a player rates their own candour on a ten-point scale and can leave a short note. At the end everyone gets a personal chart: where it was easiest to open up, which round was hardest, the average honesty of the evening and all notes in one place.
Not gamification, not competition — scores are compared with nothing. It's a prompt for the last conversation: "why the dip on round four?"

// sounds.ts — card flip: a sine 800 → 400 Hz over 150 ms, not a single file
playFlip() {
const osc = ctx.createOscillator(), gain = ctx.createGain();
osc.connect(gain); gain.connect(ctx.destination);
osc.frequency.setValueAtTime(800, ctx.currentTime);
osc.frequency.exponentialRampToValueAtTime(400, ctx.currentTime + 0.15);
gain.gain.setValueAtTime(0.15, ctx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.15);
osc.start(); osc.stop(ctx.currentTime + 0.15);
}
Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · Framer Motion · Zustand (persisted) · PeerJS / WebRTC · Recharts · Web Audio API · Service Worker (PWA)
A finished product that runs from a phone with no install, needs no server and stores none of the players' answers. 200+ original questions, six rounds, three mechanics, three depth levels, offline and online modes, a deck editor and personal stats — plus a separate landing that explains it all in one scroll.
The main discovery: in games about closeness, design works by subtraction. The final card screen is a question, a timer and one button.