A tree, or a cactus, that grows itself from a seed: tapered branches fork from the root (or a ribbed saguaro raises its arms, or prickly pear pads sprout from pad rims), leaves, blossoms or cactus flowers open at the tips, then it sways in the breeze and lets petals fall.

  • canvas
  • generative
  • tree
  • botanical
  • seeded
  • growth
  • wind
  • hero
  • cactus
  • saguaro
Preset

Installation

pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/generative-tree.json

Needs a React + Tailwind project set up with shadcn. Copies the effect into your project, along with lib/effect-runtime.ts, the small WebGL layer it runs on. No other dependencies.

Or from npm

pnpm add @kagadmodyaa/effects
import { GenerativeTree } from '@kagadmodyaa/effects/generative-tree'

One package with every free effect, one import path each. No Tailwind or shadcn needed, and no stylesheet to import: the few layout rules an effect needs come with it. The npm package and the command above ship the same source.

Usage

Use it like any other component. Choose a theme with preset; any prop you pass as well overrides the preset.

import { useRef } from 'react'
import { GenerativeTree, type GenerativeTreeHandle } from '@/components/effects/generative-tree/generative-tree'

export function Specimen() {
  const tree = useRef<GenerativeTreeHandle>(null)
  return (
    <section className="relative h-[560px]">
      {/* fills its parent; the same seed always grows the same tree */}
      <GenerativeTree ref={tree} preset="Sakura" seed={1287} className="absolute inset-0" />
      <button onClick={() => tree.current?.regrow()} className="absolute bottom-6 left-6">Grow another</button>
    </section>
  )
}

// Fully grown at once (no growth animation):      <GenerativeTree preset="Bonsai" grown />
// Growth tied to scroll (0..1):                   <GenerativeTree preset="Autumn Oak" progress={scrollProgress} />
// Over your own page, tree only, placed right:    <GenerativeTree preset="Ink Study" transparent frame={[0.5, 0.05, 0.95, 0.95]} />
// A cactus instead of a tree:                     <GenerativeTree preset="Desert Bloom" />  or  <GenerativeTree form="cactus" cactusStyle="saguaro" />
// Presets: Sakura, Autumn Oak, Ink Study (ink on paper), Moonlit (silver on night), Bonsai, Saguaro (dusk), Desert Bloom (prickly pear).
// The stage above is <GenerativeTreeShowcase />, also exported, with a headline and a Grow another button.
<GenerativeTree preset="Autumn Oak" form={"tree"} />

Presets

  • Sakura
  • Autumn Oak
  • Ink Study
  • Moonlit
  • Bonsai
  • Saguaro
  • Desert Bloom

Props

NameTypeDefaultDescription
preset'Sakura' | 'Autumn Oak' | 'Ink Study' | 'Moonlit' | 'Bonsai' | 'Saguaro' | 'Desert Bloom'none (the defaults below)A named theme. Any prop you pass as well overrides the preset’s value.
form'tree' | 'cactus''tree'tree: a branching tree. cactus: a saguaro or a prickly pear (see Cactus style); it rocks a little in the wind instead of swaying.
cactusStyle'saguaro' | 'prickly-pear''saguaro'With form cactus. saguaro: a ribbed column whose arms elbow upward (depth sets the arms, spread their reach). prickly-pear: flat pads sprouting from pad rims (depth sets the generations, spread the fan).
seednumber1287The seed the tree grows from. The same seed and shape always grow the same tree; ref.current.regrow(seed?) grows another. Range 1 to 9999.
depthnumber8How many times the branches fork. Range 4 to 10.
spreadnumber27Angle between a branch and its side shoots. Range 8 to 60 °.
gnarlnumber0.45How much the branches bend and wander. Range 0 to 1.
densitynumber0.8How much foliage grows on the outer branches. On a cactus: how many spines. Range 0 to 1.
leafSizenumber1Size of the leaves, blossoms or dots. Range 0.5 to 2.
leafShape'leaf' | 'blossom' | 'dot''blossom'leaf: almond leaves with a midrib. blossom: five-petal flowers with a few small leaves. dot: round dabs of foliage that gather into pads.
growDurationnumber7Seconds from seed to full leaf. Range 1 to 30 s.
windnumber0.5Strength of the breeze; the tips sway more than the trunk. Range 0 to 1.5.
petalsnumber28How many petals or leaves are falling at once, once the tree is grown. Range 0 to 120.
pointerWindbooleantrueMoving the pointer through the canopy pushes the branches like a gust.
trunkColorstring'#2b2327'Bark: the trunk and branches. On a cactus: its spines, areoles and fruit. A hex colour.
leafColorstring'#8aa36b'Foliage. With leafShape 'blossom' it colours the small leaves between the flowers. On a cactus: its body. A hex colour.
blossomColorstring'#f3a6bd'Blossoms. With 'leaf' or 'dot' it is a second foliage tone mixed in. On a cactus: its flowers. A hex colour.
backgroundstring'#f7f0ea'Page colour. A hex colour.
halonumber0.45A soft light behind the canopy. Range 0 to 1.
groundbooleantrueA ground line and a soft shadow under the trunk.
transparentbooleanfalseDraw only the tree and its petals, so it sits over your own page.
classNamestring—Extra class on the root element. The effect fills its parent: give the parent a height.
styleCSSProperties—Inline style on the root element.

