◆ For the curious & the technical

The Nerdy Stuff

A full 3D island life-sim that ships in ~8.5 MB — because there isn't a single art asset. Every mesh, material, character and note of music is generated in code. Here's how it all fits together.

Back to the island
◆ The headline flex

100% procedural. Zero binary assets.

No texture files, no 3D models, no audio files, no sprite sheets. The entire world is built at runtime in TypeScript — which is why the whole download is smaller than a single high-res photo on some apps.

Babylon.js 9 WebGL2 TypeScript (strict) Vite Capacitor 8 Capgo OTA Web Audio API Cloudflare Pages ~8.5 MB 0 asset files

🧱 Procedural generation

  • Meshes — assembled from Babylon primitives in code (no model files).
  • Characters — a shared rig (torso / limbs / face / hair helpers) builds the whole cast.
  • Materials & signs — code-defined colours; labels drawn live to canvas textures.
  • Audio — fully synthesised; the music is composed, the instruments & SFX synth-generated.
  • Sky — a gradient dome with a day/night crossfade. No skybox images.

🎮 Engine & rendering

  • Babylon.js 9 on WebGL2.
  • Post-FX pipeline: bloom, ACES tone-mapping, vignette, FXAA + a glow layer.
  • Real-time sun & dynamic shadows that move with the in-game clock.
  • Custom GPU vertex-shader for foliage wind-sway.
  • Shader warm-up on load & frozen static meshes for a hitch-free first frame.

🏗️ Language & architecture

  • TypeScript, strict — and a point of pride: zero as any, zero @ts-ignore.
  • System-based (ECS-flavoured): every feature is an ISystem in a strict dependency order.
  • Systems never import each other — they talk only through a fully-typed event bus.
  • Decoupled loop: simulation is a fixed 1/60s step; render is capped at 60fps.
  • Math-based collision (no physics engine) and per-system save/load serialisation.

📦 Cross-platform & delivery

  • One codebase → desktop browser, mobile browser and native Android (Capacitor 8).
  • Over-the-air updates (Capgo) — ship fixes to installed apps with no store round-trip; auto-rollback on a bad bundle.
  • Signed release APK (v2 APK Signature Scheme).
  • CI/CD on Cloudflare Pages — git-push deploys, auto-SSL, global CDN.
  • One version number locked across package.json, the git tag and the live bundle.
◆ How it fits together

The architecture, at a glance

 DELIVERY ─────────────────────────────────────────────────────────────────
                                                          ┌────────────────┐
  Desktop browser   Mobile browser   Android (native)     │  Cloudflare    │
       │                 │           Capacitor 8 WebView  │  Pages         │◄─ git push
       └────────┬────────┴──────────────────┤             │  CDN + SSL     │
                │                            │  Capgo OTA  └───────┬────────┘
                │                            │  live bundle ◄──────┘
                ▼                            ▼  (auto-rollback)
 ═══════════════════════════════════════════════════════════════════════════
  RUNTIME    index.html → main.ts → Game
                                     │
                  ┌──────────────────┴───────────────────┐
                  ▼                                       ▼
            ┌──────────────────┐               ┌────────────────────┐
            │  GAME LOOP        │  renders      │  Babylon.js 9      │
            │  sim   = 1/60 fix │ ────────────► │  WebGL2 · bloom    │
            │  render ≤ 60 fps  │               │  shadows · glow    │
            └────────┬─────────┘                │  GPU wind shader   │
                     │ update(dt)               └────────────────────┘
                     ▼
 ═══════════════════════════════════════════════════════════════════════════
  CORE   ┌──────────────┐  ┌──────────────────┐  ┌──────────────────┐
         │ GameContext  │  │   EventBus        │  │  SystemManager   │
         │ service loc. │  │   fully typed     │  │  ISystem order   │
         └──────────────┘  │ (no system imports│  │  init/update/    │
                           │  another system)  │  │  dispose         │
                           └────────┬──────────┘  └──────────────────┘
  SYSTEMS ◄─────────────────────────┴────────────────────────────────────►
   brew · friendship · mainQuest · personalQuests · womensDay · festival ·
   pubs · vibrancy · farming · weather · audio · graphics · lighting · … (~44)
            │                       │                       │
            ▼                       ▼                       ▼
 ═══════════════════════════════════════════════════════════════════════════
  PROCEDURAL GEN              CONTENT (data)          PERSISTENCE
  meshes · characters         catalog · quests        SaveManager → per-system
  canvas textures · sky       festivals · flowers     serialize → localStorage
  Web-Audio synth + score      …                       / Capacitor Preferences
                →  NO asset files
◆ Under the bonnet

Every system, listed

~44 independent systems, each owning one slice of the game and coordinating only through the typed event bus. Registered in a deliberate dependency order.

Core loop, input & world

Brewing, economy & growing

People, story & progression

Festivals, decorating & play

Rendering, atmosphere & audio

◆ Casual brag material

A few numbers & quirks

⚡ Performance & feel

  • Thermal-aware: a render-DPR cap + fps cap cut GPU load ~4× — without changing game feel (the sim is fixed-step).
  • Identical timing on a 60Hz and a 120Hz phone.
  • QA via headless soak tests (Puppeteer + SwiftShader software-GL) that fast-forward seasons, festivals & save/load.

🌍 The world

  • A 9-act main quest, ~50+ chained friendship favours, a hidden finale.
  • Four seasonal festivals with a band & minigames; live day/night & a turning year.
  • A wardrobe of 17 procedural outfits — every character built from the same code rig.
  • British island, British spelling, golden hour all the way down.
Made with Babylon.js · TypeScript · Vite · Capacitor — and rather a lot of care.