A fast, touch‑friendly survival take on Conway’s Game of Life. You command a resilient green colony battling red threats that spawn, move, and escalate over time. Play on desktop or mobile with a canvas‑accelerated grid, bottom HUD, and an always‑visible pattern dock. Scores persist per difficulty, with optional Postgres storage.
- Survival mode with escalating difficulty (“Level”) and threat waves
- Always‑visible Pattern Dock with per‑pattern cooldowns
- Mobile‑first UI: floating HUD (Play/Pause, Controls, Reset, 🏆), mini stats overlay
- Canvas 2D renderer with adaptive grid sizing and crisp cell borders
- Leaderboards per difficulty, plus an all‑time modal across difficulties
- Onboarding splash with dynamic step sizing and quick controls tutorial
- Keyboard shortcuts for power users (Space = Play/Pause, R = Reset)
- Unit conversion rule: when red and green groups touch, the larger group converts the smaller one. Your colony survives as long as at least one green cell remains.
- Threats: hostile patterns (e.g., gliders, LWSS, curated patterns) spawn near your cells. Spawn probability scales by difficulty and escalates with time.
- Difficulty escalation (“Level”): every 10s of survival during play increases an internal level. Each level ramps:
- Spawn rate multiplier
- Max simultaneous threats The current Level is visible in Stats and resets on defeat or reset.
- Scoring: survival time and combat events contribute to score. Notifications highlight milestones (time, score, generations).
- Patterns & cooldowns:
- Select from classic Life patterns (Glider, Block, Blinker, Beacon, Toad, R‑Pentomino, LWSS, Pulsar, Glider Gun).
- Each applies a cooldown that scales inversely with sim speed (higher speed → shorter real‑time cooldown).
- Cooldowns freeze while paused (both visually and in enforcement). Resuming shifts timestamps so remaining time is preserved.
- Placement modes: stamping is default. Replace mode exists in the store and can be extended to UI if desired.
- Controls:
- Play/Pause, Speed slider, Reset, Leaderboard modal.
- Touch devices: larger hit targets, manipulation‑safe touch events.
- Pattern Dock: always visible above the bottom HUD. Wraps into multiple rows; chips show full pattern names and a thin progress bar for cooldown. On ultra‑narrow screens chips condense but retain names.
- HUD: floating bottom bar with Play/Pause, Controls (opens modal), Reset, and 🏆 Leaderboard. When Controls or Leaderboard is open, the game pauses and resumes after closing (only if it was running before).
- Mini Stats: small glass overlay (top‑left) with SCR/GEN/THRT. The game canvas reserves bottom padding so it never sits under HUD/dock.
- Stack: React + Vite + Zustand (
subscribeWithSelector) + Canvas 2D. - Core components:
Grid2D.tsx: Canvas renderer. Adaptive sizing uses aResizeObserverwith throttling. It computes a grid that fills available space, clamps dimensions, and recomputes a pixel‑perfectcellSize. Grid lines and borders draw only when cells are large enough for clarity.GameOfLife.tsx: Page layout. Renders control panels (desktop), canvas, Game Over overlay, mobile HUD, pattern dock, and stats overlay.GameControls.tsx,DifficultySelector.tsx,PatternSelector.tsx(desktop),StatsPanel.tsx.- Mobile‑only:
MobileHUD.tsx,MobilePatternDock.tsx,MobileControlsModal.tsx,MobileStatsOverlay.tsx. - Onboarding:
OnboardingModal.tsxwith dynamically sized steps.
- Store:
client/src/lib/stores/useGameOfLife.tsx- State: grid data, timing, speed, survival stats, difficulty mode, escalation level, threat sets, cooldowns, progression (resources/unlocks primitives remain as scaffolding), notifications, stamping state.
- Timers: sim loop interval (based on speed), threat spawn interval, optional regeneration hooks.
- Pause semantics:
stop()recordspauseTimeand setsisRunning=false. Cooldown checks and scaling use an “effective now” ofpauseTimewhen paused, so time truly freezes. Onstart(), time spent paused is added to future timestamps to resume fairly. - Grid ops:
step()computes next generation, applies unit conversion and threat ownership diffusion, updates stats, and triggers game over on extinction. - Pattern stamping: strict cooldown enforcement at click/touch; cooldown anchors to
pauseTimewhen applied in a paused state.
- Dev server:
server/vite.tsruns Vite in middleware mode (development) and serves the SPA. In production it serves static files fromdist/public. - API routes:
server/routes.tsGET /api/high-scores?difficulty=easy|normal|hard→ top 10 scores for a difficultyPOST /api/high-scores→ create a score. Validated with zod against the shared schema.
- Storage:
server/storage.ts- Default is
FileStorage(JSON file persistence) - Stores scores indata/high-scores.json - Alternative:
MemStorage(in-memory, lost on restart) - Alternative:
DBStorage(PostgreSQL via Drizzle ORM) - Toggle by changing the export at the bottom of the file
- Default is
- Schema:
shared/schema.ts(Drizzle + zod)- Table
high_scoreswith fields:id,username,score,timeSurvived,threatsDefeated,cellsPlaced,timestamp,difficulty.
- Table
FileStorage (Default - Production)
- Persists scores to
data/high-scores.json - Auto-creates directory structure on startup
- Maintains ID sequence across restarts
- No database required
- Simple backup: copy JSON file
To enable Postgres (DBStorage):
- Set
DATABASE_URLin the environment. - Switch
export const storage = new FileStorage();toexport const storage = new DBStorage();inserver/storage.ts. - Apply the schema to your DB (Drizzle migrations or manual create) and restart the server.
- Development:
npm run dev- Starts Express on port 3001 and Vite middleware; client is served via Vite; API proxied at
/api.
- Starts Express on port 3001 and Vite middleware; client is served via Vite; API proxied at
- Build:
npm run build- Builds client to
dist/public(Vite), bundles server todist/index.js(esbuild).
- Builds client to
- Production:
npm start- Runs Node on the bundled server; serves static client and
/api.
- Runs Node on the bundled server; serves static client and
The application is deployed to /opt/seedtovoid/ and runs as a systemd service.
# 1. Build the application
npm run build
# 2. Deploy to production
sudo rsync -av dist/ /opt/seedtovoid/dist/
# 3. Restart the service
sudo systemctl restart seedtovoid.serviceWhen only client files change (HTML, CSS, JS), deploy without restarting:
# Build only
npm run build
# Deploy only static files
sudo rsync -av dist/public/ /opt/seedtovoid/dist/public/
# No restart needed - Express serves updated files immediately# Check status
systemctl status seedtovoid.service
# View logs
journalctl -u seedtovoid -n 100 -f
# Restart service
sudo systemctl restart seedtovoid.serviceLocated at /etc/seedtovoid.env:
NODE_ENV=production
PORT=4006
NODE_PATH=/opt/seedtovoid/node_modules- High Scores: Stored in
/opt/seedtovoid/data/high-scores.json - Backup:
sudo cp /opt/seedtovoid/data/high-scores.json ~/backup-scores-$(date +%F).json - Restore:
sudo cp ~/backup-scores-YYYY-MM-DD.json /opt/seedtovoid/data/high-scores.json
- Difficulty presets:
DIFFICULTY_SETTINGSinuseGameOfLife.tsxcontrol spawn rate multipliers, max threats, and escalation rate per mode. - Pattern cooldowns: defined in the store (and mirrored in UI helpers). Adjust per pattern and the speed scaling rule as needed.
- Grid sizing: see
Grid2D.calculateOptimalGridSize()for min/max grid dimensions and target cell sizes. - Mobile layout: most rules live in
client/src/index.cssunder mobile media queries. The canvas reserves bottom padding so HUD/dock never overlap the interactive grid.
- Keyboard:
Spacetoggles Play/Pause,Rresets;Hreopens onboarding. - Touch: simple tap to toggle a cell or stamp the selected pattern. Hit targets are widened;
touchAction: 'manipulation'avoids scroll interference.
The application includes Google Analytics (G-740WZ4LG3W) for tracking:
- Page views and user sessions
- Gameplay interactions and events
- Traffic sources and user behavior
The tracking code is loaded in client/index.html and automatically tracks page views. No additional configuration required.
- Replace mode is wired in the store; surfacing it in UI is straightforward (toggle chip in Controls).
- Resources/unlocks scaffolding exists in the store and logs; it's disabled in onboarding and not exposed in UI.
- Cooldown/Level reset behavior:
- Cooldowns freeze when paused; resume honors the remaining time.
- Level resets to 0 on defeat and on reset/try‑again. Escalation resumes once playing.
client/– React app (Vite). Key paths:src/components/– UI: grid, controls, modals, mobile overlayssrc/lib/stores/useGameOfLife.tsx– game state and logicsrc/lib/patterns.ts– classic Life patternssrc/index.css– design system and responsive styles
server/– Express API + Vite middleware (dev) or static (prod)shared/– DB schema and zod validator for high scoresdist/– build output (client inpublic/, server bundle in root)
MIT