Life Grid

Conway's Game of Life runs on a seeded grid, newborn cells flashing in the accent and dying cells shrinking away

Installation
$ pnpm dlx shadcn@latest add @remocn/life-grid

Usage

LifeGrid plays Conway's Game of Life. A seeded first generation fills a density share of the cells, and every next generation follows the standard rules: a live cell with two or three live neighbors survives, and an empty cell with exactly three is born. The board wraps at the edges, so patterns leave one side and come back on the other, and the border never runs dry.

The step between generations is animated. A newborn cell pops in as an accent tile with a small overshoot, then a tile in color grows from its center and covers it. A dying cell shrinks to nothing in the first 60% of the step. Surviving cells hold still. A faint lattice marks the empty cells.

import { LifeGrid } from "@/components/remocn/life-grid";
 
export const Simulation = () => <LifeGrid />;

The component fills its parent and paints its own background. cols sets the number of columns, the row count follows the composition aspect ratio, and the square board is centered. Generations are computed once per seed, grid size and density and cached for the render, so every frame is deterministic and cheap after the first.

Timing

At 30 fps, speed={1} and framesPerGeneration={5}:

FramesMotion
0–5The seeded first generation holds still
5Generation 1 begins: newborns pop in as accent tiles, dying cells start to shrink
5–8Dying cells shrink away
7–10The core of each newborn grows over its accent tile
every 5 framesThe next generation starts

The simulation runs for as long as the composition: it precomputes durationInFrames × speed / framesPerGeneration generations. It has no loop point. Over a long run the board can settle into still lifes and blinkers; try another seed or a higher density if a seed calms down too early.

Variations

Fewer cols gives big, readable cells; more gives a fine texture. framesPerGeneration slows the simulation for a calmer bed; at 1 the board churns every frame. showGrid={false} removes the lattice, and gap={0} merges neighboring cells into solid shapes.

<LifeGrid
  cols={24}
  density={0.3}
  framesPerGeneration={8}
  gap={0.08}
  showGrid={false}
  background="#f6f5f1"
  color="#171717"
  accent="#2f6bff"
/>
Props
PropTypeDefaultDescription
cols
number48Columns, rounded, minimum 4; rows follow the frame aspect ratio
density
number0.24Share of cells alive in the seeded first generation, 0 to 1
framesPerGeneration
number5Frames each generation is held, minimum 1
gap
number0.16Gap between tiles as a fraction of the cell
showGrid
booleantrueDraws the faint lattice of empty cells
seed
number7Seeds the first generation
background
string"#111111"Background fill
color
string"#FFFFFF"Living cells and the lattice
accent
string"#E5322D"Flash color of newborn cells
speed
number1Playback multiplier; 0 holds the first generation