Want to Build an Infinite Canvas? Here's a Tutorial That Takes You All the Way Down the Stack
You've probably used Figma, tldraw, or Excalidraw and wondered how the zooming and panning actually work under the hood. The user-friendly answer is Canvas2D or SVG—but plenty of serious tools reach for something lower-level. This tutorial project walks through building an infinite canvas with GPU-accelerated rendering, and it's structured as a series of lessons you can run yourself.
What It Does
The repository is a hands-on tutorial for implementing an infinite canvas—the kind of non-linear, zoomable, directly manipulable workspace you see in design tools. The README defines "infinite" in three practical terms: high scalability so users can organize content freely, zooming that emulates moving closer for detail and further out for overview, and direct manipulation for moving, grouping, and restyling basic shapes.
The technical scope is broad. The project uses @antv/g-device-api as a hardware abstraction layer supporting WebGL1/2 and WebGPU, Becsy for an ECS-based architecture, and SDF (Signed Distance Field) rendering for circles, ellipses, and rectangles. On top of that it covers GPU-accelerated text and Bezier curve rendering, hand-drawn styles via rough.js, collaborative editing through CRDTs with Yjs, and tile-based rendering referencing mapbox and Figma. The author is upfront that the project is a work in progress and hopes to eventually rewrite the rendering layer in Rust—noting wgpu, rough-rs, and y-crdt as the pieces that would make that feasible.
Why It's Cool
-
It targets the real techniques, not the easy ones. The README explicitly contrasts Canvas2D/SVG approaches with what Figma (C++ compiled to WASM calling WebGL and WebGPU), Motiff, Modyfi (wgpu compiled to WASM calling WebGL2), and Vello/xilem are doing. If you want to understand how production design tools actually render, this is aimed at that layer.
-
The hardware abstraction layer choice is pragmatic. By building on @antv/g-device-api, the tutorial covers WebGL1, WebGL2, and WebGPU through one interface. You're not learning a technique that's locked to a single backend.
-
ECS for scalability. Using Becsy means the architecture is designed around high-performance, highly scalable systems rather than ad-hoc object hierarchies. That's a meaningful design decision for anyone who's watched a canvas app slow to a crawl.
-
SDF rendering is a smart pick for shapes. Rendering circles, ellipses, and rectangles via Signed Distance Fields gives you crisp edges at any zoom level—which matters a lot when your whole premise is zooming in and out.
-
Collaboration is in scope from the start. CRDTs and Yjs aren't bolted on as an afterthought; they're listed among the core goals, which is realistic for anything resembling a modern whiteboard.
-
A clear Rust roadmap. The author doesn't pretend the current state is final. The README lays out exactly what a Rust rewrite would reuse (shaders, hardware abstraction) and what already has Rust equivalents (rough-rs, y-crdt).
How to Try It
The project uses a pnpm workspace, so start by installing pnpm, then:
pnpm i
To run a specific lesson, enter its directory and start the Vite devserver:
cd packages/lesson_001
pnpm run dev
If you'd rather run the full site locally:
pnpm run build
cd packages/site
pnpm run dev
There's also an online app, a self-deployment guide, and a StackBlitz link if you want to poke at it without cloning anything. The README points to a package for using it in your own project, though that section was truncated in what I could see—check the repo for the details. Find everything at github.com/xiaoiver/infinite-canvas-tutorial.
Final Thoughts
This isn't a drop-in library—it's a course, and the author says plainly that completion is still relatively low. That honesty is refreshing, and it sets your expectations correctly. If you're a front-end developer curious about GPU-accelerated 2D rendering, or you've ever wanted to know what separates a tldraw from a Figma under the hood, the lesson-by-lesson format gives you a path in. Start with lesson one, run the devserver, and see how far the rabbit hole goes.