A Figma-style 2D vector editor built with Zig WASM core and WebGPU rendering, running entirely in a Web Worker for smooth 60fps performance.
- Rectangle Tool - Create rectangles with optional corner radius
- Ellipse Tool - Create circles and ellipses
- Pen Tool - Draw arbitrary paths with bezier curve support (click+drag for smooth curves)
- Select Tool - Select, move, resize, and rotate shapes
- Fill & Stroke - Per-shape fill and stroke colors
- Stroke Options - Configurable width, caps (butt/round/square), joins (miter/round/bevel)
- Dashed Strokes - Customizable dash length and gap
- Corner Radius - Rounded corners for rectangles
- Nested Groups - Arbitrary hierarchy depth with Cmd/Ctrl+G to group, Cmd/Ctrl+U to ungroup
- Layer Panel - Visual hierarchy with visibility toggles
- Undo/Redo - Full history support (Cmd/Ctrl+Z / Cmd/Ctrl+Y)
- GPU Compute Shaders - Geometry generation on GPU (curve flattening, stroke expansion)
- Adaptive Bezier Subdivision - 4-128 segments based on curvature and zoom
- Tile-Based Rendering - Only re-render dirty regions for efficiency
- 4x MSAA Antialiasing - Smooth edges with fragment shader AA
- Object Transforms - Full rotation and scale support with hierarchy propagation
# Install dependencies
bun install
# Development build (fast iteration)
bun run build:wasm:debug && bun run dev
# Production build
bun run prodwiggle/
├── src/
│ ├── main.zig # Core: scene graph, input, geometry export
│ └── app/
│ ├── App.tsx # React UI: tool panel, layers, properties
│ └── styles.css # UI styling
├── www/
│ ├── worker.js # WebGPU init, WGSL shaders, render loop
│ ├── index.html # Entry point
│ └── index.js # Canvas setup, worker communication
├── build.zig # Zig build configuration
├── ARCHITECTURE.md # Detailed technical documentation
└── package.json
┌─────────────────┐ postMessage ┌──────────────────────────────┐
│ React UI │ ←───────────────→ │ Web Worker │
│ - Tool panel │ │ - WebGPU pipelines │
│ - Layers panel │ │ - WGSL compute shaders │
│ - Properties │ │ - WASM ↔ GPU buffer sync │
└─────────────────┘ └──────────────────────────────┘
↓
┌──────────────────────────────┐
│ Zig WASM │
│ - Scene graph (shapes[]) │
│ - Paths with bezier curves │
│ - Hit testing, selection │
│ - Undo/redo history │
└──────────────────────────────┘
- Zig exports shape/path descriptors to linear memory
- Worker.js reads via exported pointers (
getShapeDescriptorPtr(), etc.) - Uploads to GPU storage buffers
- Compute shaders generate vertices (curve flattening, stroke expansion)
- Render pass draws from vertex buffer with tile-based dirty tracking
| Key | Action |
|---|---|
| W | Toggle wireframe debug mode |
| Delete/Backspace | Delete selected shape |
| Escape | Cancel pen tool / deselect |
| Enter | Finish pen path |
| Cmd/Ctrl+Z | Undo |
| Cmd/Ctrl+Y | Redo |
| Cmd/Ctrl+G | Group selected |
| Cmd/Ctrl+U | Ungroup selected |
| Command | Description |
|---|---|
bun run build:wasm:debug |
Fast Zig build for iteration |
bun run build:wasm:release |
Optimized Zig build |
bun run dev |
Vite watch mode for UI |
bun run build |
Full production build |
bun run prod |
Release WASM + minified UI |
See ARCHITECTURE.md for in-depth documentation on:
- Adaptive bezier subdivision algorithm
- GPU compute pipeline stages
- Tile-based dirty rendering
- Miter join calculations
- Group hierarchy and transforms
MIT