AK / PORTFOLIOWork
Case [05]2025

A browser-based cyberpunk city where every skyscraper is someone's GitHub contribution graph.

Three.js + React Three Fiber, WebGL2 → WebGPU. Each developer becomes a procedurally-generated tower — floors are months, windows are daily commits, district placement is activity tier. In architecture and prototype phase.

Role
Design + Architecture (solo, in progress)
Stack
Three.jsReactTypeScriptNode.jsFastifyPostgreSQLRedis
Timeline
2025–Now
Status
Prototype
Ownership
Solo architecture + design
Outcome
12 design documents and a staged roadmap

Context

I wanted to build the visualisation I'd actually want to look at: not another contribution-graph heatmap, but a place. A dense, neon-lit city where every developer's year on GitHub becomes a building — floors for months, windows for days, districts by activity tier. Blade Runner meets contributionsCollection.

The idea is silly on the surface. The interesting part is the engineering: how do you render hundreds to thousands of illuminated buildings in a browser, at cinematic quality, without frying the GPU?

Architecture

Ingest is slow, patient, and rate-limit-aware. Build is offline and produces immutable spatial tiles. The browser only ever loads tiles — never talks to Postgres or GitHub at runtime — which is what makes streaming and CDN caching tractable.

Constraint

  • Must run in a browser. Rules out Unity / Unreal. WebGL2 today, WebGPU as the target.
  • Scale. Aim: several thousand buildings, each with 30–40 floors, each floor ~30 windows. That's millions of windows — individual meshes are not an option.
  • GitHub API budget. Rate limits mean batching, caching, and one-request-per-user-per-year is the ceiling.
  • First-load budget. People bounce if a browser tab spins for 20 seconds. Streaming has to be a first-class concern, not a Phase 2.

Move

  • Three.js + React Three Fiber for the render layer. Three's ecosystem (drei, postprocessing, three-stdlib) is the only realistic path to AAA-adjacent fidelity in a browser today, and R3F makes the scene graph composable in React.
  • One InstancedMesh per LOD tier per district. Building geometry is a shared instanced mesh; per-building variation (height, floor count, window pattern) lives in per-instance attributes.
  • A packed DataTexture window atlas. Every window's emissive intensity across every building lives in a single texture; a single shader samples it. This is what makes millions of windows possible in a handful of draw calls.
  • Spatial chunks. The city is tiled into 256m squares (.citychunk binary format, typed-array-friendly). Web Workers stream them in as the camera moves.
  • GitHub GraphQL contributionsCollection. One request per user per year for daily contribution counts — not the REST endpoint, which would 10× the request count.
  • Backend stack. Node.js + TypeScript + Fastify as the API gateway; PostgreSQL for canonical data (users, days, monthly_agg); Redis for cache and queues; BullMQ for ingest jobs; S3-compatible blob for pre-built tiles.
  • Atmosphere. HDRI + ACES tonemapping, postprocessing for Bloom / SSGI / DoF / FilmGrain, GPU particle rain, planar reflections on wet roads, volumetric fog raymarched in screen space.
  • WebGPU behind a feature flag. Same scene graph, better compute; GPU-driven traffic and pedestrian splines land here first. Transform-feedback fallback keeps WebGL2 users in the game.

Result

Design phase. What's decided and documented:

  • 12 design docs covering tech stack, system architecture, data pipeline, rendering pipeline, procedural city generation, LOD strategy, camera / interaction UX, folder structure, roadmap, and risk register.
  • Data-flow contract between CSV → ingest worker → GraphQL → Postgres → city-builder → blob storage → streaming loader → instanced renderer.
  • A concrete building-mapping table: 1 user → 1 tower, 1 month with any commits → 1 floor (empty months skipped, so heights vary), 1 day → 1 window, commit count → emissive intensity (dim → neon “supernova”).
  • A staged roadmap: MVP (single building → small block → small city) before Production (streaming, weather, traffic, WebGPU).

Nothing is shipped yet. This is the version of the plan that's survived enough poking that I'm confident scaffolding won't immediately have to be thrown away.

Open Risks

  • DataTexture size ceilings. WebGL2 caps around 16k×16k. At millions of windows, the atlas has to page or tile — not a blocker, but not free either.
  • Bloom on wet streets is expensive. The atmospheric look depends on the postprocessing stack behaving on mid-range GPUs. A quality-tier fallback needs to be in from day one, not bolted on later.
  • First-tile time. Even with streaming, the first frame has to include something interesting. A hand-authored downtown tile, pre-built and cached at the CDN edge, is probably the right answer.
  • GitHub rate limits. Backfilling 1000+ users of 3-year history in one pass will hit ceilings. Ingest has to be a slow, patient background job — not a "click to load" affordance.

Command palette

Search and jump to any page.