Budak Korporat: A 3D Office Card Game in Raw WebGPU
An UNO-style card game about office life, rendered in the browser with hand-written WebGPU and WGSL shaders, playable solo against bots or online with up to 16 people, with no game server.
Personal project · 2026 · TypeScript, WebGPU/WGSL, WebRTC, Firebase · Live at budak-korporat.web.app · Source is private.
At a Glance
| Aspect | Detail |
|---|---|
| Idea | Budak korporat means "corporate slave". Every card is a task another department dumps on you; empty your hand and you get to go home on time. |
| Rendering | No game engine or three.js: raw WebGPU, WGSL shaders, one instanced draw for every card, shadow mapping and MSAA. |
| Multiplayer | Peer-to-peer over WebRTC, 2 to 16 seats, bots fill empty seats. Firebase is used only to exchange connection details. |
| Platforms | Desktop and phones (portrait and landscape), installable as a PWA. |
| Skills shown | GPU rendering, game rules as a pure state machine, game AI, networking and anti-cheat design, procedural audio, mobile UX, CI/CD. |
The Game
- Cards as tasks. Four departments (Keuangan, IT, HRD, Marketing) replace UNO's colours. Number cards are Tugas 0–9, each with its own request ("Reset password bos (lagi)", "Revisi logo, besarin dikit").
- Office-themed actions. Cuti Mendadak (skip), Restrukturisasi (reverse), Lembur +2, Deadline Kemarin (+4), plus new cards: Lempar Kerjaan (hand a task to someone else), Rotasi Jabatan (everyone passes their hand on) and Kopi Sachet, which cancels a stacked draw penalty.
- House rules. Shout GAJIAN! (payday) at one card or a coworker can Lapor HRD!. Hold 20 cards and you burn out of the round. First to 500 KPI earns Promosi!.
- Three bot personalities (cautious, balanced, aggressive) that stack penalties, pick departments and catch missed GAJIAN! calls differently.
How It Works
- Rules as a pure function.
reduce(state, action) -> { state, events }with a seeded RNG and no DOM or GPU code. The 3D view only animates the events, so the rules are fully unit-tested, including a 1,000-game bot-vs-bot simulation at 2, 4, 8 and 16 seats that checks no card is ever lost. - Host-authoritative online play. The player who creates the room runs the game. Guests send intents, the host validates them and sends each player only what that seat may see (opponents' hands and the deck order never leave the host).
- No game server. Players join with a room code like LEMBUR-4821. Firebase Realtime Database (REST + streaming, no SDK) carries only the WebRTC handshake, protected by anonymous auth and strict rules; all gameplay traffic is browser to browser. A copy-paste code fallback works with no server at all.
- Rendering. All card faces are drawn procedurally into a texture atlas at load time, then rendered as one instanced draw call with a shadow map, 4× MSAA, matte paper shading and a tone-mapping pass.
Engineering Highlights
- Readable cards at any distance. Card faces are printed-paper style, lit so paper never blows out to white, with mip bias and 16× anisotropic filtering; a hover peek and a close-up inspect view show the full text.
- Scales to 16 seats. Decks scale with the table (1, 2 or 3 decks), seats sit on an oval, opponents collapse into stacks, and a small relaxation pass keeps every nameplate on screen without overlaps.
- Phone-first details. Landscape lock with a rotate prompt fallback, tap-to-peek then tap-to-play, drag-to-play, haptics, safe-area insets, and automatic resolution and MSAA fallback on slow phones.
- Procedural sound. Office ambience and sound effects are synthesised with WebAudio; the calm and tense lofi background loops are rendered offline by a small Node synthesiser and cross-fade when the game gets close.
- Shipping. GitHub Actions runs the typecheck, 176 tests and build on every push, deploys to Firebase Hosting from
main, and posts preview links on pull requests. Google Analytics tracks players, regions and real play time without names or room codes.
Screenshots
A four-player table on a phone in landscape: your hand at the bottom, the work pile and the Boss's Desk in the centre:

Inspecting a card: the department that dumped it on you, the request, and what it does:

Online lobby: share the room code, empty seats are filled by bots:

A 16-seat table with the side roster:

Status
Live and playable at budak-korporat.web.app in Chrome and Edge 113+, Safari on iOS 26+ and Chrome on Android 121+ (WebGPU required). Online play has been tested between browsers on one network; play across different networks may need a TURN relay on strict Wi-Fi. The source repository is private.
