Skip to content
All Projects

Do You Know Well

Two-player card answer game with encrypted online play

LaravelLaravel 13Inertia.jsInertia.js 2ReactReact 18TypeScriptTailwind CSSTailwind CSS 3Framer MotionPostgreSQLPostgreSQL 16PestVitestPlaywrightDockerCaddy

Overview

Do You Know Well is a mobile-first card game I built alone, in the spirit of the Newlywed Game. One player answers questions about themselves, the other guesses, and the app scores how well they know each other. It has two modes. Play Local is pass-and-play on one phone with no account and no server. Play Online sends the guesser a link, and the answers live on the server encrypted at rest. It is live at dykw.agungsmaraputra.com.

Challenge

Two very different products had to feel like one game. Local play should start in a second with nothing to sign up for, while online play needs accounts, a backend, and answers that are personal enough that they should not sit in the database as plain text. I wanted both modes to share the same cards, flow, and scoring rules, so a fix in one would not drift from the other.

Approach

The game logic is a pure TypeScript state machine with no React, DOM, or network code in it. Both modes drive the same machine and differ only in how state moves between the two players, in memory for Local and through Laravel for Online. Scoring is pluggable behind one interface. Local uses exact matching after normalization, and Online uses a UTF-8 safe Levenshtein distance on the server, so a guess like "cofee" still counts for "coffee".

For Online, each session gets its own AES-256-GCM key, which is wrapped before it is stored, and every answer is encrypted with it. Passwords use argon2id, reset links expire after 60 minutes, and sessions that show unusual request bursts are logged for review.

The interface aims for a mobile game feel. Cards are oversized with hard shadows, the swipe deck takes touch, mouse, and keyboard arrows, haptic feedback fires where the phone supports it, and desktop gets its own two-column layout instead of a phone frame.

Tech Stack

Layer Technology
Backend Laravel 13
Frontend React 18 via Inertia.js 2, TypeScript
Styling Tailwind CSS 3, Framer Motion
Database PostgreSQL 16
Testing Pest, Vitest, Playwright
Hosting Docker, Caddy, self-managed VPS

Key Implementation Details

  • Pure TypeScript game state machine shared by both modes, kept free of UI and network code so it is tested on its own
  • Swappable scoring: exact match for Local, UTF-8 safe Levenshtein matching with a threshold for Online
  • Per-session AES-256-GCM encryption of every online answer, with each session key wrapped before storage
  • Results screen with a count-up score and per-question review. In Online, the guesser sees only right or wrong unless the answering player chooses to reveal their answers
  • Swipe deck with touch, mouse, and keyboard input, plus haptics through the Vibrate API
  • 228 Pest tests, 141 Vitest tests, and Playwright end-to-end flows for the landing page, local play, online play, and breakpoints

Outcome

Live in production on my own VPS, deployed with Docker behind Caddy. Lighthouse performance scored 0.97 on desktop in the final pre-launch audit. Both modes ship from one codebase and share the same game logic.