



Draw the states.
Each state is a pose of your mascot: resting, hungry, playing. Make them in Studio from one character.

MASCOT STATE MACHINE
Connect your mascot's poses on a graph. Masko generates every move, and your app decides where your mascot goes next.
Now: Rest
Click a state. Dumple takes the arrows to get there.
HOW A MASCOT STATE MACHINE WORKS
The demo above is a real Masko graph: Dumple's poses, the moves between them, and inputs that choose the way.




Each state is a pose of your mascot: resting, hungry, playing. Make them in Studio from one character.
Describe how your mascot gets from one pose to the next. Masko generates the move as a transparent video. Reverse moves are free.
setInput('play', true)Rest → Play
When something happens in your app, set an input. The mascot follows the arrows to the state that matches.
STATES CAN CHANGE WHO IT IS
In Masko Life, a companion evolves once in its life, shaped by what happened to it. Dumple got headphones and came back in a pink hoodie, still listening.
Both forms live in one graph: the first Dumple, the evolved one, and a move between them. Each form is a variant of the same mascot, so he still looks like himself. Try it above: feed him, play with him, then click Evolved.
See Dumple in Masko Life

LIKE DUOLINGO'S CHARACTERS
Duolingo's characters run on an animation state machine. When you answer, the app moves the character to a final state that reacts to your answer.
Build the same kind of reactions for your app. Each event sets an input, each reaction is a state, and Masko generates the moves between them from your mascot's images.
How Duolingo animates its characterslessonWaitingrightCelebratingwrongEncouragingstreakWorriedAn example for a lesson app.
FROM STUDIO TO YOUR CODE
import { useEffect, useRef } from 'react';
import {
MaskoAnimation,
type MaskoAnimationRef
} from './MaskoAnimation';
// The canvas export from Studio
import config from './mascot.json';
type Answer = 'right' | 'wrong' | null;
export function LessonMascot({ answer }: { answer: Answer }) {
const mascot = useRef<MaskoAnimationRef>(null);
useEffect(() => {
mascot.current?.setInput('right', answer === 'right');
mascot.current?.setInput('wrong', answer === 'wrong');
}, [answer]);
return <MaskoAnimation ref={mascot} config={config} />;
}THE LITTLE DETAILS
It is a map of the states your mascot can be in, such as resting, hungry or celebrating, and the animated moves between them. Your app sets inputs, and the mascot follows the arrows from one state to the next.
Open your mascot's canvas in Studio. Place its poses as states, draw arrows between them, and describe each move. Masko generates every move as a transparent video, and the export checks that every move it needs is ready.
Read the canvas guideEach move is a short video. A five-second Standard animation costs 10 credits, and Premium costs 30. Playing a move in reverse is free. A dry run shows every move and the total cost before you generate.
See credit costsRive and Lottie play vector animations that you design and animate yourself, and both offer state machines. Masko starts from images of your mascot and generates each move as a video, so you describe the move instead of animating it. Video files are larger than vector animations.
Yes. One graph can hold several forms of the same mascot, each made from an approved variant, with a move between them. Masko Life uses this when a companion evolves.
Meet Masko LifeExport the canvas from Studio to get the graph as JSON and the MaskoAnimation React player as source code. The API export returns the same JSON once the mascot is published. On the Mac, the Masko runtime plays your mascot in a floating window.
Read the export guideOnly the moves your graph can actually play. A reverse move can reuse the video of its forward move, and the export checks that every path the mascot can take has its media.

Poses, moves, and inputs, all from one character. Need a mascot first?