Files

What the command adds to your project, and where.

  • components/effects/generative-tree/generative-tree.tsx

    The component.

  • components/effects/generative-tree/scene.tsx

    The component.

  • components/effects/generative-tree/showcase.tsx

    The component.

  • components/effects/generative-tree/poster.tsx

    The component.

  • components/effects/generative-tree/look.ts

    The component.

  • components/effects/generative-tree/tree.ts

    The component.

  • components/effects/generative-tree/cactus.ts

    The component.

  • components/effects/generative-tree/engine.ts

    The component.

  • components/effects/generative-tree/stage-styles.ts

    The component.

  • lib/effect-runtime.ts

    Shared by every shader effect: resizing, pausing, reduced motion, context loss and the no-WebGL fallback. Installed once.

Behaviour

  • The tree is grown by a seeded recursive model: every branch is a short curve whose direction drifts with a bend, an S-shaped wiggle and a pull toward the light, tapering from base to tip (with a root flare on the trunk). It continues as a leader and throws side shoots, some from its tip and some from partway along. The same seed and shape always give the same tree; changing density, colours or wind never moves a branch.
  • Growth runs from the root on one eased timeline: each shoot starts when its parent reaches it, extends with a soft growing point, and the wood thickens as the tree matures. Leaves, blossoms or dots unfold with a small overshoot once their branch has finished. ref.current.regrow(seed?) grows another tree while the old one fades; it returns the seed it used.
  • Once grown it sways: each branch turns a little about its base with its own phase, children inherit their parent's turn, so the tips move most, and a gust wave crosses the canopy. Petals or leaves fall, tumble and settle at the ground. With pointerWind on, moving the pointer through the canopy pushes the branches near it like a gust and springs back.
  • With form cactus it grows a saguaro or a prickly pear from the same seed and timeline. A saguaro is a ribbed column with a domed crown; its arms leave the trunk sideways, elbow and rise (depth sets how many, spread how far out, gnarl the lean and the waists), and arms on one side nest so they never cross. A prickly pear raises flat pads from the rims of earlier pads in a fan (depth sets the generations, spread the fan), some in front of their parent and some behind. Pleated ribs and pads are lit from the upper left; areoles carry hairline spines drawn at the device pixel ratio (density sets how many). Flowers open on the crowns and pad rims once growth is done, prickly pear sets fruit, and a cactus only rocks a little in the wind and drops the odd petal.
  • It is drawn on a Canvas2D at the device pixel ratio: the wood as anti-aliased filled outlines with a lit and a shaded flank, the foliage from sprites rendered at the size they are drawn, the background with a fine grain that dithers its gradients. The grown tree is fitted to its frame before it starts, so nothing shifts as it grows.
  • It pauses off screen and in a background tab and stops drawing when nothing moves. Under prefers-reduced-motion it shows the grown tree, still, with no sway and no petals. Without a 2D canvas it shows the same tree as an SVG.

See all effects