English | νκ΅μ΄
π 1st place at 2026 I/O Extended: Hack the Beat β theme: "Make the Party Better."
Built in about three hours for a hackathon where the judges were not human: three AI judges (founder, engineer, investor) scored the project nine times, and Playwright opened the deployed link and clicked through the app itself. How we approached it is in the retrospective (νκ΅μ΄) and on LinkedIn.
"Every person you talk to at the party becomes a stamp in your passport."
Guests scan each other's QR codes to count the people they've met, collect badges along the way, and after the party secretly pick who they'd like to see again. Only mutual picks are revealed.
π Live demo: https://twin-fang.github.io/Hack-the-Beat/ β no sign-up, no app install. The UI is in Korean.
π Backend API: https://api.hack-the-beat.suhsaechan.kr
| Create a party | Your passport & QR | Join via invite link | Collect badges | Mutual match after the party |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Screenshots taken from the live service at mobile width (390px).
The judges ran this exact scenario against the deployed app, so every button label and completion message matches it word for word (in Korean).
| Step | Action | Success signal |
|---|---|---|
| 1 | On the home screen, enter "κΈμμΌ νν°" (Friday Party) as the party name and press "νν° λ§λ€κΈ°" (Create party) | "μ΄λ λ§ν¬κ° μμ±λμμ΅λλ€" (Invite link created) appears and the URL changes to /party/ |
| 2 | Press "μ΄λ λ§ν¬ 볡μ¬" (Copy invite link) | "볡μ¬λμμ΅λλ€" (Copied) appears and the invite URL is shown |
| 3 | Open the invite link, enter "κΉμμ€" as the name, and press "μ°Έμ¬νκΈ°" (Join) | "μ°Έμ¬ μλ£" (Joined), "λ§λ μ¬λ 1λͺ " (1 person met), and the "첫 λ§λ¨" (First Meeting) badge appear |
- Instant tagging with QR or a 4-character code
- Join from a link or camera, with no app install and no login
- Opening an invite link (
?from=<code>) tags you with the person who invited you and awards the First Meeting badge - A "tag by code" fallback for browsers without camera access, which is also what let the Playwright judge complete the flow
- Six badges
- First Meeting (1 person), Icebreaker (3 people), Party People (half the room), Party Master (everyone), Mission Complete (your assigned 1:1 partner), Reunion (a mutual match)
- Badges stay in "My Badges" in your browser after the party ends
- 1:1 mission partner
- Pairs you with someone you haven't met yet, so friends don't just stick together
- Secret mutual picks after the party
- Each guest privately checks who they'd like to meet again
- The backend reveals only pairs who picked each other, so a one-sided pick is never exposed
- Retention loop
- "λ€μ νν° λ§λ€κΈ°" (Create next party) on the result screen turns any guest into the host of the next gathering
flowchart TD
subgraph Client ["Frontend (React 19 + TypeScript + Vite + Tailwind/daisyUI)"]
UI_Home["HomePage (create party / join by code / my badges)"]
UI_Passport["PartyPassportPage (my QR / tag by code / 6 badges / 1:1 mission)"]
UI_Result["PartyResultPage (secret picks / mutual matches / next party)"]
Store["Zustand (badges & session persisted in localStorage)"]
Query["TanStack Query (4s polling & optimistic updates)"]
end
subgraph Server ["Backend (Spring Boot 3.4.1 + JPA + PostgreSQL)"]
API_Party["/api/parties (create party & issue host passport)"]
API_Join["/api/parties/{code}/join (join & auto-meet the inviter)"]
API_Tag["/api/parties/{code}/tag (mutual meet by 4-char code)"]
API_Picks["/api/parties/{code}/picks (secret picks & mutual match)"]
DB[(PostgreSQL - party / participant / meet / pick)]
end
UI_Home -->|POST /api/parties| API_Party
UI_Passport -->|POST /join, POST /tag| API_Join
UI_Passport -->|POST /tag| API_Tag
UI_Result -->|POST /picks, GET /matches| API_Picks
API_Party --> DB
API_Join --> DB
API_Tag --> DB
API_Picks --> DB
| Document | What's inside |
|---|---|
| docs/retrospective/ | Winning retrospective: reverse-engineering the grader, scoring ideas in parallel, agent-first UX, the self-scoring loop (English Β· νκ΅μ΄) |
| server/README.md | Backend REST API reference: endpoints, response shapes, deployment |
| docs/submission/ | What we submitted: 3-step scenario, proposal, pitch script, design asset guide (Korean) |
| docs/judging-criteria.md | The 12-item judging rubric and how we planned around it (Korean) |
| docs/personas/ | Estimated personas for the three AI judges (Korean) |
| docs/prd/ | PRDs: frontend and backend (Korean) |
| AGENTS.md | Working rules: stack, directories, code conventions, commit and deploy flow (Korean) |
# Frontend
npm install
npm run dev # http://localhost:5173
npm run build # type-check and bundle into dist/
npm run lint # oxlint
# Backend
cd server
./gradlew test # in-memory H2 tests
./gradlew bootJarThe official recap from the organizers is on LinkedIn.








