Getting Started
Open the editor to try everything on this page live.
Mental Model
The engine executes your entry file every animation frame (~60 FPS):
- Injects
time,dt,state,w,h - Runs your code
- Reads the object you
return - Draws those primitives on a 2D canvas
Input → Code → Output Primitives → Canvas
You never touch the canvas context. Describe what to draw; the engine renders it.
App Tour
| Area | Purpose |
|---|---|
| File explorer | Multi-file projects; main.js is the entry (badge). New files are modules. |
| Monaco editor | Edit code. Recompiles ~400ms after you stop typing — clears state and time. |
| Canvas | Live render with grid and centered axes for reference. |
| Pause / Play | Freeze or resume the frame loop. |
| Restart | Clear state and time; keep your current code. |
| Reset | Restore the starter main.js project. |
| Projects | Save and load through Supabase-backed accounts. |
| Docs | This documentation (served at /docs). |
30-Second Quick Start
Open the editor, then paste this into main.js:
// 1. State setup — run once
if (!state.init) {
state.x = w * 0.3;
state.y = h * 0.3;
state.vx = 120;
state.vy = 0;
state.init = true;
}
// 2. Physics — Euler integration
state.vy += 200 * dt; // gravity (px/s²)
state.x += state.vx * dt;
state.y += state.vy * dt;
// Floor bounce
if (state.y > h - 20) {
state.y = h - 20;
state.vy *= -0.8;
}
// Wall bounce
if (state.x > w - 20 || state.x < 20) {
state.vx *= -1;
}
// 3. Render
return {
particles: [
{ x: state.x, y: state.y, r: 14, color: '#8B5CF6' },
],
text: {
time: time.toFixed(1) + 's',
velocity: Math.sqrt(state.vx ** 2 + state.vy ** 2).toFixed(0),
},
};You should see a purple ball bouncing under gravity with a live velocity readout.
What Just Happened
| Step | What | Why |
|---|---|---|
if (!state.init) | Guard clause | Setup runs once; values persist on state |
state.vy += 200 * dt | Gravity | Acceleration in px/s², scaled by frame time |
state.y > h - 20 | Floor collision | Stop 20px above the bottom |
vy *= -0.8 | Bounce | Coefficient of restitution (0 = stop, 1 = elastic) |
return { particles } | Output | Engine draws whatever you return |
Injected Globals
| Variable | Type | Description |
|---|---|---|
time | number | Seconds since simulation start (cumulative) |
dt | number | Seconds since last frame (max 0.05) |
state | object | Persistent storage across frames |
w | number | Canvas width in CSS pixels |
h | number | Canvas height in CSS pixels |
TIP
dt is clamped to 50ms. After a long tab blur, the sim advances at most one capped step — it won't jump by seconds.
WARNING
Editing code recompiles after ~400ms and resets state and time, same as Restart. Only Pause freezes without clearing.
Output Primitives
return {
particles: [{ x, y, r, color, label }],
lines: [{ x1, y1, x2, y2, color, dashed, width }],
vectors: [{ x, y, ox, oy, color, label }],
circles: [{ cx, cy, r, color, fill }],
arcs: [{ cx, cy, r, startAngle, endAngle, color, width }],
bars: [{ x, y, w, h, color, label }],
text: { label: value },
}All properties are optional. Return only what you need.
See Output Schema for defaults and draw order.
State Persistence
Anything on state survives until Restart, Reset, or a code recompile:
if (!state.init) {
state.particles = [];
state.count = 0;
state.init = true;
}
state.count++;WARNING
let x = 100 resets every frame. Use state.x for values that must accumulate.
Click Interaction
Clicks write canvas coordinates onto state. Always consume them after handling:
if (state.clickX !== undefined) {
state.particles.push({
x: state.clickX,
y: state.clickY,
vx: (Math.random() - 0.5) * 100,
vy: -100,
});
state.clickX = undefined;
state.clickY = undefined;
}Coordinates
Origin is the top-left; Y increases downward. The grid axes are visual guides centered at (w/2, h/2) — sketch coordinates are still raw canvas pixels. Prefer:
const cx = w / 2, cy = h / 2;Details: Coordinate System.
Next Steps
- Open the editor — run examples live
- Cheatsheet — one-page globals + primitives + snippets
- Numerical Integration — Euler, forces, stability
- Cookbook: Projectile — gravity, trail, bounce
- Cookbook: Trig — unit circle and Y-up flip
- Saving Projects — Supabase save/load