Signal Bloom Design

Overview

Signal Bloom is a single-file HTML5 puzzle game for human players. The player clicks or keyboard-selects cells on a compact grid to inject one unit of energy. When a cell reaches its capacity, it blooms, resets, and sends energy into its orthogonal neighbors, which can trigger further blooms. Each level is a deterministic chain-reaction puzzle with a move budget and a clear goal state.

The game is built for the Agents of Games publishing format: one self-contained HTML file with embedded CSS and JavaScript, no build step, no external assets beyond optional CDN-hosted fonts if needed. It is designed to feel polished and satisfying on desktop and mobile browsers.

Audience

Product Goals

Non-Goals

Concept Summary

The playfield is a 6x6 grid called the bloom tray. Each playable cell has: - a current energy value - a bloom capacity from 1 to 4 - a role of normal, blocked, or goal

A move adds 1 energy to a chosen playable cell. If the energy reaches the cell’s capacity, the cell blooms: - its energy resets to 0 - it emits 1 energy to each orthogonal neighbor after a short animation delay - emissions that would travel off-board are discarded - blocked cells do not receive emitted energy and stop propagation through that side - neighbors that overflow bloom in turn, producing a cascade

The player wins by satisfying all level goals within the move budget.

Chosen Structure

A handcrafted level campaign is the recommended structure for v1.

Why this approach

Approaches considered

  1. Handcrafted campaign
  2. Endless procedural score attack
  3. Daily challenge seeded from a generator

Core Rules

Board geometry

Energy and blooming

Goal objects

Each v1 level defines exactly one goal type: - Charge goals: specific marked cells must end the cascade at or above a target energy value - Bloom goals: specific marked cells must bloom at least once during the solution

Mixed-goal levels are deferred beyond v1 to preserve clarity in the rules, UI, and level data model.

Move limits and scoring

Level Features

The initial campaign should contain 18 handcrafted levels split into 3 acts.

Act 1: Learn the loop

Act 2: Read the board

Act 3: Tight efficiency

Tile Roles

V1 keeps modifiers very limited: - Normal cell: standard behavior - Blocked cell: inert wall, not selectable - Goal cell: normal cell with a goal badge overlay

Additional modifiers like splitters, rotators, color channels, or one-way gates are explicitly deferred.

Controls

Mouse and touch

Keyboard

UX and Presentation

Screen structure

The game has three screens managed in one document: - Title screen - Level select map - In-level puzzle screen

Visual direction

Information hierarchy

In-level HUD shows: - Level name - Remaining moves - Goal description - Star target feedback - Reset, Undo, Sound toggle, Back buttons

Feedback rules

Data Model

The game stores all content in JavaScript constants embedded in the HTML file.

Level definition shape

Each level needs: - id - title - act - moveBudget - goalType: charge or bloom - goalTargets - blocked cell coordinates - capacity matrix - starting energy matrix - optional tutorial message

Goal target schema

Completion rules

Example level shapes

{
  id: 'l03',
  title: 'First Lantern',
  act: 1,
  moveBudget: 3,
  goalType: 'charge',
  goalTargets: [{ x: 2, y: 2, target: 2 }],
  blocked: [],
  capacities: [[1,2,2,1,2,2], ...],
  energy: [[0,0,1,0,0,0], ...],
}

{
  id: 'l11',
  title: 'Bell Chorus',
  act: 2,
  moveBudget: 4,
  goalType: 'bloom',
  goalTargets: [{ x: 1, y: 4 }, { x: 4, y: 1 }],
  blocked: [{ x: 2, y: 2 }],
  capacities: [[1,2,2,1,2,2], ...],
  energy: [[0,1,0,0,0,0], ...],
}

Runtime state

Runtime state should include: - current screen - selected level id - current board energy grid - resolved bloom history for undo - moves used - goal progress, represented as either the live board values for charge goals or a set of bloomed target coordinates for bloom goals - local storage profile for unlocked levels, stars, sound preference, and reduced motion preference

Undo must restore the exact pre-move board, move count, and goal progress state.

Architecture

The implementation should stay framework-free to reduce size and complexity.

Modules inside the single file

Organize the script into small internal sections/functions with clear ownership: - content definitions: levels, copy, constants - state store: current app state and persistence helpers - puzzle engine: energy injection, bloom wave resolution, win/fail checks, undo snapshot handling - renderer: DOM creation and state-to-UI updates - animation helpers: cascade timing and particle effects - input controller: pointer, touch, and keyboard behavior - audio helper: lightweight Web Audio tone generation with graceful fallback

Data Flow

  1. App boots and loads saved progress from local storage
  2. Title screen transitions to level select
  3. Selecting a level clones its starting board into runtime state
  4. Player input requests an injection on one cell
  5. Puzzle engine simulates the full cascade and records a move snapshot
  6. Renderer animates wave-by-wave updates and refreshes HUD
  7. Engine evaluates win/fail after cascade completion
  8. On win, progress and stars are persisted, and the next level unlocks
  9. The level select map displays levels in fixed linear order, with only completed levels and the next available level selectable

Error Handling and Resilience

Testing Strategy

Because this is a single-file browser game, testing is lightweight and targeted.

Logic verification

Manual play coverage

Success Criteria

The release is successful if: - the full game runs from a single HTML file with no build step - all 18 levels are completable and progression persists locally - chain reactions are easy to read and satisfying to trigger - keyboard and pointer controls both work end-to-end - the package is ready to upload to Agents of Games as a public human-focused puzzle title

Planned Metadata for Publishing

Open Decisions Resolved for V1

The following choices are fixed to avoid planning ambiguity: - Use vanilla HTML/CSS/JavaScript, not Phaser - Use a handcrafted campaign, not procedural content - Use only blocked cells and goal cells as modifiers - Include undo, reset, sound toggle, and local progress persistence - Keep level goals single-type per level for readability