How it works

Flipbook Foundry is 93 actions of stick-figure animation, 2,614 drawings in all, shipped as a font. In the browser a figure is one character. Playing an action means replacing that character with the next one, 24 times a second. This is how the drawings are made, how they move without sliding, and where the idea runs out.

A drawing is a character

The baker gives each action a contiguous run of Private Use Area codepoints, starting at U+E000. Frame i of an action is String.fromCodePoint(start + i). Here is the whole walk cycle, 24 characters set as ordinary text. Select it and copy it if you like.



U+E000–U+E017 · 24 glyphs

Every drawing has the same advance width, 560 units on a 1000-unit em, with the pelvis on the centre line. That is most of the trick. Each frame is exactly as wide as the last, so swapping one for the next never changes the width of the line it sits in, and the text around a figure never moves. There is no SVG, no canvas path and no skeleton at runtime. There is a font and a lookup table.

Bones and angles

The drawings come from a skeleton with fixed bone lengths: thigh, shin, torso, neck, upper arm, forearm and a head. A pose is a handful of angles on those bones, two per limb, plus lean, spine curve, head tilt and a whole-body rotation for tumbles. An action is a list of sparse keys on a frame timeline, and each key states only what changes.

Interpolating angles instead of joint positions keeps the figures from going rubbery. A hand moving between two keys sweeps an arc at the end of a rigid arm rather than cutting a straight line through the chest. Between keys the timeline runs a time-aware Catmull-Rom spline, so speed carries through a key instead of stopping at it. A key can ask for an explicit ease when it should stop: a hold, a hit, the snap into a take.

Feet that stay put

The classic failure of a 2D walk is skating. The body moves at one speed, the feet at another, and the figure looks like it is on ice. The baker fixes this per frame, in two passes.

First it runs forward kinematics, finds the lowest ink, and moves the figure so that point sits on the ground. Then, for each pair of neighbouring frames, it looks at the contacts near the floor in both. The foot sliding backward under the body is the one bearing weight; a swing foot still travelling with the body is only landing. The baker locks the weight-bearing foot, and the distance it slid becomes that frame's root motion, dx. Frames in the air get the average. These are the walk's, in font units:

22.9 16.3 37.1 33.9 19.9 15.7 17.4 21 23.6 27 33.6 34.4 22.9 16.3 37.1 33.9 19.9 15.7 17.4 21 23.6 27 33.6 34.4

The numbers ship in the manifest. A travelling figure adds dx, scaled to its size and flipped by its facing, on every frame it steps. One walk cycle covers 606 units, about 1.1 figure widths, which is exactly as far as its planted foot says. scripts/skate.ts prints the drift that is left, frame by frame.

Everything is in the outline

Squash and stretch are fields on the pose. Speed lines are traced from where fast joints were over the two previous frames. Impact puffs are pinned in world space for three frames, so they stay on the ground while the body moves on. All of it is drawn into the glyph, and the runtime has nothing extra to render.

Limbs are stroked into closed shapes that overlap at every joint. Before writing a glyph the baker unions them into a single outline, so no rasteriser ever sees overlapping contours and there is no seam where an arm crosses the chest.

The baker also records anchors for every frame: head, top of head, hands, feet, pelvis, shoulder, spine angle and forearm angles. Text layout doesn't need them, so they live in a separate file a canvas Stage loads on demand. They are what let a figure hold a shovel, take someone's hand, or swap its body for a letter.

Fonts in pieces

The same drawings are baked four ways: Flipbook Stick Regular and Bold, and Flipbook Stick Limbs Regular and Bold, which leave out the head and torso. All four use the same codepoints. Props such as a shovel or a sack are a fifth font, Flipbook Stick Things, with 8 of them.

Actions are grouped by category, and each group is a contiguous range of codepoints. So each group becomes its own woff2 file, 32 per weight, registered as a FontFace with a matching unicode-range. The browser fetches a file only when the page uses a codepoint inside it. A page with one waving figure downloads one small file.

One loop

At runtime a Character holds an action, a frame, a position and a facing. It never draws. Every Character on the page steps on one shared requestAnimationFrame, split into read, update and render phases like framer-motion's frameloop. Each figure advances at its action's frame rate and caps catch-up, so a tab returning from the background doesn't fast-forward a crowd.

Every action starts and ends on one of 6 rest poses: stand, lie, crouch, sit, hang and perch. Transitions such as sit-down and get-up are edges between them, and a breadth-first search finds the shortest path. Ask a figure lying on the floor to sit and it plays get-up then sit-down first. Any action can follow any other without a pop, and the API stays declarative: you say what a figure should be doing, not how it gets there.

Text that makes room

Text is laid out with Cheng Lou's pretext. pretext measures a string once; after that, line breaking is arithmetic with no DOM reads. A Page splits a paragraph on {action} tokens and hands pretext a list of inline items: words in your font, figures as single characters in the Flipbook Stick font, each padded by however far that action's ink reaches past its advance. Layout runs when the text or width changes. Animation only repaints.

Sue waved from the door. Bob walked over, sat down on the step, and shrugged. The sentence never moved.

On a canvas Stage, TextFlow goes further and re-wraps the paragraph every frame. For each line it takes the boxes of the figures crossing it, finds the free gaps between them, and fills each gap with pretext's layoutNextLineRange. The words that come out double as ledges a figure can stand on.

Letters with legs use the Limbs font. The Stage draws a letter from any typeface between the pelvis and the top of the head, tilted to the spine anchor, then draws the limbs over it.

The Stage itself is plain. Each figure is one setTransform and one fillText of one glyph, and facing left is a negative x scale. Props, letters and paragraphs are fillText too, so a crowd is just more calls.

What it's for

Small, characterful motion in places that are already text: a figure in a sentence, an empty state, a loading line, docs that want an illustration but not a sprite sheet. The API follows framer-motion, with animate, exit, variants and stagger, for Svelte, React and plain JavaScript.

Limits

They are stick figures, in one style. Proportions are fixed when the fonts are baked, so changing them or adding an action means editing an action file and baking again. The builder exports actions as TypeScript for that.

The characters live in the Private Use Area. Copied out of the page, they paste as empty boxes anywhere the Flipbook Stick font isn't loaded. Inline figures are hidden from assistive tech. Page and TextFlow draw to a canvas, so each mirrors its words into a visually hidden paragraph for screen readers, with the figures left out.

Motion is stepped. Actions are drawn at fixed frame rates, most at 24 fps, and each drawing is held until the next; nothing is tweened between them. That is the look, and it is also the ceiling.

Code is MIT and the fonts are under the SIL Open Font License. Read the docs or the source on GitHub.