Hi everyone ![]()
Over the last few weeks I’ve been vibe-coding an animation tool for Penpot: keyframe animation for boards, right in the workspace, in the spirit of Figma Motion. It lives on a branch of my fork behind a feature flag. I’d love for you to try it and tell me what works and what doesn’t.
What it does
Timeline
- Each board gets its own timeline in a dock at the bottom (View → Show animation timeline, or Shift+M for motion mode).
- You can keyframe position, size, rotation, scale, opacity, corner radii, fill and stroke color/opacity, stroke width, shadows, layer and background blur, and path trim (strokes that draw themselves).
- Easing presets, a cubic-bezier editor, back easings, springs (gentle, quick, bouncy, slow, custom) and hold.
- Playback modes: once, loop, ping-pong.
- Preset animations (fade, move, scale, rotate, slide, pop, zoom, spin, …) stay editable. Applied to several layers, they get a stagger.
- Markers, snapping, box selection, copy/paste of keyframes and arrow-key nudging.
Editing on the canvas
- In motion mode the canvas shows the board at the playhead, and you edit shapes where they appear. Each drag, resize or rotation becomes a keyframe.
- REC / auto-keyframe records every property you change at the playhead.
- Motion paths: the path of a moving layer shows on the canvas, with handles to curve it.
- The design tab shows the values at the playhead. Typing a value there sets the keyframe.
Components & collaboration
- Copies of an animated component play the animation of their main, also in other boards and when resized.
- Time-stamped comments: a comment placed in motion mode belongs to a moment of the animation, and a click on it moves the playhead there.
- Edits to different layers merge, so two people can animate the same board. Animations survive duplicating, copy/paste and moving layers between boards.
- View mode plays the animations, and animated boards get a play button on their title.
Export & import
- Export a board as MP4, WebM, GIF, animated AVIF, animated SVG, Lottie (vectors, gradients, strokes, trim, shadows, blur, clipping) or CSS @keyframes (respects
prefers-reduced-motion). Inspect shows the animation CSS of the selection. - Import Lottie (JSON or dotLottie, by drag & drop or File → Import Lottie…) as a board with its timeline. A warning lists what it could not bring over.
Plugins & MCP
- The plugin API, and through it the Penpot MCP server, can create timelines, keyframes, presets and markers, and set the export settings. So an AI agent can animate a board for you.
Performance
- Works with both renderers, but the WASM renderer is the target. It now draws the viewport in one pass during playback. A toggle plays in full quality (shadows and blur) instead.
Try it
Branch: GitHub - girafic/penpot at girafic-penpot-timeline-animation · GitHub
- Check out the branch and start the devenv (
./manage.sh run-devenv). - Add
enable-feature-animationto the flags (penpotFlagsinfrontend/resources/public/js/config.js). Turn on the WASM renderer for the video exports. (Optional also addenable-available-viewer-wasmto the flags) - Select a board and open View → Show animation timeline (or press Shift+M).
This is experimental. The data model can still change, so please don’t use it on files you care about.
Not there yet
- Shape morphing (animating path points). The Lottie import also skips track mattes, merge paths and text layers.
- Text-specific animation (per word or letter).
- Without the WASM renderer, the only export is Lottie, and only when all layers are vectors.
