mahnoor·fatima

computational creative direction

BLOOM

L-system identity for a children's learning platform

PLANT Move to bend the plant and set how far it branches

SEED 0XF0EA GROWING

BLOOM

Volume VIII — A learning platform for children

Computational Creative Direction — L-Systems


The research question

What if a brand behaved according to one computational law — the tiny rewrite rule that turns a single seed into a whole tree?

BLOOM helps children learn, and its core belief is that learning is growth: small rules, repeatedly applied, producing something branching, personal, and alive. The perfect model already exists in botany. An L-system grows an entire plant from one symbol and a handful of substitution rules. So BLOOM’s identity grows the same way — every learner’s journey is a slightly different tree, generated from the same grammar, and no two are alike.

The computational principle

An L-system (Aristid Lindenmayer, 1968) is a formal grammar for growth. You start with an axiom — say F — and a rule — say F → F[+F]F[-F]F — and rewrite the string over and over. Interpreted as turtle-graphics commands (F = draw forward, +/- = turn, [/] = push/pop position), the string becomes a plant. The magic is that unbounded, natural-looking complexity comes from a rule you can write on a napkin. Structure is grown, not drawn — and small changes to the rule produce whole new species.

The behavior engine

One grammar generates the mark, the type ornaments, and every learner’s personal tree. Progress rewrites the string; the string draws the plant.

// L-system + turtle interpreter — the entire BLOOM engine
class Bloom {
  constructor(axiom, rules, angle = 25) {
    this.axiom = axiom; this.rules = rules; this.angle = angle;
  }

  // rewrite the string N times using the production rules
  grow(iterations) {
    let s = this.axiom;
    for (let i = 0; i < iterations; i++) {
      let next = "";
      for (const ch of s) next += this.rules[ch] ?? ch;
      s = next;
    }
    return s;
  }

  // interpret the string as a plant (turtle graphics)
  draw(ctx, s, { x, y, len = 6 }) {
    const stack = [];
    let a = -Math.PI / 2;                         // start pointing up
    const rad = this.angle * Math.PI / 180;
    for (const ch of s) {
      switch (ch) {
        case "F":                                 // draw a branch segment
          const nx = x + Math.cos(a) * len, ny = y + Math.sin(a) * len;
          ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(nx, ny); ctx.stroke();
          x = nx; y = ny; break;
        case "+": a += rad; break;                // turn right
        case "-": a -= rad; break;                // turn left
        case "[": stack.push({ x, y, a }); break; // remember a fork
        case "]": ({ x, y, a } = stack.pop()); break; // return to it
      }
    }
  }
}

// a learner's seed picks the rule; their progress picks the depth
const tree = new Bloom("X", {
  X: "F+[[X]-X]-F[-FX]+X",   // classic branching grammar
  F: "FF"
}, 22);

The axiom is the learner’s “seed,” the rule is their “species,” and iteration depth is how far they’ve grown — three variables that make every child’s tree unmistakably their own.

The visual language

Every BLOOM surface is branching structure — clean, generative botany rendered in a single confident line weight. The mark is a small recursive plant grown from BLOOM’s own axiom; because segment length and angle carry a little controlled randomness, every render is a fresh individual of the same species. The feel is friendly and precise at once — a scientific illustration that happens to be alive.

Living typography

Letters are grown, not set. Each glyph is an L-system whose branches trace the letterform, sprouting leaves and tendrils at the terminals. Early in a lesson the type is a bare sapling skeleton; as a child progresses, iterations increase and the letters leaf out and flower. Type literally matures with the learner — a headline on a mastered topic is in full bloom, one on a new topic is still budding.

Motion rules

  • Progress grows the tree. Completing a lesson advances the iteration count; the child watches their tree add a branch.
  • Growth animates in real time. New segments unfold with easing, the way a time-lapse plant reaches and forks.
  • Seasons. Long-term engagement cycles the palette through seasons — a returning learner finds their tree in bloom or in autumn.
  • Wind on hover. Pointing at a branch sways it gently; the whole plant has soft physics.

Interactive website

The homepage is a garden of grown identities — a field of trees, each a real learner’s L-system. A child’s dashboard is their tree: branches are subjects, leaves are lessons, flowers are mastery. Navigation means climbing your own plant. Because the grammar is deterministic given a seed, a learner’s tree is perfectly reproducible and shareable — the same seed always grows the same plant.

Physical applications

  • Report cards & certificates: each printed as the child’s actual tree at that moment — a keepsake no two of which are identical.
  • Classroom murals: a whole class’s trees grown into one forest, generated from their seeds.
  • Packaging & books: covers grown per copy from the product’s axiom.
  • Interactive exhibits: children plant a seed on a touch wall and watch the grammar grow it.

The brand system

Guidelines define growth stages rather than fixed art: named states (Seed, Sapling, Branching, Leafing, Bloom) each specifying iteration depth, angle variance, and legibility. “On-brand” means the plant is grown to a stage suited to context — an empty-state onboarding screen shows a Seed; a celebration screen shows full Bloom.

Color: soil brown, sprout green, bark, blossom pink, sun yellow, autumn amber. Branch depth maps to hue — trunks are bark and soil, terminals blossom and sun.

Open-source behavioral library

Shipped as bloom.js, an eight-verb API over the grammar:

const plant = new Bloom(canvas);

plant.Seed(axiom);        // set the starting symbol — a learner's origin
plant.Grow(iterations);   // rewrite deeper — the plant matures
plant.Branch(rule);       // change a production rule — a new species
plant.Prune(depth);       // roll back growth — reset to an earlier stage
plant.Leaf(terminals);    // decorate branch ends — lessons become leaves
plant.Flower(nodes);      // mark mastery with blossoms
plant.Sway(wind);         // apply soft physics to the structure
plant.Season(phase);      // cycle the palette through the year

Reflection

BLOOM was about making personalization feel earned rather than assigned. A lot of “personalized” branding just swaps a name into a template; here the identity is genuinely generated from the individual — same grammar, different seed — so every child’s tree is both unmistakably BLOOM and unmistakably theirs. Getting the angle and randomness right mattered enormously: too orderly and the trees feel manufactured, too wild and they stop reading as a family.

The takeaway: an L-system is the perfect metaphor for learning because it makes an invisible truth visible — that big, branching outcomes come from small rules applied patiently. BLOOM’s identity doesn’t illustrate growth; it grows, one lesson at a time, alongside the child.