Skip to main content

Architecture

Novactorio is deliberately framework-free on the rendering side. The game loop, simulation, and drawing are hand-written on the Canvas 2D API; React is used only for UI overlays. The codebase spans 21,000+ lines of TypeScript (21,257 LOC across src/).

Layer overview

┌─────────────────────────────────────────────────────────┐
│ React overlay (src/components/, src/ui/) │
│ Auth → Start → Game routing, HUD, menus, chat, shop │
└─────────────────────────┬───────────────────────────────┘
│ game state / events
┌─────────────────────────▼───────────────────────────────┐
│ Game engine (src/game/) │
│ engine.ts — main loop: update() + render(), entities │
│ systems.ts — supply chains, belts, pipes, AI, pollution│
│ world.ts — chunk storage, infinite scrolling │
│ noise.ts — Perlin noise terrain generation │
│ renderer.ts — 10 dedicated draw methods │
│ constants.ts, types.ts, audio.ts, postproc.ts │
└─────────────────────────┬───────────────────────────────┘

┌─────────────────────────▼───────────────────────────────┐
│ Render pipeline (src/render/) │
│ AmbientAtmosphere · ParticleEffects · PollutionOverlay │
│ ScreenEffects · SpriteManager · WeatherSystem · utils │
└─────────────────────────────────────────────────────────┘

Source map (src/)

DirectoryFilesResponsibility
game/9Engine core: loop, systems, world, noise, renderer, audio, postprocessing
core/engine, systems, typesShared engine/system/type definitions
render/7Visual effects: atmosphere, particles, pollution, weather, sprites, screen FX
components/React UI: AuthScreen, BuildMenu, ChatPanel, shop, HUD
services/auth, coop, tradeSupabase-backed services
config/Environment-driven configuration
ui/Additional UI primitives
easter/Easter-egg content
shaders/Shader definitions
lib/Shared utilities

Game engine (src/game/)

ModuleResponsibility
engine.tsGame loop (update/render), entity lifecycle, building logic, inventory, combat, particles
renderer.tsExtracted render passes: sky, ground, entities, damage numbers, etc.
systems.tsSupply chains, conveyor belts, pipe networks, enemy AI, pollution
world.tsChunk-based world, block storage, infinite scrolling
noise.tsPerlin noise for terrain generation
types.tsShared type definitions
constants.tsTuning constants
audio.tsSound effects
postproc.tsPost-processing effects

Render pipeline (src/render/)

ModuleResponsibility
AmbientAtmosphere.tsSky/atmosphere rendering
ParticleEffects.tsParticles (smoke, sparks, damage)
PollutionOverlay.tsPollution visualization
ScreenEffects.tsScreen-space effects
SpriteManager.tsSprite atlas management
WeatherSystem.tsWeather simulation
utils.tsRender helpers

Services (src/services/)

ServiceResponsibility
authSupabase authentication integration
coopCo-op multiplayer via Supabase Realtime
tradePlayer trading (Stripe-fee checkout for trades)

Rendering approach

The renderer is organized as discrete draw methods (sky, ground, entities, particles, damage numbers, …) rather than a monolithic draw call, keeping each pass cheap and debuggable. World chunks are culled to the visible area while scrolling. The render pipeline is further split into dedicated modules (atmosphere, particles, pollution, weather) layered over the base canvas.

UI overlay

React 18 renders the interface on top of the canvas: full screen routing (Auth → Start → Game), build menu, chat panel, shop, stats, and settings. State flows from the engine into React through a shared game-state bridge.

TypeScript strictness

tsconfig.app.json runs with strict typing; the project validates with tsc --noEmit (npm run typecheck) and lints with ESLint (npm run lint).

Scripts

ScriptPurpose
npm run devVite dev server
npm run buildProduction build
npm run typecheckTypeScript validation
npm run lintESLint
npm run previewBuild + local Wrangler preview
npm run deployBuild + wrangler deploy (Cloudflare)
npm run easter-eggEaster-egg generator script

Deployment target

The game builds with Vite and deploys to Cloudflare via Wrangler (wrangler.jsonc), with Supabase as the backend.