FlipbookFoundry

An animation library where every frame is a glyph.

93 actions, 2,614 hand-timed drawings, one font. A framer-motion-style API for Svelte, React and plain JavaScript. Free and open source.

Docs Builder GitHub

Write your own.

Type anything. Put an action in braces and it appears at text size:,,. Chain them with > like.


Figures are characters.

Bob left the house at nine. Sue waved from the window, and the dog ran after the postman. Halfway down the road Bob tripped, sat on the curb for a while, then got up and danced it off. Nobody minded.


It's just text.

Each drawing is a character in the Flipbook Stick font. A walk is twenty-four of them in a row. Playing an action means swapping one character for the next at the right moment — no canvas paths, no SVG, no skeleton at runtime. Select the line on the right and copy it: you're holding a walk cycle.

Each frame also carries how far the planted foot travelled, so figures cover ground without skating, plus anchors for hands, feet and head so they can carry things and meet each other's hands.

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

U+E000–U+E017 · 24 glyphs



U+E17E–U+E1A7 · 42 glyphs


Text that makes room.

Paragraphs are laid out by Cheng Lou's pretext. It measures once, then wraps with arithmetic, so a paragraph can re-flow around moving figures every frame.

This paragraph is set in a real typeface and laid out by pretext, which measures once and then wraps with arithmetic alone. That makes it cheap enough to re-wrap every single frame, so the text simply makes room for whoever is passing through. Nobody here is an image. Each figure is one character in a font, swapped for the next drawing twenty-four times a second, and moved along by exactly as far as its planted foot says it travelled. The words do not mind. They have seen worse. Resize the window and everything reflows without a single DOM measurement. This paragraph is set in a real typeface and laid out by pretext, which measures once and then wraps with arithmetic alone. That makes it cheap enough to re-wrap every single frame, so the text simply makes room for whoever is passing through. Nobody here is an image. Each figure is one character in a font, swapped for the next drawing twenty-four times a second, and moved along by exactly as far as its planted foot says it travelled. The words do not mind. They have seen worse. Resize the window and everything reflows without a single DOM measurement.


Letters with legs.

Any font, any letter. The letter becomes the body; the limbs come from the Flipbook Stick Limbs font, posed by the same 2,614 drawings.


Familiar if you've used framer-motion.

animate, initial, exit, variants, transition, whileHover, stagger, sequences with at. Swap a pose for an action name and you already know it. Figures route themselves between rest poses, so animate="sit-idle" from a run plays the stop and the sit-down first.

Svelte
<script>
  import { Stage, Figure, TextFlow } from 'flipbook-foundry/svelte';
</script>

<!-- Inline: one glyph in a line of text -->
<p>Hello <Figure animate="wave" whileHover="cheer" /></p>

<!-- A world: canvas, pretext, thousands of figures -->
<Stage style="height: 400px">
  <TextFlow text={copy} font="20px Georgia" width={720} lineHeight={30} />
  <Figure animate="run" x={0} y={300} size={64} />
  <Figure
    variants={{ rest: 'idle', happy: { action: 'cheer', transition: { repeat: 2 } } }}
    animate={mood}
    exit="bow"
  />
</Stage>
React
import { Stage, Figure, useAnimate, stagger } from 'flipbook-foundry/react';

function Parade({ people }) {
  const animate = useAnimate();
  const crowd = useRef([]);
  return (
    <Stage style={{ height: 300 }}>
      {people.map((p, i) => (
        <Figure key={p.id} ref={(c) => (crowd.current[i] = c)}
                animate="walk" x={i * 60} y={240} />
      ))}
      <button onClick={() => animate(crowd.current, 'jump', { delay: stagger(0.05) })}>
        Everybody jump
      </button>
    </Stage>
  );
}
Vanilla
import { createStage, animate, wander, greet } from 'flipbook-foundry';

const stage = createStage(canvas);
const bob = stage.add({ x: 0, y: 300, size: 80 });
const sue = stage.add({ x: 600, y: 300, size: 80, facing: -1 });

// Walk until x = 260, high-five on the same frame, then go about the day.
await animate([
  [bob, 'walk', { x: 260 }],
  [sue, 'walk', { x: 340, at: '<' }],
  [[bob, sue], 'high-five'],
]);
bob.use(wander(), greet());
sue.use(wander(), greet());

Every action.

93 actions · 2614 frames

locomotion 13

walk
run
jog
sprint
sneak
tiptoe
march
skip
backpedal
skid-stop
start-run
shuffle-step
sneak-off

aerial 7

hop
jump
leap
frontflip
backflip
fall
land

pratfall 6

trip
tumble
slip
stumble
faceplant
topple

transition 9

sit-down
stand-up
lie-down
get-up
crouch-down
rise
climb-up
hop-off
sit-on

idle 14

idle
look-around
tap-foot
yawn
sleep
fidget
sit-idle
perch-idle
hang-idle
type
sweat
lean-back
hang-swing
search

gesture 13

wave
point
beckon
shrug
clap
salute
bow
think
facepalm
peek
dust-off
peek-out
wave-hello

emote 14

cheer
laugh
cry
panic
angry
dance
flex
shiver
victory
exhausted
huddle
cover
wobble
rub-hands

interaction 17

push
pull
carry
lift
throw
catch
kick
punch
high-five
lean
knock
dig
scoop
toss-back
scoop-toss
drag
erase

Flipbook Foundry. Code under MIT, fonts under the SIL Open Font License. How it works · GitHub