Skip to content

Web minimal bundle

The Web minimal bundle is the smallest possible Forge bundle: one screen, one loop, four unlockable tools, every system wired through a GameManager spine. Pure DOM, no canvas, no game engine. About 600 lines of TypeScript across 9 source files plus 5 composed system components.

Use this when you want to learn the harness. The whole thing reads in 10 minutes and demonstrates every pattern the bigger bundles use, without the visual novel or 2D platformer noise.

  • 9 TypeScript files: GameManager spine, scenes (boot / tutorial / complete), tools registry, goals registry, page chrome.
  • Single-screen loop: hammer the anvil 100 times. Tools unlock at 25 / 50 / 75 strikes. Saves on every strike.
  • 4 unlockable tools (hammer, bellows, tongs, chisel) with per-tool cooldowns and combo behavior.
  • One background plate (bg_tutorial_forge.png) from the asset bank and 4 tool icons.

The bundle ships with 5 systems registered:

  • EventBus carries strike, unlock, and goal-reached events.
  • StateMachine drives boot / tutorial / complete.
  • SaveSystem persists progress to localStorage (debounced 2 seconds).
  • SettingsManager renders audio / video / accessibility menus.
  • ThemeManager ships three themes (default dark, light, high contrast) via CSS variables.

No AudioManager (a single click is too small a loop to justify a mixer). No InputManager (click plus keyboard activator is overkill for one button). No CharacterController (no avatar in the world). No ProjectConfig (no constants worth extracting at this scale).

InputAction
Left click on the anvilHammer strike (+1, builds heat)
Space / Enter (with anvil focused)Hammer strike
Click bellows (unlocks at 25)+30 heat. Hot strikes count double
Click tongs (unlocks at 50)5s combo grip. Rapid strikes chain a streak bonus
Click chisel (unlocks at 75)Instant +5 strikes
R (after completion)Restart the tutorial
SystemDrives
Hammer (always)+1 strike per anvil click. Builds heat by 4
HeatDecays 6/sec. At >= 50, anvil glows + strikes count double
Bellows (>= 25)+30 heat per click. 1.5s cooldown
Tongs (>= 50)5s grip. Consecutive strikes within 600ms add a streak bonus (+0.5/streak, capped at +5). 8s cooldown
Chisel (>= 75)Instant +5 strikes (does not stack heat / combo). 10s cooldown
SaveEvery strike autosaves to localStorage (debounced 2s)
GoalsFire goal_reached once each as hammerCount crosses target

Three exercises, each takes 5 to 15 minutes. The first one teaches the pattern; the rest are obvious from the source comments.

Add a tool: drop a 256x256 PNG into public/icons/icon_<name>.png. Add an entry to src/data/tools.ts:

{ id: 'rivet', label: 'Rivet driver', icon: '/icons/icon_rivet.png',
kind: 'chisel', // reuse an existing kind for free behavior
unlockAt: 60,
cooldownMs: 6000,
hint: 'Drives a rivet. Instant +3 strikes.' }

Tools render in the bottom palette automatically. To wire new behavior, add a ToolKind variant in tools.ts and a matching branch in handleToolClick() in tutorial-scene.ts.

Add a goal: append to src/data/goals.ts in ascending target order:

{ id: 'masterpiece', target: 200,
message: 'A masterpiece is forged.',
banner: 'Masterpiece complete' }

The highest target ends the run and transitions to the complete scene. Intermediate goals fire goal_reached and show the banner if banner is set.

Add a theme: append to THEMES in src/systems/theme-manager.ts. Switch via devtools: __forge.theme.setTheme('your-id'). The page reskins via CSS variables on <body>.

The Web minimal bundle is the reference implementation when building any new bundle that fits on one screen. If you’re going to read one bundle from top to bottom to learn how Forge composes systems, this is the one. The bigger bundles add a lot of game-specific logic. This one is just the spine.