one file · zero dependencies · canvas 2d

flowers.js

Algorithmic doodle flowers that grow around the edges of things — grown from a pencil doodle in a meeting notebook.

fig. 1 — a card, all four edges

A flowery card

Flowers sprout outward from every edge.

fig. 2 — after the original sketch
fig. 3 — around a headline
Even around a headline
fig. 4 — theme: 'autumn'
fig. 5 — theme: 'noir'

The noir cut

Greyscale blooms, silver stems.

fig. 6 — theme: 'meadow' (2.3× density)
fig. 7 — trigger: 'hover'

Hover over me 🌱

Blooms while you’re here, wilts when you go.

fig. 8 — cranes.js · count: 3

Under construction 🏗️

Cranes assemble along the roof; flowers take the ground floor.

fig. 9 — kites.js · count: 3
fig. 10 — heli.js · a bell 412 arrives, hovers, lands on the button

…or click any figure to regrow just it

usage

<script src="flowers.js"></script>
<script src="cranes.js"></script>
<script src="kites.js"></script>
<script src="heli.js"></script>
<script>
  const field = Flowers.grow('#card', {
    edges: ['top', 'bottom', 'left', 'right'],
    theme: 'autumn',   // or 'noir', 'meadow' — omit for the classic garden
    trigger: 'hover',  // or 'load' (default), 'visible', 'manual'
    density: 1,        // plant count multiplier
    size: [26, 78],    // stem length range, px
    seed: 7,           // set for a reproducible arrangement
  });
  field.regrow();      // fresh arrangement, replay the growth

  const site = Cranes.build('#hero', {
    count: 3,          // a request — packed so they never overlap
    labels: ['FABCO'], // nameplates painted on some decks
    idle: true,        // hooks keep gently swaying after assembly
  });
  site.rebuild();      // a new skyline

  const sky = Kites.fly('#park', { count: 3 });
  sky.relaunch();      // little people, fresh kites

  const pad = Heli.hover('#cta', { labels: ['G-MEGN'] });
  pad.refly();         // fly in again with a new livery

  // the same four, in three dimensions — one extra file each:
  Flowers3D.grow('#card');  Cranes3D.build('#hero');
  Kites3D.fly('#park');     Heli3D.hover('#cta');
</script>

part ii — in three dimensions

Same doodles, real depth: hand-rolled perspective, painter’s sort, no libraries.

fig. 11 — flowers3d.js · a garden with a breeze
fig. 12 — cranes3d.js · the jibs slew
fig. 13 — kites3d.js · box kites are boxes now
fig. 14 — heli3d.js · hovers on a turntable, then lands

The 3D helipad 🟡

Watch it turn on the spot before it sets down.

colophon

These renderers were generated by Claude Fable, Anthropic’s Claude 5 model, working from hand-drawn images in an old meeting notebook — pencil flowers curling up a page margin, and a lattice tower crane labelled “FABCO” doodled beside an October 2015 to-do list. The kites and the Bell 412 were asked for afterwards and drawn to match. Sketches: the notebook’s. Code: Claude Fable. The graph paper is a nod to where it all started.