Developing a bird murmuration
Why a flock?
A murmuration is a useful way to think about intelligence without a central brain. Each bird sees only a small part of the world: the birds close to it, the space directly ahead, and any immediate danger. From that partial view, it follows three simple rules:
- Separation: keep enough space to act independently.
- Alignment: pay attention to the direction of nearby birds.
- Cohesion: stay connected to the larger group.
The metaphor for agent swarms
The agents people are building today do not literally behave like birds, but the metaphor is useful. An agent has a limited view, a set of instructions, and the ability to act. Put many agents together and the important question changes. It is no longer only “How smart is each agent?” It becomes “What happens between them?”
Separation becomes clear ownership, so two agents do not overwrite the same work. Alignment becomes shared context and a common goal. Cohesion becomes communication: knowing when to ask for help, hand work off, or bring a result back to the group. The quality of the swarm lives in these relationships. A collection of capable agents without good local rules can still collapse into noise.
Step 1 — Start with something alive
I did not begin with a blank canvas and carefully place birds at x, y, and z coordinates. I started with Alex Scott's Canvas murmuration, got it running, and built a rough prototype around it. That gave me a living system immediately: birds were already moving, reacting to neighbors, and revealing what felt convincing or wrong.
This is often how I vibe code. I begin with a working piece whose behavior I can see, then learn the system by changing it. The prototype became a question I could interact with: what would make this flock feel less like particles and more like a collective intelligence?
Step 2 — Build the studio before perfecting the flock
Very early on, I built Murmuration Studio around the prototype. The behavior depended on dozens of numbers—bird count, speed, neighbor distance, rule strength, wind, fear, camera, depth—and changing those values directly in code made the result difficult for me to understand. I needed to see cause and effect while the flock was still moving.
The studio turned those hidden constants into live controls. I could move a slider, disturb the birds, and watch whether they scattered, clumped, flowed, or recovered. It was not polish added after the engine was finished. It was the tool that helped me discover what the engine needed to become. It can also upload artwork, save presets, and eventually export the finished flock for the web.
Step 3 — Learn the system through its three rules
The borrowed prototype gave me the basic boids model. For each bird, find its nearby neighbors. Push away from birds that are too close. Turn toward their average direction. Move gently toward the center of the local group. Add those forces to the bird's velocity, limit its speed, and move it forward. Then repeat.
Because the studio made every change visible, bugs became easier to reason about. One early version averaged the separation forces. In a symmetrical crowd, opposite pushes cancelled each other out and the flock collapsed into a dense blob. Summing those forces with a linear falloff gave every nearby bird a real vote, and the flock began holding its shape.
I tuned in this order: density, behavior, then appearance. First, use enough birds to read as a collective form. Next, balance separation, alignment, and cohesion until it moves with confidence and recovers from interruption. Only then tune the surface. A beautiful swarm with weak rules is still a weak swarm.
Step 4 — Give the flock somewhere to go
Local rules create coordination, but they do not create purpose. Without a destination, the birds can drift, orbit themselves, or settle into a static cluster. I added one to three invisible attractors moving along slow looping paths. Each bird follows the nearest one, while soft boundaries guide the flock back before it leaves the canvas. Wind and a small amount of turbulence keep the route from feeling predetermined.
This is another useful parallel with agent systems: autonomy is not the same as direction. Agents still need a goal, constraints, and a definition of useful progress. The goal should guide the swarm without scripting every move it makes.
Step 5 — Make the cursor an event, not an animation
The cursor acts like a moving danger field. A bird inside its radius gets a strong force away from it. A faster cursor creates a slightly larger disturbance, and a click produces a short outward pulse.
The important choice was not to trigger a separate escape animation. The cursor changes the conditions of the system; the birds decide how to respond using the same rules as before. Once the disturbance passes, they return to separation, alignment, and cohesion. I briefly strengthen cohesion after a scare, helping the flock recover in about two seconds. The recovery matters more than the disruption: an adaptive system earns trust by finding its form again.
Step 6 — Turn the words into invisible walls
The headline remains real HTML above the canvas, but the flock needs to experience it as physical geometry. The website measures the text and sends its rectangle to the engine. Birds near it are pushed outward and guided along its edge; any bird that crosses the boundary is moved back out.
Murmuration Studio can go further and measure each visible line separately. A single rectangle around an entire paragraph blocks empty space beside shorter lines. Line-sized obstacles let the birds use that space and flow closer to the actual shape of the words. The interface is not decoration placed over the simulation. It becomes part of the simulation's world.
Step 7 — Add a shallow third dimension
The first flock moved correctly but still felt like paper sliding across a table. A shallow third dimension did more for believability than another round of physics tuning. The camera has yaw, pitch, field of view, and distance controls. Birds nearer the camera appear larger; distant birds become smaller and lighter.
The depth stays deliberately shallow. A real murmuration behaves more like a moving sheet than a deep cloud. The renderer draws far birds first, rotates each sprite toward its projected movement, and selects a wing frame from the sprite atlas.
Step 8 — Make the birds look handmade
I drew birds in a few wing poses and let the studio pack them into a sprite atlas. Every bird begins at a different point in its flap cycle, so the flock does not move in mechanical unison.
The final treatment holds each drawing for a few frames, with a slight positional jitter, grain, and vignette. The underlying movement is still calculated at 60 steps per second, while the visible artwork changes at about 6 frames per second. Separating simulation time from visual time creates the handmade stop-motion quality without damaging the flock's ability to steer.
Step 9 — Export a small package for the website
The studio is an authoring environment, not the thing that should ship. “Export for Web” creates a small bundle containing preset.json, atlas.webp, manifest.json, an optional sky.webp, a static fallback, and a README. The separate embed script is produced with npm run build:embed.
Place the exported files and murmuration-embed.js in the site's public folder. The preset stores the behavior, the atlas stores the artwork, the manifest maps each bird pose inside that atlas, and the fallback respects visitors who prefer reduced motion. Separating the tool from its output keeps experimentation flexible and production stable.
Step 10 — Connect it to the hero
On this Next.js site, a small client component creates a full-size container and dynamically imports murmuration-embed.js from the public folder. It calls createMurmuration once with the container, the absolute URL of the exported bundle, and .hero-obstacle as the selector for text the birds should avoid.
The embed owns the canvas, physics, camera, pointer events, and render loop. React only mounts it and destroys it when the hero leaves the page. That narrow interface lets the simulation remain a self-contained system rather than being rewritten around the framework.
Step 11 — Make phones feel roomy too
A phone is not simply a smaller desktop canvas. Below 768 pixels, I reduce the bird count by half, scale down each sprite, and proportionally scale nine pixel-based physics values: speed, neighbor distances, fear radius, obstacle margin, and boundary margin among them. The multiplier is the screen width divided by 768.
A 200-pixel boundary is modest on a wide laptop and enormous on a 390-pixel phone. Shrinking only the artwork fixes how the birds look, not how the system behaves. Responsive simulations need responsive rules.
Step 12 — Test the ways it can fail
Do not only test the flock at rest. Pull the cursor hard through the headline and watch whether the birds route around the words, scatter cleanly, and recover. Resize the window. Try a phone. Leave the tab and return; the flock should pause while hidden and resume when visible. Turn on reduced motion and confirm the static fallback appears.
Failure is diagnostic. If every bird behaves incorrectly all the time, inspect the model. If the error appears only at a particular heading or frame, inspect the renderer. That distinction exposed a sprite-mirroring bug that made some birds fly backward and a shadow bug that made shadows rotate in midair.
Reflection
The murmuration is a metaphor. Human-built agents will need more than three rules, and their mistakes carry different consequences. But the flock makes one principle visible: collective intelligence is not created by multiplying isolated intelligence. It emerges from goals, boundaries, communication, recovery, and the quality of the rules between participants. The future of agents may be decided as much by how they coordinate as by how capable any one of them becomes.

