Primitive Animator

An IDE for motion graphics

Hi! This is the landing page for my passion project. I'm still working on it (sorry, no interactive demo yet), but I'm excited to share it with you.

I love experimenting with different paradigms, so this static webapp uses a unique tech stack: React, Haskell (WebAssembly) and Rust (WebAssembly). More details below.

Primitive Animator interface showing visual expression editor with project files, expression tree, and canvas preview

Visual Expression Editor

See your animations update in real time as you edit.

Keyboard-Driven Workflow

All UI elements are accessible via keyboard navigation.

Flexible Layout

Maximize the editor or canvas, or use a multi-pane layout.

Features

Rich Built-In Functions

Access math operations, drawing primitives (circles, rectangles), noise functions (Simplex 1D/2D), easing curves, time-based functions, and more. Compose them to create complex animations.

Function and Parameter System

Organize code into reusable functions with parameters. Move functions between files, convert expressions to functions, and build a library of reusable components.

Multi-Project Workspace

Manage multiple projects in one workspace. Organize code into project files and shared library files. Switch between projects quickly.

Keyboard-Driven Workflow

Navigate and edit with keyboard shortcuts. Use the command palette (Cmd+K) for quick actions: create functions, navigate, convert expressions, and more.

Powerful Drawing Primitives

Draw shapes with position, size, color (HSV), and opacity. Use system functions like DrawCircle and DrawRectangle to build visual compositions.

Time-Based Animation

Access the current time and use it to drive animations. Combine with easing functions and math operations to create smooth motion.

Expression Manipulation

Move expressions in the tree, cut and paste, convert expressions to functions or parameters, and refactor code with keyboard shortcuts.

Project Persistence

Projects save automatically. Export and import project data as JSON for version control and sharing.

Architecture Overview

Technology Stack

  • Domain logic: Haskell compiled to WebAssembly
  • Expression evaluation: Rust compiled to WebAssembly for high-performance expression evaluation
  • Templates and styling: React + TypeScript + Tailwind CSS
  • Type Safety: End-to-end type safety via auto-generated TypeScript definitions from Haskell types
  • Communication: WASM FFI bridge between Haskell/JavaScript and Rust/JavaScript with typed message passing

Reactive Architecture

  • Selector-based data flow: React components subscribe to Haskell selectors via useDh hooks
  • Action system: UI triggers actions that execute in Haskell monadic context (AppOp)