Manic API reference
The complete index of every Manic builtin — 490 builtins across 19 kits. Each entry shows its signature, whether it sets things up or animates them, and what it does. Every name listed here is one the editor knows too, so autocomplete and highlighting always match this page.
Reading a signature
new idis the name created by a constructor.id or tagtargets an existing entity, generated part, or group.- Parameters inside brackets are optional.
…means the builtin is catalogued here, but its detailed parameters are covered in the topic chapter for its kit.- This is the exhaustive name index; the topic chapters remain the best place to learn composition, constraints, and examples.
Standard shapes, styling, and motion
| API | Kind | What it does |
|---|---|---|
circle(id: new id, center: (x, y), r: number) | constructor / setup | a circle |
rect(id: new id, center: (x, y), w: number, h: number) | constructor / setup | a rectangle |
image(id: new id, center: (x, y), path: string, [w: number], [h: number]) | constructor / setup | a raster image (PNG/JPG) from a bundled asset: URI or file path, centred at a point (w×h px) |
svg(id: new id, center: (x, y), path: string, [size: number]) | constructor / setup | import VECTOR artwork from an asset: URI or file path as native path entities (each subpath a traceable Polyline/Polygon), fitted to size px wide and centred; pieces are tagged {id} so draw/show/fade/hue/gradient/move broadcast |
equation(id: new id, center: (x, y), latex: string, [size: number]) | constructor / setup | typeset a LaTeX math string centred at a point; standard \textcolor{cyan}{…} gives individual terms semantic Manic colours that follow the template. Put LaTeX in BACKTICKS; animate with show/fade/move/scale, and untraced+draw gives a left-to-right WRITE-ON wipe |
mathparts(…) | constructor / setup | mathparts(id, (x,y), part0, part1, …, [size]) — one equation split into PARTS, auto-laid-out left-to-right + baseline-aligned, centred at (x,y). Each part is its own entity {id}.0/{id}.1/… (all tagged {id}) so you can framebox/color/draw a single term. Manim’s indexable MathTex(…). Put each part in BACKTICKS; a trailing number is the size |
framebox(id: new id, target: id or tag, [buff: number], [color: colour]) | constructor / setup | an outlined rectangle that SURROUNDS a target entity’s bounding box, padded by buff px (default 8) — a highlight box. Move it to another target with surround(box, target). Default colour gold |
surround(box: id or tag, target: id or tag, [dur: number], [ease: easing]) | animation verb | move a highlight box (framebox/rect) to surround a NEW target, gliding + resizing to fit it (Manim ReplacementTransform on surrounding rectangles) |
line(id: new id, from: (x, y), to: (x, y)) | constructor / setup | a line segment; from/to take a (x,y) point OR AN ENTITY NAME (see arrow) |
link(id: new id, from: id or tag, to: id or tag, [bend: number]) | constructor / setup | a straight or bent edge that follows two moving entities |
arrow(id: new id, from: (x, y), to: (x, y), [bend: number]) | constructor / setup | an arrow (optional bend bows it into a curved arc — signed, so the sign picks the side). from/to are a (x,y) point OR AN ENTITY NAME, so an arrow can be aimed at something whose position was computed rather than typed: an atom or bond in a structure (arrow(a, nuc.a0, sub.a1, 62) is a mechanism curly arrow), a graph node, a matrix cell. A path-shaped entity (a bond, a plotted curve) resolves to the centre of its bounds, which is the point a reader means |
polygon(…) | constructor / setup | a filled polygon: polygon(id, (x1,y1), (x2,y2), (x3,y3), …, [color]) |
dot(id: new id, at: (x, y), [r: number]) | constructor / setup | a small filled dot |
cloud(…) | constructor / setup | a point field: N points placed by closed-form formulas of index i and time t |
shader(…) | constructor / setup | a per-pixel colour field: r/g/b (or c) as closed-form formulas of pixel coords u/v and time t |
raymarch(…) | constructor / setup | a 3D SDF scene, ray-marched per pixel: let d = signed distance to the scene at (x,y,z,t) |
glsl(id: new id, source: string) | constructor / setup | run a raw GLSL fragment shader (Shadertoy mainImage, iTime/iResolution) at full resolution |
particles(id: new id, container: id or tag, count: number, [radius: number], [seed: number], [layout: string]) | constructor / setup | deterministic small dots inside a circle or rectangle; optional random/grid/ring layout |
text(id: new id, at: (x, y), text: string, [size: number]) | constructor / setup | a text label; optional trailing point size (default 28) |
label(…) | constructor / setup | a label pinned to an entity |
caption(id: new id, words: string, at: (x, y), [size: number], [color: colour]) | constructor / setup | a row of caption words (karaoke/pop) |
support(id: new id, center: (x, y), [len: number], [dir: string]) | constructor / setup | a hatched fixed support (wall/ceiling/floor) for mechanics diagrams; dir = open side |
counter(id: new id, at: (x, y), value: number, [decimals: number], [prefix: string], [suffix: string]) | constructor / setup | a live numeric readout |
parameter(id: new id, at: (x, y), initial: number, min: number, max: number, [label: string], [decimals: number]) | constructor / setup | a visible bounded value for a smooth multi-visual journey |
bind(parameter: id or tag, target: id or tag, property: new id, formula_or_from: string, [to: number], [formula_component_3: string]) | constructor / setup | connect a parameter to a property, plot/field formula, or stable generated 3-D family |
cursor(id: id or tag) | constructor / setup | give a text entity a typewriter cursor |
sticky(id: id or tag) | constructor / setup | pin an entity to the screen so it stays fixed through cam/zoom (HUD overlay) |
morph(…) | constructor / setup | sampled-point shape morph a->b |
invertpath(id: new id, source: id or tag, center: id or tag, radius: number, [samples: number]) | constructor / setup | live whole-outline inversion about a named center |
reflectpath(id: new id, source: id or tag, mirror: id or tag, [samples: number]) | constructor / setup | live whole-outline reflection across a named line |
copy(new: new id, src: id or tag) | constructor / setup | duplicate an entity |
color(id: id or tag, color: colour) | constructor / setup | set fill/stroke colour |
outline(id: id or tag, color: colour) | constructor / setup | set outline colour |
size(id: id or tag, size: number) | constructor / setup | set text size |
wrap(id: id or tag, width: number) | constructor / setup | wrap a text/caption/$…$ label to a width (px), breaking at word boundaries; inline math stays atomic. Text that would leave the canvas wraps to the room it has WITHOUT this - nothing is silently clipped - so wrap is for choosing a narrower column than the frame allows |
align(id: id or tag, edge: id or tag) | constructor / setup | which edge of a text block is pinned to its point: left, center (the default) or right. Applies to a wrapped block, to hand-broken \n lines, and to an equation image; a right-aligned label keeps its right edge as the text changes length, which is what a column of numbers wants |
leading(id: id or tag, factor: number) | constructor / setup | line height as a multiple of the font size (default 1.4). Tighten it for a stacked column or a title that should read as one block, open it out for a paragraph |
vertical(id: id or tag, [leading: number]) | constructor / setup | stack a text label’s glyphs into a column, each one UPRIGHT - the poster/spine reading. Not the same as rot(id, 90), which turns the whole line on its side and takes the letters with it. Optional line height (default 1.0, tighter than prose because single capitals otherwise read as a list). Spaces become gaps in the column, combining marks stay on their letter, and applying it twice changes nothing. Inline math is refused - a formula cannot be stacked letter by letter |
stroke(id: id or tag, width: number) | constructor / setup | set stroke width |
dashed(id: id or tag, [dash: number], [gap: number]) | constructor / setup | use a repeating dash/gap stroke on a path-like entity |
gradient(…) | constructor / setup | multi-stop gradient on the primary paint: gradient(id, c1, c2, …, [mode]) — along a path stroke by arc length, a linear (angle°) / radial fill, or a computed “speed”/“curvature” quantity on strokes |
glow(id: id or tag, amount: number) | constructor / setup | set neon glow amount |
plate(id: id or tag, [opacity: number]) | constructor / setup | give TEXT a legibility backing: a theme-aware (template background) chip sized to the glyphs so a caption/title stays readable over a busy shader or field — plate(id, [opacity]); default opacity 0.55 |
opacity(id: id or tag, value: number, [layer: id or tag]) | constructor / setup | set opacity 0..1. Optional trailing fill / stroke word sets just THAT layer’s opacity, independent of the other — a translucent interior under a crisp outline (a shape carries its own fill and stroke opacity, like set_fill/set_stroke). Omit the word → whole entity |
hue(id: id or tag, degrees: number, [s: number], [l: number]) | constructor / setup | drive colour by an HSL hue |
rot(id: id or tag, degrees: number) | constructor / setup | set rotation (degrees) |
z(id: id or tag, z: number) | constructor / setup | set draw order |
clip(id: id or tag, region: id or tag) | constructor / setup | clip an entity (or tagged group) to another entity’s rectangular bounds — reveal-through-a-window / crop-to-panel / region-wipe; the scissor follows the region each frame |
mask(id: id or tag, region: id or tag) | constructor / setup | clip an entity (or tagged group) to another entity’s ARBITRARY shape (circle, polygon, star, an imported svg outline) — reveal-through-any-shape / lens / porthole / spotlight; masks any content and follows the region each frame |
tag(id: id or tag, tag: new id) | constructor / setup | add a group tag |
bold(id: id or tag) | constructor / setup | use the bold mono font |
display(id: id or tag) | constructor / setup | mark visible |
hidden(id: id or tag, [from: id or tag]) | constructor / setup | start hidden (opacity 0). Optional from arms a GROW-IN reveal for show (scale 0 at the anchor -> home): center | up/down/left/right (a bbox edge) | tail (an arrow’s start) | a point (x,y). The reveal STYLE lives on hidden, exactly like untraced arms draw |
filled(id: id or tag) | constructor / setup | SOLID posture: fill on, outline off — the default for circle/rect/polygon. Reverts a hollow shape |
outlined(id: id or tag) | constructor / setup | HOLLOW posture: outline on, fill off — a ring/frame you can draw-on (untraced+draw) and give a translucent fill via opacity(id, a, fill). The stroke-first look |
untraced(id: id or tag) | constructor / setup | start undrawn, ready for draw-on |
union(…) | constructor / setup | boolean union of two shapes |
intersect(…) | constructor / setup | boolean intersection |
intersection(…) | constructor / setup | boolean intersection |
difference(…) | constructor / setup | boolean difference a-b |
subtract(…) | constructor / setup | boolean difference a-b |
exclusion(…) | constructor / setup | boolean symmetric difference |
xor(…) | constructor / setup | boolean symmetric difference |
brace(id: new id, p1: (x, y), p2: (x, y), [depth: number], [direction: id or tag]) | constructor / setup | a curly brace between two points; optional depth (amplitude) and direction (“up”/“down”/“left”/“right”) to set which way it bulges — either may be given alone, e.g. brace(b,(x1,y1),(x2,y2),“down”) or brace(b,p1,p2,30,“down”) |
bracelabel(…) | constructor / setup | a brace with a label |
bracetext(…) | constructor / setup | a brace’s text label |
draw(id: id or tag, [dur: number], [ease: easing]) | animation verb | trace a stroke on |
flow(path: id or tag, [dur: number], [direction: id or tag], [mode: id or tag]) | animation verb | send a directional luminous pulse or finite continuous stream over a path |
erase(id: id or tag, [dur: number], [ease: easing]) | animation verb | reverse of draw |
show(id: id or tag, [dur: number], [ease: easing]) | animation verb | reveal an entity: a fade-in, OR a GROW-IN if it was armed with hidden(id, from) (scale 0 at the anchor -> home). One reveal verb; the style is picked by how you hid it |
fade(id: id or tag, [dur: number]) | animation verb | fade out |
flash(id: id or tag, [color: colour], [dur: number], [ease: easing]) | animation verb | flash a colour, then restore |
recolor(id: id or tag, color: colour, [dur: number]) | animation verb | permanently change colour |
pulse(id: id or tag, [dur: number]) | animation verb | grow-and-settle attention pulse |
oscillate(id: id or tag, prop: new id, period: number, amp: number, [phase: number], [dur: number]) | animation verb | continuously oscillate a property sinusoidally — prop is size|opacity|x|y|hue; period seconds/cycle; amp is a scale delta (size), opacity delta, pixels (x/y) or degrees (hue); phase in cycles (0–1) — give looped siblings a per-index phase for a travelling wave; runs for dur (default 6s). Works on a tag. |
breathe(id: id or tag, period: number, amp: number, [phase: number], [dur: number]) | animation verb | size oscillation (alias for oscillate with prop=size): the entity grows and shrinks; give looped siblings a per-index phase for a breathing wave |
shake(id: id or tag, [dur: number]) | animation verb | horizontal shake (error gesture) |
spin(id: id or tag, [degrees: number], [dur: number]) | animation verb | spin about the centre |
move(id: id or tag, to: (x, y), [dur: number], [ease: easing]) | animation verb | move to an absolute point |
wander(particles: id or tag, [dur: number]) | animation verb | gently move a particle group inside its source container |
burst(particles: id or tag, [dur: number]) | animation verb | explode a particle group outward from its container centre, decelerating and fading — the impulse/impact/confetti/ignition beat |
arrange(particles: id or tag, container: id or tag, [layout: string], [dur: number], [ease: easing]) | state-changing verb | move persistent particles into a deterministic random, grid, or ring layout; random uses stable organic curved routes |
travel(entity: id or tag, path: id or tag, [dur: number], [ease: easing]) | state-changing verb | move one persistent entity once along an existing path and stop at its endpoint |
attach(child: id or tag, target: id or tag, [offset: (x, y)]) | state-changing verb | keep an entity pinned to another entity plus an optional offset; use target none to release |
become(source: id or tag, target: id or tag, [dur: number], [ease: easing]) | state-changing verb | transform one entity into a declared visual blueprint while retaining the source id |
turn(id_or_tag: id or tag, pivot: (x, y), degrees: number, [dur: number], [ease: easing]) | state-changing verb | rotate one entity or tagged arrangement rigidly around a shared pivot |
disintegrate(entity: id or tag, [dur: number]) | state-changing verb | dissolve an entity’s actual silhouette into deterministic seekable particles |
shift(id: id or tag, by: (x, y), [dur: number], [ease: easing]) | animation verb | move by a delta |
slidex(id: id or tag, x: number, [dur: number], [ease: easing]) | animation verb | slide to an absolute x, keeping y where it is |
slidey(id: id or tag, y: number, [dur: number], [ease: easing]) | animation verb | slide to an absolute y, keeping x where it is |
dock(group: id or tag, member: id or tag, target: (x, y), [dur: number], [ease: easing]) | animation verb | shift a group rigidly so one member lands on a target point or entity |
groupscale(group: id or tag, factor: number, [dur: number], [ease: easing]) | animation verb | scale a group about its collective centre (not each part about its own) |
sliders(id: new id, n: number, center: (x, y), [width: number], [height: number], [color: colour]) | constructor / setup | a rack of N vertical coordinate dials, each a value in [-1,1] (a point in N-D space as N dials); setsliders drives them and shows the running sum of squares |
setsliders(sliders: id or tag, values: string, [dur: number], [ease: easing]) | animation verb | animate every dial of a sliders rack to its value in [-1,1] (one value per dial) and update the sum-of-squares readout |
deform(id: id or tag, u: string, v: string, [dur: number], [ease: easing]) | state-changing verb | continuous homotopy: over dur, animate t:0->1 and remap an entity’s outline points by (u(x,y,t), v(x,y,t)) each frame — the animated twin of warp. Write t=0 as the identity (u=x, v=y). e.g. a wave: v = y + ampsin(xk + t)sin(pit) |
wiggle(id: id or tag, [dur: number]) | animation verb | an attention WIGGLE: a there-and-back scale pulse + oscillating rotation, returning to base. The rotate+scale cousin of shake (which is translation only) |
blink(id: id or tag, [dur: number]) | animation verb | blink an entity out-and-in twice over dur to draw the eye |
circumscribe(id: id or tag, [color: colour], [dur: number]) | state-changing verb | draw a temporary outlined rectangle around an entity or group, then fade it — a transient surround to call attention. Creates {id}.circ |
spotlight(id: id or tag, [dur: number]) | state-changing verb | a translucent disc converges onto an entity then fades — a converging spotlight that draws focus to it. Creates {id}.spot |
passflash(id: id or tag, [color: colour], [dur: number]) | state-changing verb | a luminous sliver travels along an entity’s outline once, then vanishes (closed shapes: the light circles the whole outline). Creates {id}.pass |
savestate(id: id or tag) | constructor / setup | snapshot an entity’s transform (pos/scale/rotation/colour/opacity); restore(id, ...) later animates it back to how it started |
spiralin(group: id or tag, [dur: number]) | state-changing verb | reveal a group’s members by spiralling them in from a rotated, shrunken offset while fading up, staggered |
trail(id: id or tag, target: id or tag, [color: colour], [thickness: number]) | constructor / setup | a growing motion trail that records where an entity has been |
loupe(id: new id, source: (x, y), sw: number, sh: number, display: (x, y), mag: number, [frame_color: colour], [panel_color: colour]) | constructor / setup | a magnifier: a source frame swsh over the scene at (sx,sy) + a panel at (dx,dy) that shows that region magnified mag live. Animate {id}.frame (move/scale) and the view follows. Manim’s ZoomedScene |
regions(…) | constructor / setup | fill + count the areas the dividers (chords/segments/edges — each an entity or tag) cut a boundary (polygon/rect/circle) into. Computes the planar arrangement; fills every enclosed face {id}.r0, {id}.r1, … (all tagged {id}) with a cycling palette. The number of {id}.r* parts is the region count. Variadic: regions(id, boundary, d1, d2, …) |
spantree(…) | constructor / setup | a spanning tree (forest) of the graph whose edges are the given entities/tags. Greedy union-find in argument order (list preferred edges first to shape the tree). Tree edges = green overlays {id}.t0.. (tagged {id}); leftover co-tree edges = overlays {id}.c0.. (tagged {id}.co). Works on any drawn graph, including a dual. Variadic: spantree(id, e1, e2, …) |
dual(…) | constructor / setup | the DUAL graph of a planar graph: a node at each enclosed face’s centre + one OUTER node, and a dual edge across each primal edge joining the two faces it separates (boundary edge -> outer node). Nodes = dots {id}.n0.. (tagged {id}.nodes); dual edges = lines tagged {id}, so spantree(dt, id) gives the dual’s spanning tree (F-1 edges). Variadic: dual(id, boundary, d1, d2, …) |
grow(id: id or tag, to: (x, y), [dur: number], [ease: easing]) | animation verb | animate a line/arrow endpoint |
scale(id: id or tag, factor: number, [dur: number]) | animation verb | animate scale to a factor |
rotate(id: id or tag, degrees: number, [dur: number], [ease: easing]) | animation verb | animate rotation |
say(id: id or tag, text: string, [dur: number], [ease: easing]) | animation verb | crossfade text to new content |
speak(…) | animation verb | narrate with TTS; service from voice(“gtts”|“cartesia”|“elevenlabs”) (default gTTS); speak(“text”) or speak(caption, “text”); duration is the voice length |
cue(sound: id or tag) | animation verb | play a deterministic procedural sound beat: tick, pop, whoosh, or chime |
rewrite(equation: id or tag, latex: string, [dur: number], [ease: easing]) | state-changing verb | smoothly transform one authored LaTeX equation state into the next while matching unchanged visual parts; this animates supplied math and does not solve it |
type(id: id or tag, [dur: number]) | animation verb | typewriter reveal |
to(id: id or tag, prop: new id, value: number, [dur: number], [ease: easing]) | animation verb | animate any property to a value |
set(id: id or tag, prop: new id, value: number, [dur: number], [ease: easing]) | animation verb | alias of to |
transform(id: id or tag, origin: (x, y), a: number, b: number, c: number, d: number, [dur: number], [ease: easing]) | animation verb | apply a 2x2 matrix (ApplyMatrix) |
swap(a: id or tag, b: id or tag, [dur: number]) | state-changing verb | swap two entities, or array slots i,j |
cycle(…) | state-changing verb | move entities cyclically into one another’s positions along an optional arc |
cam(to: (x, y), [dur: number], [ease: easing]) | animation verb | pan the camera to a point |
zoom(factor: number, [dur: number], [ease: easing]) | animation verb | zoom the camera |
followshot(target: id or tag, [offset: (x, y)]) | state-changing verb | a moving-camera FOLLOW SHOT: the 2D camera tracks an entity, centred on it every frame (+ optional screen offset). Pair with zoom; none releases it (pan/zoom back to restore) |
karaoke(…) | animation verb | highlight caption words in sequence |
wordpop(…) | animation verb | pop caption words in one at a time |
sweep(id: new id, template: id or tag, xparam: new id, xrange: (x, y), yparam: new id, yrange: (x, y), [center: (x, y)], [cols: number], [rows: number], [cellw: number], [cellh: number], [overlays: number], [fit: number]) | constructor / setup | a small-multiples GRID of anything, over any two of its parameters. template is an id you declared normally; each cell rebuilds it with xparam/yparam stepped across their ranges (parameter names come from the builtin’s own signature). Kit-agnostic: it re-invokes the constructor, so it works for any kit, sims or plain shapes. Cells are ordinary entities tagged {id} + {id}.cells; run(id) plays every cell, run({id}.c0x0) just one. Cells are BARE by default (a sim’s {id}.overlays chrome is stripped from the grid) - pass overlays=1 to keep it. fit 0-1 = how much of the MOTION must fit in a cell (1 = never leaves the cell, 0 = fit the resting pose and let a big swing cross the edge) |
Generative
| API | Kind | What it does |
|---|---|---|
lsystem(id: new id, center: (x, y), size: number, axiom: string, rules: string, [options: string]) | constructor / setup | a fitted, batched curve L-system with turtle turns, continuous draw-on, and optional closed concave fill |
repeat(id: new id, motif: id or tag, options: string) | constructor / setup | repeat one entity or tagged motif as a stable hex, grid, or radial arrangement |
ifs2(id: new id, center: (x, y), size: (x, y), count: number, seed: number, rules: string, [options: string]) | constructor / setup | a deterministic batched affine iterated-function system |
mandelbrot(id: new id, center: (x, y), size: (x, y), xrange: (x, y), yrange: (x, y), iterations: number, [columns: number]) | constructor / setup | a batched escape-time Mandelbrot field |
polarpath(id: new id, center: (x, y), scale: number, formula: string, range: (x, y), [samples: number], [closed: number]) | constructor / setup | a sampled polar formula path |
hull2(id: new id, cloud: id or tag, [depth: number], [pivot: number]) | constructor / setup | an onion-depth hull derived from a batched point cloud |
3D
| API | Kind | What it does |
|---|---|---|
cloud3(…) | constructor / setup | a 3D point field: N points placed by closed-form x/y/z formulas of index i and time t |
camera3(eye: (x, y, z), target: (x, y, z), [fov: number], [projection: id or tag], [panel_center: (x, y)], [panel_w: number], [panel_h: number]) | constructor / setup | a Z-up orbit camera. Optionally render the 3D scene into a canvas-space VIEWPORT panel — pass (cx,cy), w, h after the projection and the 3D renders into that bordered sub-rect (a 3D inset in a 2D layout) instead of the whole canvas, using the panel’s own aspect. |
point3(id: new id, at: (x, y, z), [radius: number]) | constructor / setup | a point in 3D space |
line3(id: new id, from: (x, y, z), to: (x, y, z)) | constructor / setup | a 3D line segment |
arrow3(id: new id, from: (x, y, z), to: (x, y, z)) | constructor / setup | a 3D vector arrow |
cross3(id: new id, origin: (x, y, z), v: (x, y, z), w: (x, y, z), [color: colour]) | constructor / setup | the 3D CROSS PRODUCT v x w shown geometrically: the two vectors, the parallelogram they span, and p = v x w perpendicular to both with length = that parallelogram’s AREA (the geometric meaning behind the determinant formula). Vectors {id}.v (green), {id}.w (red), {id}.p (the cross, gold); parallelogram far edges {id}.e1/{id}.e2. All tagged {id}. Orbit with camera3. |
cube3(id: new id, center: (x, y, z), size: (x, y, z)) | constructor / setup | a rotatable 3D cuboid |
linmap3(id: new id, center: (x, y, z), a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, [color: colour]) | constructor / setup | a 3x3 matrix deforming the unit cube; volume = determinant |
eigen3(id: new id, center: (x, y, z), a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, [color: colour]) | constructor / setup | the real eigenvector directions of a 3x3 matrix (invariant lines) |
sphere3(id: new id, center: (x, y, z), radius: number) | constructor / setup | a 3D sphere |
collection3(id: new id, center: (x, y, z), count: number, spread: (x, y, z), seed: number, [radius: number]) | constructor / setup | renderer-batched repeated 3D points with stable indexed children |
collection3data(id: new id, center: (x, y, z), points: string, [radius: number]) | constructor / setup | renderer-batched explicit 3D coordinates with stable indexed children |
links3(id: new id, collection: id or tag, mode: id or tag, [neighbors: number]) | constructor / setup | live relationship mesh over a collection3: chain, nearest, or all |
links3data(id: new id, collection: id or tag, edges: string) | constructor / setup | an explicit arbitrary edge list that follows a 3D collection |
trail3(id: new id, collection: id or tag, [child: number], [thickness: number]) | constructor / setup | live history path for one stable indexed child of a collection3 |
ring3(id: new id, collection: id or tag, child: number, [segments: number]) | constructor / setup | live orbit ring derived from one segment of a collection3 chain |
historyplot(id: new id, collection: id or tag, child: number, component: id or tag, center: (x, y), size: (x, y)) | constructor / setup | screen-space 2D component history derived from one compiled collection3 child |
historyplot3(id: new id, collection: id or tag, child: number, component: id or tag, origin: (x, y, z), size: (x, y)) | constructor / setup | world-space 3D component history derived from one compiled collection3 child |
child3(id: new id, collection: id or tag, index: number, [radius: number]) | constructor / setup | addressable proxy for one stable indexed child of a collection3 |
tree3(id: new id, root: (x, y, z), length: number, angle: number, shrink: number, depth: number, seed: number) | constructor / setup | seeded fractal tree batched as one edge mesh per generation |
vectorfield3(id: new id, center: (x, y, z), half: (x, y, z), u: string, v: string, w: string, [density: number]) | constructor / setup | bounded batched 3D vector field from x/y/z/p component formulas |
grid3(id: new id, center: (x, y, z), half: number, [spacing: number]) | constructor / setup | an XY ground grid |
axes3(id: new id, origin: (x, y, z), length: number, [step: number]) | constructor / setup | three colored coordinate axes with ticks + numbers |
frame3(id: new id, center: (x, y, z), size: (x, y, z), [options: string]) | constructor / setup | bounded scientific axes and selectable XY/XZ/YZ grid planes |
randomwalk3(id: new id, center: (x, y, z), steps: number, [seed: number], [options: string]) | constructor / setup | a deterministic batched 3D axis or turtle walk with optional direction color and depth shading |
hilbert3(id: new id, center: (x, y, z), size: number, order: number, [options: string]) | constructor / setup | a bounded batched 3D Hilbert curve that visits every lattice cell once |
present3(frame: id or tag, mode: id or tag, [dur: number], [ease: easing]) | state-changing verb | restyle one frame3 as textbook linework or spatial color |
move3(id: id or tag, to: (x, y, z), [dur: number], [ease: easing]) | animation verb | move a 3D entity |
shift3(id: id or tag, by: (x, y, z), [dur: number], [ease: easing]) | animation verb | shift a 3D entity |
rotate3(id: id or tag, degrees: (x, y, z), [dur: number], [ease: easing]) | animation verb | rotate to Euler angles |
grow3(id: id or tag, to: (x, y, z), [dur: number], [ease: easing]) | animation verb | retarget a 3D line or arrow |
orbit3(azimuth: number, elevation: number, radius: number, [dur: number], [ease: easing]) | animation verb | orbit the 3D camera |
roll3(degrees: number, [dur: number], [ease: easing]) | animation verb | roll the 3D camera around its viewing direction |
look3(target: (x, y, z), [dur: number], [ease: easing]) | animation verb | move the 3D camera target |
drift3(collection: id or tag, dur: number, [amount: number]) | state-changing verb | compile deterministic bounded ambient motion for a collection3 |
chain3(collection: id or tag, lengths: string, rates: string, dur: number) | state-changing verb | animate a generated dependent chain from per-link lengths and rotation rates |
advect3(collection: id or tag, field: id or tag, dur: number, [rate: number]) | state-changing verb | advect a collection3 through a time-varying vectorfield3 with deterministic RK4 |
followshot3(target: id or tag, [offset: (x, y, z)]) | state-changing verb | make the 3D camera target follow an entity, or release with none |
view3(target: id or tag, view: string, [dur: number], [ease: easing], [margin: number]) | state-changing verb | smoothly frame a 3D entity or tagged group from a named view |
travel3(entity: id or tag, path: id or tag, [dur: number], [ease: easing]) | state-changing verb | move a persistent 3D entity along a line, arrow, or curve |
attach3(child: id or tag, target: id or tag, [offset: (x, y, z)], [mode: id or tag]) | state-changing verb | attach one 3D entity to another, or release it with none |
become3(source: id or tag, blueprint: id or tag, [dur: number], [ease: easing]) | state-changing verb | transform a persistent 3D entity into a blueprint |
turn3(target: id or tag, pivot: (x, y, z), axis: id or tag, degrees: number, [dur: number], [ease: easing]) | state-changing verb | turn a 3D entity or tagged group around a world-space pivot and axis |
pin3(label: id or tag, at: (x, y, z), [offset: (x, y)]) | constructor / setup | glue a 2D label to a 3D point with an optional screen-space offset |
follow3(id: id or tag, target: id or tag, [offset: (x, y, z)]) | constructor / setup | track another 3D entity + offset each frame |
midpoint3(id: new id, a: id or tag, b: id or tag) | constructor / setup | a point at the midpoint of two 3D entities |
link3(id: new id, a: id or tag, b: id or tag, [trim: number]) | constructor / setup | a live 3D edge between two moving entities |
project3(id: new id, source: id or tag, plane: string) | constructor / setup | live orthogonal projection of a 3D entity onto xy, xz, or yz |
projectpath3(id: new id, source: id or tag, plane: id or tag) | constructor / setup | live orthogonal projection of a complete changing 3D path |
contour3(id: new id, surface: id or tag, level: number) | constructor / setup | a level curve on a surface3 height field |
label3(label: id or tag, target: id or tag, [world_height: number]) | constructor / setup | projected label with optional world-space height |
curve3(id: new id, x: string, y: string, z: string, [domain: (x, y)]) | constructor / setup | parametric 3D curve from x(t)/y(t)/z(t) formulas |
trajectory3(id: new id, dx/dt: string, dy/dt: string, dz/dt: string, start: (x, y, z), [steps: number], [dt: number]) | constructor / setup | integrate a 3D ODE (dx/dt, dy/dt, dz/dt) with RK4 — draws strange attractors (Lorenz, …) |
surface3(id: new id, z: string, xdom: (x, y), ydom: (x, y), [res: number]) | constructor / setup | filled, flat-shaded height-field surface z = f(x,y) |
domainsurface(id: new id, formula: string, xdom: (x, y), ydom: (x, y), [res: number], [height: number]) | constructor / setup | DOMAIN COLOURING in 3D — the modulus surface of a complex function f(z): each grid point is z=x+iy, the surface HEIGHT is height·|f(z)| (poles clamped finite) and each vertex’s COLOUR is arg f(z) (phase hue). Orbit with camera3. Write f in z/i (e.g. 1/(z*z+1), (z-1)/(z+1), sin(z)). res = grid resolution (default 48), height = vertical scale (default 1). |
implicit3(id: new id, formula: string, xdom: (x, y), ydom: (x, y), zdom: (x, y), [level: number], [resolution: number]) | constructor / setup | an isosurface extracted from a bounded 3D scalar field |
lsystem3(id: new id, origin: (x, y, z), step: number, angle: number, iterations: number, axiom: string, rules: string, [max_symbols: number]) | constructor / setup | a bounded deterministic branching 3D turtle grammar |
heightmap3(id: new id, grid: id or tag, z: string, [size: number]) | constructor / setup | lift a 2D grid into a 3D terrain mesh: z(x,y,h), h=cell value |
gradient3(id: new id, surface: new id, x: number, y: number, [color: colour]) | constructor / setup | steepest-ascent arrow on a surface3 at (x,y) |
slice3(id: new id, surface: new id, axis: id or tag, value: number, [at: number], [color: colour]) | constructor / setup | the geometric partial derivative: cut a surface3 at a constant coordinate (axis = x or y) and draw the cross-section curve riding the surface, whose steepness is the partial along the free axis; with at, also draw the tangent whose slope is that partial at that point |
descend3(id: new id, surface: new id, x: number, y: number, [rate: number], [steps: number], [color: colour]) | constructor / setup | gradient DESCENT on a surface3: from a start (x,y), step against the gradient (rate, steps) and trace the path the ball rolls downhill to a minimum; draw the path to roll it on, {id}.ball marks the start |
tangentplane3(id: new id, surface: new id, x: number, y: number, [color: colour]) | constructor / setup | the plane tangent to a surface3 at (x,y) |
volume3(id: new id, surface: new id, [res: number], [color: colour]) | constructor / setup | the volume under a surface3 as a grid of columns |
param3(id: new id, x: string, y: string, z: string, udom: (x, y), vdom: (x, y), [res: number]) | constructor / setup | parametric surface x(u,v),y(u,v),z(u,v) — tori, shells, Möbius |
pieces3(id: new id, source: new id, cols: number, [rows: number], [inset: number]) | constructor / setup | cut a param3/surface3 into addressable pieces ({id}.r{i}c{j}, tags {id}.row{i}/.col{j}); they follow a bound source as it deforms |
prism3(id: new id, center: (x, y, z), sides: number, radius: number, height: number) | constructor / setup | regular n-gon prism (many sides ≈ cylinder) |
pyramid3(id: new id, center: (x, y, z), sides: number, radius: number, height: number) | constructor / setup | regular n-gon pyramid (many sides ≈ cone) |
revolve3(id: new id, center: (x, y, z), profile: string, tdom: (x, y), [sides: number]) | constructor / setup | solid of revolution from a radius profile r(t) |
extrude3(id: new id, source: id or tag, height: number, [center: (x, y, z)]) | constructor / setup | extrude a 2D shape or boolean region into a solid prism (CSG) |
morph3(a: id or tag, b: id or tag, [spin: number]) | constructor / setup | set 3D entity a up to morph into b’s shape (animate with to(a, morph, 1, dur)) |
thick(id: id or tag, radius: number) | constructor / setup | render a 3D curve3/line3/arrow3 as a tube of the given world radius |
finish3(id: id or tag, spec: string) | constructor / setup | bounded 3D finish: shading (flat|smooth), material (matte|metal|glass), texture (solid|checker|stripes), scale, mesh, wire (0..1 — render any solid as a bright triangulated WIREFRAME with no filled faces; sphere/cube/prism/pyramid/extrude/surface), depth, shadow |
model3(id: new id, path: string, center: (x, y, z), [scale: number]) | constructor / setup | load deterministic geometry from a bundled asset: URI or safety-limited OBJ path |
assembly3(id: new id, path: string, center: (x, y, z), [scale: number]) | constructor / setup | load grouped OBJ geometry as addressable id.group entities sharing one id tag |
tube3(id: new id, path: id or tag, radius: string, [sides: number]) | constructor / setup | variable-radius tube around a line3, arrow3, or curve3 |
Math
| API | Kind | What it does |
|---|---|---|
colorwheel(id: new id, center: (x, y), radius: number) | constructor / setup | the LEGEND for domain colouring: a hue disk of radius px where angle = phase (arg) and the centre darkens (small |z|) toward a bright rim — the key for domaincolor/domainsurface. |
warp(id: new id, center: (x, y), unit: number, formula: string, [range: number], [res: number]) | constructor / setup | a coordinate grid over the complex plane that DEFORMS under a complex function z->f(z): each grid line is sampled from f (so it bends into a curve). Starts as the identity grid and morphs to the warped image when you animate it — to(id, morph, 1, dur) (broadcasts over the whole grid). Write f in z/i (e.g. z*z, 1/z, (z-1)/(z+1), sin(z)). The complex/non-linear twin of linmap and the deforming-grid companion to domaincolor. range = half-width in complex units (default 3, integer grid lines); res = samples per line (curve smoothness, default 28). Lines tagged {id}. |
squish(id: new id, center: (x, y), unit: number, a: number, b: number, [span: number]) | constructor / setup | the DOT PRODUCT as a transformation (DUALITY): the whole plane collapses onto a NUMBER LINE under the 1x2 map [a b], sending (x,y) -> ax + by. Animate with to(id, morph, 1, dur) — the grid squishes onto the line, i-hat lands on a, j-hat on b. The gold DUAL VECTOR (a,b) ({id}.dual) is the 2D vector whose dot product IS this map (the duality). The rank-reducing sibling of gridmap; output line + ticks are {id}.line. |
domaincolor(id: new id, center: (x, y), w: number, h: number, formula: string, [range: number]) | constructor / setup | domain colouring of a complex function f(z) over a w×h plane region: each pixel is z=x+iy, hue = arg f(z), brightness from |f(z)| (zeros dark, poles white). Write f in terms of the complex variable z and the imaginary unit i (e.g. z^2+1, 1/(z*z+1), sin(z), (z-1)/(z+1)); constants pi/tau/e and functions sin/cos/tan/sinh/cosh/tanh/exp/ln/sqrt/conj/abs/re/im AND zeta (the Riemann zeta function, valid through the critical strip — zeta(z) shows the pole at s=1 and zeros as dark points). range = half-width in complex units along the real axis (default 4; imaginary extent scales by aspect). |
axes(id: new id, center: (x, y), halfw: number, halfh: number, [unit: number]) | constructor / setup | a coordinate frame (optional tick spacing in px) |
coords(id: new id, origin: (x, y), xrange: (x, y), yrange: (x, y), sx: number, sy: number, [tips: number], [step: number], [numbers: number], [xname: string], [yname: string]) | constructor / setup | a flexible coordinate frame: arbitrary ranges, per-axis scale, optional tips/ticks/auto-numbers, and optional axis names. Origin (0,0) maps to origin; align a plot with the same origin+sx+sy. Use xtick/ytick for custom (non-numeric) tick labels |
xtick(id: new id, coords: new id, value: number, [text: string]) | constructor / setup | a tick + label on a coords frame’s x-axis at an axis VALUE (not a pixel); label is any text — number, word (“Mon”), or symbol (“π/2”) — omit to show the value |
ytick(id: new id, coords: new id, value: number, [text: string]) | constructor / setup | a tick + label on a coords frame’s y-axis at an axis VALUE (see xtick) |
field(id: new id, formula: string) | constructor / setup | define a REUSABLE scalar field — a pure function of x and y: field(name, “expr”). Call it name(a, b) inside ANY formula (plot / surface3 / shader / cloud) and it INLINES, so every view samples the identical expression (author once, view many ways — provably the same field; e.g. plot name(x,0), surface3 name(x,y), a heatmap shader name((u-0.5)*8,(v-0.5)*8)). Use name(x, 0) for a 1-D slice. Body may use only x, y, pi/tau/e, and functions — pass time/extra inputs at the call site. Not an entity; references only earlier-defined fields (no cycles). |
plot(id: new id, center: (x, y), sx: number, sy: number, formula: function or formula, [domain: number]) | constructor / setup | y = f(x) as a curve |
param(id: new id, center: (x, y), sx: number, sy: number, x: string, y: string, [tdomain: number]) | constructor / setup | a PARAMETRIC curve (x(t), y(t)) — the twin of plot for curves that aren’t y=f(x): spirals, roses, Lissajous. Two formulas in the parameter t; tdomain is a (t0,t1) pair or a scalar giving [0,t] (default [0, tau]). sx/sy are px per unit, origin at center. |
polar(id: new id, center: (x, y), sx: number, sy: number, r: string, [tdomain: number]) | constructor / setup | a POLAR curve r = f(t) with t the angle θ; traces (r·cos t, r·sin t). tdomain is a (t0,t1) pair or a scalar [0,t] (default [0, tau]). Roses cos(3t), spirals t, limaçons. |
normal(id: new id, curve: new id, x: number, [len: number]) | constructor / setup | the normal (perpendicular) line to a curve at x |
slope(id: new id, curve: new id, x: number, [offset: (x, y)]) | constructor / setup | a live readout of a curve’s slope at x |
slopetri(id: new id, curve: new id, x: number, [run: number]) | constructor / setup | a slope triangle on a curve at x: a run leg (length run, default 1, labeled {id}.one) + a red rise leg up to the tangent, proving slope = rise/run. Parts {id}.run/.rise/.one share tag {id}, so to(id, x, ...) slides the whole triangle in lock-step. |
area(id: new id, curve: new id, a: number, b: number, [n: number]) | constructor / setup | the filled region under a curve from a to b |
integral(id: new id, curve: new id, a: number, b: number, [at: (x, y)]) | constructor / setup | a live readout of the integral of a curve from a to b |
roots(id: new id, curve: new id, [color: colour]) | constructor / setup | dots where a curve crosses zero |
deriv(id: new id, curve: new id, [color: colour]) | constructor / setup | the derivative f’ of a curve, drawn as its own curve |
accum(id: new id, curve: new id, [a: number], [color: colour]) | constructor / setup | the accumulation function integral(a..x) of a curve |
extrema(id: new id, curve: new id, [color: colour]) | constructor / setup | dots at a curve’s maxima and minima (slope = 0) |
inflections(id: new id, curve: new id, [color: colour]) | constructor / setup | dots where a curve changes concavity (f’’ = 0) |
band(id: new id, top: new id, bottom: new id, [color: colour], [range: (x, y)]) | constructor / setup | the filled region between two curves (optional (a,b) restricts it to that x-slice) |
vline(id: new id, curve: new id, x: number, [color: colour], [style: id or tag]) | constructor / setup | a guide line from the x-axis up to a plotted curve at x; dotted by default (style: dotted/dashed/solid) |
curvedot(id: new id, curve: new id, x: number, [color: colour]) | constructor / setup | a dot that rides a plotted curve at x, always on the graph; slide it with to(id, x, …). Named curvedot and not mark, because mark("name") is the timeline beat marker |
graphlabel(id: new id, curve: new id, latex: string, [x: number], [direction: id or tag], [color: colour]) | constructor / setup | a LaTeX label pinned to a plotted curve at x (default: the curve’s right end), nudged clear of the line in a direction (up/down/left/right/upright/upleft/downright/downleft, default up); colour defaults to the curve’s. Put LaTeX in BACKTICKS |
boxto(id: new id, curve: new id, x: number, [color: colour]) | constructor / setup | a filled rectangle from the origin (0,0) to the point (x, f(x)) on a curve (an inscribed box, area x*f(x)); slide it with to(id, x, …) — on y=k/x the area stays constant |
riemann(id: new id, curve: new id, a: number, b: number, [dx: number], [color: colour]) | constructor / setup | Riemann rectangles under a curve from a to b (bars of width dx, left-endpoint sampled) — the discrete analogue of area; default colour green |
taylor(id: new id, curve: new id, a: number, n: number, [color: colour]) | constructor / setup | the degree-n Taylor polynomial of a curve about a |
limit(id: new id, curve: new id, a: number, [color: colour]) | constructor / setup | visualise lim(x->a) f(x): the value approached, with an approaching dot |
newton(id: new id, curve: new id, x0: number, [steps: number]) | constructor / setup | Newton’s method zig-zag from a starting guess |
spline(…) | constructor / setup | a smooth curve through a list of points |
trajectory(id: new id, dx/dt: string, dy/dt: string, start: (x, y), center: (x, y), scale: number, [steps: number]) | constructor / setup | an ODE path: dx/dt, dy/dt integrated from a start point |
linmap(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, [span: number]) | constructor / setup | a 2x2 matrix applied to the plane (grid + basis), shown STATICALLY as a before/after (faint identity grid + bright transformed grid). For the ANIMATED version use gridmap. |
gridmap(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, [span: number], [a0: number], [b0: number], [c0: number], [d0: number]) | constructor / setup | an ANIMATED 2x2 matrix transform of the plane: a coordinate grid + basis i-hat/j-hat that MORPHS from the identity to [[a,b],[c,d]] when you animate it — to(id, morph, 1, dur) sweeps all of space deforming (the iconic ‘matrices transform space’). A faint identity grid {id}.bg stays behind. The animated twin of linmap (static before/after) and the linear sibling of warp (complex). i-hat lands on the first column, j-hat on the second. Optional FROM matrix a0,b0,c0,d0 (default identity): morph BETWEEN two matrices [[a0,b0],[c0,d0]] -> [[a,b],[c,d]] so a second gridmap continues where the first left off (matrix multiplication = composition). |
determinant(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, [color: colour]) | constructor / setup | the unit square mapped to a parallelogram; area = det |
eigen(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, [color: colour]) | constructor / setup | a matrix’s real eigenvector directions (with eigenvalues) |
diagonalise(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, [color: colour]) | constructor / setup | A = P D P^-1: in the eigenbasis the matrix is a pure stretch |
diagonalize(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, [color: colour]) | constructor / setup | A = P D P^-1: in the eigenbasis the matrix is a pure stretch |
rref(id: new id, data: string, center: (x, y), [cellw: number], [rowh: number]) | constructor / setup | animated Gaussian elimination to reduced row-echelon form |
project(id: new id, center: (x, y), unit: number, b: (x, y), a: (x, y), [color: colour]) | constructor / setup | orthogonal projection of a vector onto a line (subspace) |
leastsquares(id: new id, center: (x, y), unit: number, data: string, [color: colour]) | constructor / setup | the best-fit line through a point cloud (linear regression) |
linsolve(id: new id, center: (x, y), unit: number, a: number, b: number, c: number, d: number, e: number, f: number, [span: number]) | constructor / setup | the row picture of Ax=b: two lines meeting at the solution |
span(id: new id, center: (x, y), unit: number, v: (x, y), [w: (x, y)], [color: colour]) | constructor / setup | the span of one or two vectors (a line, or the whole plane) |
vector(id: new id, origin: (x, y), delta: (x, y), [color: colour]) | constructor / setup | an arrow from an origin |
numberline(…) | constructor / setup | a labelled number line |
numberplane(…) | constructor / setup | a gridded coordinate plane |
plane(…) | constructor / setup | a coordinate plane |
complexplane(…) | constructor / setup | the complex plane |
polarplane(…) | constructor / setup | a polar grid |
matrix(id: new id, data: string, center: (x, y), [colw: number], [rowh: number]) | constructor / setup | a bracketed matrix |
table(id: new id, data: string, center: (x, y), [colw: number], [rowh: number], [cols: string], [rows: string]) | constructor / setup | a ruled table |
mathtable(…) | constructor / setup | a table of math expressions |
integertable(…) | constructor / setup | a table of integers |
decimaltable(…) | constructor / setup | a table of decimals |
arc(…) | constructor / setup | a circular arc |
sector(…) | constructor / setup | a pie sector |
annulus(…) | constructor / setup | a ring / annular sector |
pie(…) | constructor / setup | a pie chart |
arrowfield(…) | constructor / setup | a named or formula-authored bounded vector field |
vectorfield(…) | constructor / setup | a named or formula-authored bounded vector field |
tangent(…) | constructor / setup | tangent line to a curve at x (or tangent points to a circle) |
Process
| API | Kind | What it does |
|---|---|---|
livehistogram(id: new id, center: (x, y), min: number, max: number, bins: number, [width: number], [height: number], [color: colour]) | constructor / setup | an initially empty histogram driven by real measurements from a deterministic collection process |
stream(particles: id or tag, path: id or tag, dur: number, [spread: number], [ease: easing]) | state-changing verb | progressively send a persistent particle collection along a path and retain truthful arrival/speed measurements |
emit(particles: id or tag, path: id or tag, profile: id or tag, dur: number, [spread: number], [ease: easing]) | state-changing verb | release a persistent particle collection with deterministic individual speeds sampled from a named profile |
advect(target: id or tag, field: id or tag, duration: number, [rate: number]) | state-changing verb | carry a particles collection OR a whole cloud through a bounded vector field with deterministic seekable RK4 integration. A particles collection keeps every child individually addressable (capped at 500 by particles); a cloud is batched, so its paths are precompiled and the whole swarm — tens of thousands of points — rides one track. Cloud seeds come from the cloud’s own formulas, so the flow starts from the shape you drew. Either way a particle reaching the field boundary stops there |
branch(particles: id or tag, paths: id or tag, dur: number, [ease: easing]) | state-changing verb | send every persistent item through one seeded route in a tagged directed acyclic path network |
collect(histogram: id or tag, particles: id or tag, measurement: id or tag, [dur: number], [ease: easing]) | state-changing verb | catch processed particles in the live-histogram bins selected by their real speed, arrival, outcome, or step measurement |
observe(target: id or tag, particles: id or tag, measurement: id or tag) | animation verb | drive a counter or live histogram from measurements produced by the latest stream, emit, or branch process |
Charts
| API | Kind | What it does |
|---|---|---|
racechart(id: new id, layout: string, periods: string, [title: string]) | constructor / setup | declare an animated race chart: layout “bar” (v1), a period-label list that ticks as it plays, and an optional title; feed rows with racedata, then play with race |
racedata(parent: new id, block: string) | constructor / setup | paste the data for a race chart — one row per entity: label [icon] v0 v1 …; rows split on newline or ;, cells on comma/tab/whitespace; the optional icon is an SVG shorthand (us → a flag) or a full asset path |
raceseries(parent: new id, label: string, icon_or_values: string, [values: string]) | constructor / setup | add ONE entity to a race chart (the per-series sibling of racedata, for the computed/loop path): raceseries(parent, "label", ["icon"], "v0 v1 …") |
raceline(parent: new id, [label: string], [values: string]) | constructor / setup | add a companion LINE across the top of a bar race — a running total (auto-summed from the bars) or an explicit tracked metric: raceline(parent, ["label"], ["v0 v1 …"]) |
racepanel(parent: new id) | constructor / setup | add a multi-line HISTORY panel at the bottom of a bar race — every series drawn as a line up to a moving time-cursor, synced to the race (the classic bar+line combo): racepanel(parent) |
race(parent: new id, [dur: number], [ease: new id]) | animation verb | play the whole race: interpolate each series between periods, re-rank, slide bars to their new slots (the reorder IS the race), rescale to the running max, and tick the period + value counters |
Systems
| API | Kind | What it does |
|---|---|---|
architecture(id: new id, [center: (x, y)], [width: number], [height: number]) | constructor / setup | an automatically laid-out diagram canvas; geometry is optional and auto-fits the canvas when omitted |
flowchart(id: new id, [direction: id or tag], [max_nodes: number]) | constructor / setup | an edge-ranked flowchart canvas (Mermaid graph TD/LR); with no direction it auto-orients TD/LR to fit and re-decides as nodes are added; reuses the architecture layout/ports/scale-to-fit. Optional max_nodes is the readability split limit (default 6 top-down, 12 left-right) — over it, check warns to split into linked sub-flows |
c4(id: new id, [level: id or tag]) | constructor / setup | a C4-model diagram canvas (Context/Container/Component); inside it node kinds read as C4 elements (person/system/container/component/external) with name/[type: tech]/description |
node(id: new id, parent: id or tag, kind: string, label: string, [description: string], [technology: string]) | constructor / setup | a component inside an architecture/cluster/c4/flowchart; kind is a provider icon, native archetype, flowchart shape, or C4 element. In a c4 diagram the extra args are the box’s description and technology |
cluster(id: new id, parent: id or tag, label: string, [legacy_members: string]) | constructor / setup | a labelled responsive ownership group; children name it as their parent |
connect(id: new id, from: id or tag, to: id or tag, [routing: routing], [from_port: port], [to_port: port]) | constructor / setup | a dashed directed possibility with an optional bend or port-aware orthogonal route |
annotate(edge: id or tag, text: string) | constructor / setup | a small caption at a connection’s midpoint (a decision’s yes/no, or any edge annotation) |
message(id: new id, source: id or tag, label: string) | constructor / setup | a persistent generic message starting at one system node |
request(id: new id, source: id or tag, label: string) | constructor / setup | a persistent labelled request starting at one system node |
route(message: id or tag, connection: id or tag, [duration: number], [ease: easing]) | state-changing verb | move one persistent message through a continuous named connection and illuminate its selected lane |
hotpath(message: id or tag, [duration: number], [seed: number]) | state-changing verb | move one persistent message end-to-end over a seeded valid path, choosing one lane at each fan-out |
Geometry
| API | Kind | What it does |
|---|---|---|
point(id: new id, at: (x, y), [label: string]) | constructor / setup | a labelled point |
segment(id: new id, a: id or tag, b: id or tag) | constructor / setup | segment between two points |
midpoint(id: new id, a: id or tag, b: id or tag) | constructor / setup | midpoint of two points |
centroid(…) | constructor / setup | centroid of a triangle |
circumcenter(…) | constructor / setup | circumcentre |
incenter(…) | constructor / setup | incentre |
orthocenter(…) | constructor / setup | orthocentre |
foot(…) | constructor / setup | foot of a perpendicular |
meet(…) | constructor / setup | line-line intersection |
linecircle(…) | constructor / setup | line-circle intersection |
circlecircle(…) | constructor / setup | circle-circle intersection |
commontangent(id: new id, oA: id or tag, aOn: id or tag, oB: id or tag, bOn: id or tag, [type: string]) | constructor / setup | a common tangent to two circles (each = centre + a point on it): segment {id} between the touch points {id}.a/{id}.b; type external/direct (default) or internal/transverse |
reflect(…) | constructor / setup | reflect a point over a line |
bisector(…) | constructor / setup | angle bisector |
rotpoint(…) | constructor / setup | rotate a point about another |
between(…) | constructor / setup | a point between two others |
anglepoint(…) | constructor / setup | a point at an angle |
circumcircle(…) | constructor / setup | circumscribed circle |
incircle(…) | constructor / setup | inscribed circle |
circle2(…) | constructor / setup | circle from centre + a point on it |
ellipse(…) | constructor / setup | an ellipse |
parabola(…) | constructor / setup | a parabola |
hyperbola(…) | constructor / setup | a hyperbola |
fullline(…) | constructor / setup | an infinite line through two points |
anglemark(…) | constructor / setup | an angle arc mark (optional label rides the bisector) |
rightangle(…) | constructor / setup | a right-angle square mark |
Algorithms and data structures
| API | Kind | What it does |
|---|---|---|
graph(id: new id, verts: string, edges: string, layout: new id, center: (x, y), scale: number, [radius: number]) | constructor / setup | a node/edge graph (weights via a-b:w) |
array(id: new id, vals: string, center: (x, y), [cw: number], [ch: number]) | constructor / setup | a row of value cells in slot boxes |
list(id: new id, vals: string, center: (x, y), [kind: new id], [cw: number], [ch: number]) | constructor / setup | a linked list (singly/doubly/circular) |
stack(id: new id, center: (x, y), [cw: number], [ch: number]) | constructor / setup | a stack (LIFO, grows up) |
queue(id: new id, center: (x, y), [cw: number], [ch: number]) | constructor / setup | a queue (FIFO, grows right) |
hashmap(id: new id, n: number, center: (x, y), [ew: number], [ch: number]) | constructor / setup | n buckets with separate chaining |
pointer(id: new id, arr: id or tag, slot: number, [label: string]) | constructor / setup | an index caret under an array slot |
caret(id: new id, at: (x, y), label: string, [dir: new id]) | constructor / setup | a labelled triangle marker |
compare(arr: id or tag, i: number, j: number, [color: colour]) | animation verb | flash the values in two array slots |
pointat(id: id or tag, arr: id or tag, slot: number, [dur: number]) | animation verb | slide an index pointer to a slot |
push(id: id or tag, value: string, [dur: number]) | state-changing verb | push onto a stack |
pop(id: id or tag, [dur: number]) | state-changing verb | pop the top of a stack |
enqueue(id: id or tag, value: string, [dur: number]) | state-changing verb | enqueue at the back |
dequeue(id: id or tag, [dur: number]) | state-changing verb | dequeue from the front |
insert(id: id or tag, after: number, value: string, [dur: number]) | state-changing verb | splice a node into a list |
remove(id: id or tag, index: number, [dur: number]) | state-changing verb | unlink a list node |
put(id: id or tag, key: string, val: string, [dur: number]) | state-changing verb | hash a key into a bucket + chain |
get(id: id or tag, key: string, [dur: number]) | animation verb | scan a bucket’s chain for a key |
bfs(g: id or tag, start: id or tag) | state-changing verb | breadth-first traversal (queue) |
dfs(g: id or tag, start: id or tag) | state-changing verb | depth-first traversal (stack) |
dijkstra(g: id or tag, start: id or tag) | state-changing verb | single-source shortest paths |
Circuit
| API | Kind | What it does |
|---|---|---|
circuit(id: new id, center: (x, y), netlist: string, [unit: number], [labels: number], [build: number]) | constructor / setup | draw a schematic from a netlist and solve it. One component per line — <type> <x1> <y1> <x2> <y2> [key=value …], ground <x> <y>, # comments — placed on an integer grid, and the TOPOLOGY comes from the geometry: points that coincide (or are joined by a wire) are the same node, so there are no node numbers to write. ground is a REFERENCE, not a component: the solver needs one node to measure from, and with no ground line the kit elects the first source’s negative terminal — so a single loop solves identically either way and the symbol is just clutter. Write one when several sources or loops make it worth saying which node is zero. Known types: wire, ground, resistor, capacitor, inductor, dc-voltage, ac-voltage, dc-current, switch, lamp, diode, led, zener, bjt-npn, bjt-pnp, mosfet-n, mosfet-p, opamp (junctions, transistors and op-amps are solved by Newton–Raphson; is=/n= set a junction, vz= a zener’s breakdown, beta= a bipolar’s gain, vth=/kp= a MOSFET, gain=/rail= an op-amp) — plus DIGITAL: and-gate, or-gate, nand-gate, nor-gate, xor-gate, not-gate, logic-input (state=1), logic-output. A gate’s output is a real 5 V / 0 V node, held for one timestep, so a chain settles a gate-delay at a time. SEQUENTIAL: d-flipflop, sr-flipflop, jk-flipflop — four pins each (the two outputs are the derived pins one and two steps below the second coordinate), and each output is separately driven, so Q and Q̄ are real complementary nodes. SWITCHING AND THRESHOLDS: clock (a square wave, value is its frequency in Hz), push-switch (normally OPEN, closed only while pressed), spdt-switch (three pins: common, then a throw on each of the derived pins, state=1 selects the first), ideal-switch (three pins: a control pin that carries no current, then the two terminals it connects — threshold= sets the control voltage it closes above), fuse (rating= amps; it blows once and stays open, and the symbol shows it), comparator (three pins: V+, V−, output — 5 V when V+ is higher), schmitt (vhi=/vlo= its two switching points, which is what stops it chattering on a noisy crossing), polarized-cap (a capacitor that draws its polarity). MORE DEVICES: jfet-n/jfet-p (idss=/vpinch=) — a DEPLETION transistor, conducting at zero gate voltage and pinched off by a negative one, which is the opposite of a MOSFET; relay (coilr=/pullin=) — FOUR pins, a coil and the contacts it closes, two circuits coupled mechanically rather than electrically; vco (fcenter=/gain= hertz per volt, three pins: control, output, ground) — a square wave whose frequency follows its control pin, integrated as a phase so the frequency can move without the waveform jumping. A THREE-pin part still takes two coordinates — its third pin sits one grid step below the second, and a relay’s fourth sits below its FIRST. COMPOSITES, built out of INTERNAL nodes the geometry never names: darlington-npn/darlington-pnp (beta1=) is genuinely two transistors sharing a base–emitter connection, so it carries both the β₁·β₂ gain and the two-junction 1.2 V base drop; transmission-line (z0=/delay=/sections=, FOUR pins — the input pair are the written points, the output pair hang below them) is a ladder of L–C sections, which is what a DELAY actually is, so a step arrives late rather than instantly (more sections = a cleaner edge; the delay itself is exact either way). Values take SI suffixes (1k, 4.7u, 100n). Parts are {id}.c{k} (and {id}.<name> when a line says name=R1), tagged {id} + {id}.parts + {id}.<type>s; junction dots are {id}.n{node}, tagged {id}.nodes; value text is tagged {id}.labels. unit is px per grid step (default 46); labels 0 hides the values. The schematic DRAWS ITSELF by default, one component at a time in netlist order — the netlist is already the order a teacher would draw it in — and each PREFIX of it is really solved, so nothing flows until the loop closes and then everything does at once. build is the share of run spent drawing (default 0.35): it needs a run(id, dur) to play, and build 0 gives the finished schematic at t=0 instead, which is what a film’s opening frame wants. Value labels, junction dots and probes arrive with the component they belong to. Solved by Modified Nodal Analysis, so KCL and KVL hold by construction |
probe(circuit: new id, at: (x, y), [offset: (x, y)]) | constructor / setup | a live readout on a circuit, in either of two forms. Given a GRID POINT a component touches, it reads that node’s VOLTAGE; given the bareword NAME of a part (name=R1 on its netlist line), it reads the CURRENT through it, in amps scaled to a readable unit. Either way it shows a ring where the measurement is taken and a number beside it, and the number follows the transient when you run the circuit. Optional (dx,dy) moves the label. Entities are {id}.v{node} (or {id}.i{name}) + .at, tagged {id} + {id}.probes |
current(circuit: new id, [speed: number], [shape: id or tag], [color: colour], [size: number]) | constructor / setup | how a circuit’s current READS — presentation only, the solver never sees it. speed multiplies every branch by the same factor (1 = the circuit’s own pace, 2 = twice as fast), so a branch carrying twice the current still moves twice as fast: the PROPORTIONALITY is what carries the meaning and scaling it uniformly cannot lie. shape is circle (default), square or diamond; color any palette name or #rrggbb (default gold, the conventional-current colour — cyan is the usual choice for electron flow); size is the radius in px (default 3). Write it after the circuit it restyles |
cut(circuit: new id, part: id or tag, [dur: number]) | state-changing verb | TAKE A COMPONENT OUT of a circuit — and mean it. The circuit that is left is re-analysed and re-solved from scratch, so breaking a loop really does stop the current everywhere, and a meter on another branch falls to zero on its own. Address the part by its netlist name=, or by position as c0, c1, … The component fades out (with its value label), every charge dot goes with it, and each probe moves to what it now reads; the next run(id, dur) replays the circuit that remains. Cutting one wire of a loop leaves the gap where it was, which is the whole demonstration |
reconnect(circuit: new id, part: id or tag, [dur: number]) | state-changing verb | put a cut component back: the same mechanism in the other direction, so the circuit is solved again with it in place and the next run shows the current returning. (Named reconnect, not restore, because restore is already the general savestate rollback verb) |
scope(circuit: new id, at: (x, y), center: (x, y), [w: number], [h: number]) | constructor / setup | the WAVEFORM of a circuit node or part: a trace of the pre-simulated transient with a sweep line that keeps step with run. at is a grid point (that node’s voltage) or the bareword name of a part (its current), exactly like probe. Both axes are labelled with their real extent — the peak the trace reaches and the time window the circuit chose for itself — because a curve without a scale is decoration. Parts are {id}.scope.<what>.curve / .frame / .sweep / .vscale / .tscale (+ .zero when the trace crosses zero), all tagged {id} + {id}.scopes; the trace is a plain polyline, so draw traces it on |
Grid
| API | Kind | What it does |
|---|---|---|
grid(id: new id, [center: (x, y)], [cols: number], [rows: number], [cellsize: number], [seeded_cellsize: number]) | constructor / setup | a 2D cell grid (arg1 a “# . @ *” spec seeds it, else it is the centre) |
neighbors(id: id or tag, mode: string) | constructor / setup | grid connectivity: “4” (default) or “8” (diagonals) |
setcell(id: id or tag, r: number, c: number, kind: id or tag) | constructor / setup | set one cell’s kind (wall/open/start/goal) |
walls(id: id or tag, cells: string) | constructor / setup | batch-set several cells to wall: “r,c r,c …” |
gridbfs(id: id or tag, start: (x, y), goal: (x, y)) | state-changing verb | unweighted BFS over open cells (spatial sibling of bfs) |
gridastar(id: id or tag, start: (x, y), goal: (x, y), [heuristic: id or tag]) | state-changing verb | A* pathfinding with a heuristic (manhattan/euclidean/diagonal) |
evolve(id: id or tag, rule: string) | constructor / setup | pre-simulate one CA generation (“life” or a Golly rulestring) |
collapse(id: id or tag, tileset: string, [seed: number]) | constructor / setup | pre-simulate a seeded Wave-Function-Collapse settling |
Chem
| API | Kind | What it does |
|---|---|---|
structure(id: new id, source: string, [center: (x, y)], [unit: number], [spec: string]) | constructor / setup | a SKELETAL STRUCTURAL FORMULA — the flat drawing a chemist puts on paper — from an MDL structure file’s 2-D depiction coordinates. Every convention is derived from the file, not authored: a carbon is a bare VERTEX, hydrogens on carbon vanish, a heteroatom is lettered with its hydrogens folded in (an oxygen with one explicit H becomes OH, a nitrogen with two becomes NH2), a double bond’s second line leans toward the CROWDED side — which inside a ring is the ring centre, and falls out of the neighbours’ own coordinates without detecting rings — and a bond is a wedge or a hash where the molfile’s fourth bond column records stereochemistry. Bonds stop short of a letter so no line runs under text. unit is PIXELS PER BOND (default 64; a 2-D record is laid out on a 1.0-per-bond grid, so this is literally how big a bond should be). spec takes carbons=1 (letter every carbon too — the explicit style a first lesson uses), hydrogens=1 (draw them as their own vertices instead of folding them in), labels=text|latex (latex TYPESETS the label so a subscript is a real subscript — NH₂ rather than NH2 — and a charge is raised; costs one rasterised image per DISTINCT label, so a molecule with six hydroxyls costs one), color=, record=. Entities: bonds {id}.b{k} (the FILE’s numbering, so it has gaps where C–H bonds were skipped — address {id}.bonds instead), labels {id}.a{i}, tagged {id} + {id}.bonds / {id}.labels / {id}.multibonds / {id}.wedges / {id}.hashes, and every label also by its element ({id}.O, {id}.N) — and by FUNCTIONAL GROUP: {id}.carboxyl, {id}.ester, {id}.hydroxyl, {id}.aromatic and the rest of hydroxyl / carbonyl / carboxyl / aldehyde / ketone / ester / amide / primary_amine / secondary_amine / tertiary_amine / nitro / nitrile / thiol / sulfide / sulfoxide / sulfone / halogen / ether / epoxide / aromatic, detected from the structure itself, so color(asp.carboxyl, crimson) addresses the CHEMISTRY rather than a list of indices. A tag covers the group’s labels AND the bonds inside it, every repeat of a group shares one tag (a sugar’s five hydroxyls colour together), and groups OVERLAP on purpose — a carboxyl is also a carbonyl and a hydroxyl, all three being true of it. Works identically from a file or a SMILES string. NAMES: {id}.name (the everyday word, from the curated asset:molecules/ filename) and {id}.iupac (the systematic name, from the record or generated) are HIDDEN captions under the drawing — show(caf.name); show(caf.iupac); is the nomenclature lesson. A SMILES string or your own file gets {id}.iupac at best and no {id}.name; long names wrap. The captions are tagged {id}.names and NOT {id}, so show({id}) does not reveal them. EVERY atom is addressable as {id}.a{i} even when it carries no letter — a skeletal carbon gets an invisible anchor — so arrow(a, nuc.a0, sub.a1, 62) aims a curly arrow at a carbocation, and {id}.b{k} resolves to a bond’s midpoint. A structure that COULD NOT EXIST is refused rather than drawn — five bonds on a carbon lays out cleanly, so only a valence check catches it; the rule is charge-aware, so [N+](C)(C)(C)C is fine and O(C)(C)C is not. names wrap. These are 2-D entities, so framebox and brace work on them (unlike molecule3), and untraced + stagger { draw({id}.bonds) } writes the formula on bond by bond. Needs the 2-D record — a 3-D conformer flattened is a tangle of crossing bonds, so one is refused with the record_type=2d fix named. Bundled as asset:molecules/<name>-2d.sdf. source ALSO takes a SMILES string in place of a path — structure(e, "CCO") is ethanol — and then the coordinates are COMPUTED, not read: a chain zig-zags at the tetrahedral angle, a ring closes as a regular polygon, a fused ring reflects across the bond it shares, a substituent points radially out of its ring, and an aromatic ring is Kekulé-ised so the alternating double bonds are real bonds. A string is read as SMILES when it does not look like a file (no asset:, no /, no .sdf/.mol), so the two forms never collide. The layout is CHECKED before it is drawn — overlapping atoms, crossing bonds or a stretched bond are REFUSED with the 2-D-file fix named, rather than drawn as a tangle, because a plausible-but-wrong formula is worse than none. Chains, single rings and outward-growing FUSED systems are reliable, and that covers a steroid’s four rings, a substituted phenanthroline and the aromatics; a BRIDGED or caged skeleton (morphine) is what gets refused. SMILES atoms are numbered in WRITTEN order, so CC(=O)O puts its hydroxyl oxygen last and {id}.a4 addresses it |
molecule3(id: new id, path: string, [center: (x, y, z)], [scale: number], [style: id or tag], [record: number]) | constructor / setup | a REAL MOLECULE from an MDL structure file — .sdf (what a PubChem “Download → SDF” gives you) or .mol, as an asset: URI or a path. Nothing about the shape is authored: the atom coordinates are the file’s, in Ångströms, so a bond angle on screen is the one someone computed. Atoms are spheres coloured by the CPK/Jmol convention and sized by covalent radius; bonds are sticks, with a double bond drawn as two parallel lines and a triple as three. center defaults to the origin and the molecule is centred on its own centroid; scale is world units per Ångström (default 1, which puts a small molecule at the few-units scale the rest of the 3D kit works at); style is ball (default), spacefill (full radii, no bonds — the shape the molecule presents to the world) or wireframe (bonds only); record picks one molecule out of a multi-record SDF, counting from 1. Atoms are {id}.a{i} and bonds {id}.b{k} ({id}.b{k}.{n} for each line of a multiple bond), tagged {id} + {id}.atoms / {id}.bonds / {id}.multibonds — and every atom is ALSO tagged by its element ({id}.O, {id}.C), so color(caf.N, cyan) addresses the chemistry rather than an index. Bundled: water, methane, ammonia, benzene, carbon-dioxide under asset:molecules/. A V3000 file is refused with the way to convert it |
balance(id: new id, center: (x, y), equation: string, [size: number]) | constructor / setup | solve a chemical equation’s coefficients and draw the SKELETON: balance(rx, (x,y), “Fe + O2 -> Fe2O3”). One column per species and one row per element makes a matrix whose null space IS the set of balanced equations, so the coefficients are found by exact rational elimination (never floating point) and reduced to the smallest whole numbers - 4 Fe + 3 O2 -> 2 Fe2O3. Formulae read as written, with nested groups Ca(OH)2 / Al2(SO4)3 and hydrates CuSO4.5H2O, and every symbol is checked against the periodic table (Co is cobalt, CO is carbon monoxide). An equation that cannot balance says which: an element that only appears on one side, two reactions written as one, or something on the wrong side of the arrow. The equation is an ordinary LaTeX image at {id}; solve(id) writes the coefficients in |
tally(id: id or tag, center: (x, y), [width: number], [row: number], [size: number]) | constructor / setup | the conservation table beside a balance: one row per element, atoms on the left against atoms on the right, red while they disagree and lime when they match. Counts are live counters that solve updates at every step, so a half-finished balance shows exactly the mismatch a student would be looking at. Draws {id}.tally.e{k} + {id}.tally.l{k}/{id}.tally.r{k}, all tagged {id}.tally |
solve(id: id or tag, [dur: number]) | state-changing verb | write a balance’s coefficients in, one at a time, with the tally keeping score. Each step is a rewrite, so a coefficient slides in beside a formula that stays exactly where it is - the equation is never retyped or re-laid-out. dur is the total for all the steps (default 2.4). An equation that needs no coefficients still plays; it simply has nothing to add |
lewis(id: new id, formula: string, center: (x, y), [unit: number], [size: number]) | constructor / setup | a Lewis structure WORKED from a formula: lewis(x, “NO3-”) counts the valence electrons, picks the central atom (least electronegative that can hold more than one bond), spends two on each bond, completes the octets from the outside in, promotes a lone pair to a pi bond while the centre is short (or while it tidies the formal charges, where period 3+ may expand), and computes the formal charges - which must sum to the ion’s charge or it refuses. Charges beyond +-1 want a separator: “SO4 2-” or “CO3^2-”, since NO3- is nitrate rather than NO with three minuses. Electron-deficient centres stay deficient (BF3/BeCl2/AlCl3 keep single bonds and no charges, because a halogen does not pi-donate) while carbon still insists on its octet (CO is a triple bond with C- and O+). Oxyacids put their hydrogens on oxygen and complete those oxygens before the centre, so H2SO4 comes out neutral with two S=O. Declines what it cannot honestly draw: an ODD electron count (NO, NO2 - radicals), transition metals (no group number to count), and any skeleton needing TWO central atoms (C2H6, H2O2, CH3OH - a formula cannot say H-O-O-H rather than H2O-O). Draws {id}.a{i} letters + {id}.bonds lines (one per pair, so a double is two lines) + {id}.pairs dots + {id}.charges + an {id}.count electron total + {id}.formula, which labels the structure with what it is OF (NO3- prints as NO3- with the digit down and the charge up). The NAME is not the kit’s to give: nitrate is a fact about usage, so a scene says that |
octet(id: id or tag, [dur: number]) | animation verb | play the working of a lewis structure in the order it is taught: the electron count, then the sigma bonds one at a time, then the lone pairs from the outside in, then the pair that SWINGS IN to finish the centre’s octet, then the formal charges that fall out of it. The step that needs the animation is the fourth one |
resonate(id: id or tag, [dur: number], [cycles: number]) | animation verb | move a lewis structure’s extra bonds round its equivalent neighbours - the double bond hopping between the three oxygens of nitrate, or the two of ozone - with the lone pairs and formal charges following it, because they are the same bookkeeping. The claim being made is that the molecule is NONE of the drawings and the average of all of them, which is only sayable in motion. Refuses when there is only one arrangement |
levels(id: new id, center: (x, y), [w: number], [h: number], [nmax: number], [Z: number]) | constructor / setup | the energy-level diagram of a ONE-ELECTRON atom (H, He+, Li2+ …): E_n = -13.606 Z^2/n^2 eV, so the rungs are placed at their energies and crowd towards zero as n grows. Every transition’s photon is computed with lambda = hc/dE. Restricted to one electron on purpose - the Rydberg formula is exact there and simply wrong for anything with electron-electron repulsion. Draws {id}.n{k} rungs (tagged {id}.rungs) + labels + {id}.electron + {id}.photon + {id}.readout |
emission(id: new id, levels: id or tag, center: (x, y), [w: number], [h: number], [from: number]) | constructor / setup | the emission spectrum those levels produce: one line per VISIBLE transition, standing at its own wavelength, and COLOURED FROM that wavelength rather than chosen - so hydrogen’s Balmer alpha is red at 656 nm because the arithmetic put it there. Ultraviolet and infrared transitions are computed but not drawn, because they are not colours. Draws {id}.strip + {id}.line{k} (tagged {id}.lines) + wavelength labels |
drop(id: id or tag, from: number, to: number, [dur: number]) | animation verb | an electron falls from one level to another and emits the photon that energy difference is worth: the electron slides down the diagram, a photon of the computed COLOUR flies off, the matching spectral line flares, and the readout gives n, the energy in eV and the wavelength in nm. Emission only - the second level must be the lower one |
cell(id: new id, metals: string, center: (x, y), [w: number], [h: number], [spec: string]) | constructor / setup | a galvanic cell that works out its own polarity: give it two metals (“Zn|Cu”) and the more positive standard reduction potential becomes the CATHODE, so “Zn|Cu” and “Cu|Zn” are the same cell and both read +1.10 V. E(cell) = E(cathode) - E(anode), I = E/R across the external resistor, and the half-equations are written from the same decision. spec is a “key=value” string: resistance (ohms, default 10), carriers (electrons drawn, default 8). Draws beakers, electrodes, salt bridge, wire, a voltmeter reading the computed EMF, plus {id}.electrons and {id}.ions; the two counter captions carry {id}.captions rather than {id}, so show(id) is the bench alone |
discharge(id: id or tag, [dur: number], [minutes: number]) | animation verb | let a cell run: electrons cross the wire and ions cross the salt bridge at a rate set by the current, while the readouts count the charge (Q = It) and the anode’s mass loss (Faraday: m = MQ/nF). minutes is how long the cell is being run for, not how long the shot is - a Daniell cell through 10 ohms for half an hour is 198 C and 67 mg of zinc, and that is what it says rather than an exaggerated electrode |
lattice(id: new id, formula: string, center: (x, y), [cols: number], [rows: number], [unit: number]) | constructor / setup | an ionic lattice as an alternating grid, sized by real ionic radii (chloride really is much bigger than sodium). 1:1 salts only, since that is what a checkerboard keeps honest. Counts each ion’s COORDINATION - 2 at a corner, 3 on an edge, 4 inside - which is the order dissolve uses. Where a data book has the numbers it also prints the energy account: lattice enthalpy against the hydration enthalpies, and the small positive dH that explains why dissolving salt is entropy-driven. Draws {id}.i{k} ions (tagged {id}.ions) + labels + waiting {id}.water; the spoken-word readout carries {id}.captions rather than {id}, so show(id) is the crystal alone |
dissolve(id: id or tag, [dur: number], [count: number]) | animation verb | the crystal comes apart, CORNERS FIRST - ions leave in order of how few neighbours hold them, which is why a crystal erodes inwards. Each one leaves inside a hydration shell whose water molecules are turned by the sign of its charge: oxygen towards a cation, hydrogens towards an anion. count is how many ions leave |
newman(id: new id, source: string, center: (x, y), [unit: number], [labels: number]) | constructor / setup | a Newman projection down a molecule’s central rotatable bond (chosen for you: the single bond with the most on both sides), with its torsional energy profile COMPUTED - the real geometry is rotated degree by degree and scored with a threefold torsional term plus Lennard-Jones repulsion across the bond. Butane comes out with staggered wells, anti lowest and the methyls eclipsing worst. It is a RIGID scan, so peaks come out high (butane’s syn barrier lands in the fifties against a measured 19-21) - the order and the shape are the lesson. Draws {id}.circle + {id}.front + {id}.back arms + {id}.readout |
profile(id: new id, torsion: id or tag, center: (x, y), [w: number], [h: number]) | constructor / setup | the energy-against-dihedral curve for a newman, in kJ/mol above the lowest conformer, with a marker that rides it while twist turns the bond. Ticks every 60 degrees, which is where staggered and eclipsed alternate |
twist(id: id or tag, angle: number, [dur: number]) | state-changing verb | turn a newman to a dihedral angle, the short way round, with the profile marker climbing or falling to the energy that arrangement costs. The readout names it the way a chemist does - anti, gauche, eclipsed - and gives the energy. State carries forward, so a chain of twists walks the curve |
vibration(id: new id, source: string, center: (x, y), [unit: number], [labels: number]) | constructor / setup | a molecule drawn flat with its NORMAL MODES computed from real geometry: masses from the periodic table, a harmonic force field of bond, angle and out-of-plane springs with tabulated force constants, and the eigenvectors of the mass-weighted Hessian. Gives the textbook set - 3N-6 modes, or 3N-5 when the molecule is linear - with wavenumbers in cm^-1 that land near the measured ones (H-Cl 2886, CO2 asymmetric stretch 2374 against 2349). Needs the 3-D record, not a flat depiction, because the shape is the physics. Draws {id}.b{k} bonds + {id}.a{i} atoms (tagged {id}.atoms) + {id}.l{i} labels + a {id}.readout that vibrate fills in |
vibrate(id: id or tag, mode: number, [dur: number], [amp: number], [cycles: number]) | animation verb | animate one normal mode of a vibration, numbered from the lowest wavenumber up. The atoms move along the mode’s own eigenvector, so a symmetric stretch really is symmetric; amp scales the displacement (0.28 of a bond by default) and cycles sets how many oscillations fit in dur. Sets {id}.readout to the wavenumber, whether it is a stretch or a bend (decided by what the motion does to bond lengths against bond angles), and whether it is infrared active |
irspectrum(id: new id, molecule: id or tag, center: (x, y), [w: number], [h: number], [size: number]) | constructor / setup | the infrared spectrum a molecule’s modes imply, drawn high wavenumber to low as a spectrum is: a Lorentzian band per ACTIVE mode with its wavenumber labelled, and a coral marker where a SILENT one would have been. A mode is active only if it changes the dipole moment - carbon dioxide’s symmetric stretch does not, so it has no peak however hard the bond is vibrating, and that cancellation is computed from the mode’s own displacements rather than asserted. Draws {id}.axis + {id}.curve + {id}.peaks + {id}.silent |
supply(id: id or tag, amounts: string) | constructor / setup | what you are GIVEN of each reactant, for a balance: supply(rx, “Fe=10g O2=5g”). Values are grams unless written mol (Fe=0.18mol), converted with STANDARD atomic weights - the ones you weigh with, not the monoisotopic masses a mass spectrum uses. Every reactant needs an amount, because the question is which of them runs out first. Solving it is one line: batches = moles / coefficient, and the smallest wins - which is why the limiting reagent is so often NOT the one you have least of |
limiting(id: id or tag, center: (x, y), [width: number], [row: number], [size: number]) | constructor / setup | the limiting-reagent view for a balance that has a supply: one bar per reactant showing how far the reaction could get on that reactant alone (moles / coefficient), the shortest marked runs out first, then what comes out - each product’s mass, the excess left standing, and a mass-in against mass-out check that has to agree. Everything starts blank and arrives during react. Draws {id}.limit.b{k} bars + {id}.limit.n{k} / .y{p} / .spare / .in / .out counters, tagged {id}.limit |
react(id: id or tag, [dur: number]) | animation verb | run the supplied amounts through a balanced equation: the bars grow to how far each reactant alone could take it, the shortest is named as the limiting reagent, and the yields, the leftover and the mass check count up. Needs supply and limiting first |
Brand
| API | Kind | What it does |
|---|---|---|
banner(id: new id, center: (x, y), [scale: number]) | constructor / setup | the manic logo/banner |
watermark(id: new id, [at: (x, y)], [text: string]) | constructor / setup | a screen-fixed watermark; omit the point for responsive bottom-right placement or pass an exact point |
Stats
| API | Kind | What it does |
|---|---|---|
histogram(id: new id, center: (x, y), data: string, [bins: number], [width: number], [height: number], [color: colour]) | constructor / setup | bin a dataset into bars — the shape of the data |
summary(id: new id, center: (x, y), data: string, [width: number], [color: colour]) | constructor / setup | describe a dataset: mean/median/mode markers, spread, and readouts |
correlation(id: new id, center: (x, y), unit: number, data: string, [color: colour]) | constructor / setup | scatter + best-fit line + the Pearson correlation r |
skew(id: new id, center: (x, y), data: string, [bins: number], [width: number], [height: number], [color: colour]) | constructor / setup | a histogram labelled with its skewness (left / right / symmetric) |
boxplot(id: new id, center: (x, y), data: string, [width: number], [color: colour]) | constructor / setup | five-number summary as a box-and-whisker (box = IQR) |
hypothesis(id: new id, center: (x, y), z: number, [alpha: number], [unit: number]) | constructor / setup | a two-tailed significance test: p-value as shaded normal tails |
covariance(id: new id, center: (x, y), unit: number, data: string, [color: colour]) | constructor / setup | covariance as signed-area rectangles about the mean cross |
bayes(id: new id, center: (x, y), heads: number, tails: number, [width: number], [height: number]) | constructor / setup | Bayesian updating: prior + likelihood -> posterior for a coin’s bias |
distribution(id: new id, center: (x, y), kind: string, a: number, [b: number], [color: colour]) | constructor / setup | a named distribution: uniform / exponential / maxwell / binomial / poisson |
confidence(id: new id, center: (x, y), mean: number, sd: number, n: number, [level: number], [width: number]) | constructor / setup | a confidence interval for a mean: estimate + z*sd/sqrt(n) error bar |
montecarlo(id: new id, center: (x, y), points: number, [seed: number], [size: number]) | constructor / setup | estimate pi by darts: random points in a square vs the circle |
randomwalk(id: new id, center: (x, y), steps: number, [seed: number], [scale: number]) | constructor / setup | a 2D random walk path from the centre |
bellcurve(id: new id, center: (x, y), mu: number, sigma: number, [unit: number], [color: colour]) | constructor / setup | the normal/Gaussian bell curve with the 68-95-99.7 rule shaded |
gaussian(id: new id, center: (x, y), mu: number, sigma: number, [unit: number], [color: colour]) | constructor / setup | the normal/Gaussian bell curve with the 68-95-99.7 rule shaded |
lln(id: new id, center: (x, y), trials: number, [seed: number], [width: number], [height: number]) | constructor / setup | Law of Large Numbers: a running proportion settling onto the truth |
clt(id: new id, center: (x, y), samplesize: number, trials: number, [seed: number], [width: number], [height: number], [color: colour]) | constructor / setup | Central Limit Theorem: sample means of dice pile into a bell |
Physics
| API | Kind | What it does |
|---|---|---|
freekick(id: new id, center: (x, y), speed: number, angle: number, spin: number, [scale: number], [steps: number]) | constructor / setup | an RK4 free-kick trajectory under drag + the Magnus force (sidespin curves it); draw {id}, run(id) flies the ball |
pendulum(id: new id, [center: (x, y)], [length: number], [angle0: number], [unit: number], [damping: number]) | constructor / setup | a swinging pendulum (pre-simulated); animate with swing(id) |
spring(id: new id, [center: (x, y)], [stiffness: number], [x0: number], [unit: number], [damping: number], [v0: number]) | constructor / setup | a mass on a spring (pre-simulated); animate with run(id) |
doublependulum(id: new id, [center: (x, y)], [angle1: number], [angle2: number], [unit: number]) | constructor / setup | the chaotic double pendulum (pre-simulated); animate with run(id) |
springpendulum(id: new id, [center: (x, y)], [angle0: number], [stretch0: number], [unit: number], [damping: number]) | constructor / setup | an elastic pendulum (swings + bounces); animate with run(id) |
kapitza(id: new id, [center: (x, y)], [angle0: number], [vibeamp: number], [unit: number]) | constructor / setup | a Kapitza pendulum — fast vibration stabilises the inverted position |
cartpendulum(id: new id, [center: (x, y)], [angle0: number], [unit: number]) | constructor / setup | a pendulum on a spring-mounted cart (control-theory system) |
comparependulum(id: new id, [center: (x, y)], [angle0: number], [unit: number]) | constructor / setup | two chaotic pendulums a hair apart — sensitive dependence |
verticalspring(id: new id, [center: (x, y)], [stretch0: number], [unit: number], [damping: number]) | constructor / setup | a mass bobbing on a vertical spring under gravity |
springincline(id: new id, [center: (x, y)], [angle: number], [unit: number], [damping: number]) | constructor / setup | a mass on a spring on an inclined plane |
bungee(id: new id, [center: (x, y)], [unit: number], [damping: number]) | constructor / setup | a bungee jump — free-fall then a one-sided elastic cord |
resonance(id: new id, [center: (x, y)], [drivefreq: number], [unit: number], [damping: number]) | constructor / setup | a driven spring — amplitude peaks near the natural frequency |
doublespring(id: new id, [center: (x, y)], [unit: number]) | constructor / setup | two masses coupled by springs — beating / normal modes |
seriesparallel(id: new id, [center: (x, y)], [unit: number]) | constructor / setup | springs in series vs parallel — soft/slow vs stiff/fast |
carsuspension(id: new id, [center: (x, y)], [unit: number]) | constructor / setup | a quarter-car riding a scrolling road (bump/washboard/pothole) |
piston(id: new id, [center: (x, y)], [rpm: number], [unit: number]) | constructor / setup | an engine piston — a spinning crank drives a slider in a cylinder |
molecule(id: new id, [center: (x, y)], [atoms: number], [unit: number]) | constructor / setup | N atoms bonded by springs, vibrating about their shape |
robotarm(id: new id, [center: (x, y)], [mode: number], [unit: number]) | constructor / setup | a two-link robot arm tracking a target by inverse kinematics (mode 1=circle, 2=figure-8, 0=fixed) |
pulley(id: new id, [center: (x, y)], [m1: number], [m2: number], [unit: number]) | constructor / setup | a vertical Atwood machine — two masses over one pulley |
pulleyscale(id: new id, [center: (x, y)], [m1: number], [m2: number], [unit: number]) | constructor / setup | an Atwood machine with an in-line spring scale reading the rope tension |
blocktackle(id: new id, [center: (x, y)], [load: number], [effort: number], [strands: number], [unit: number]) | constructor / setup | a compound pulley (block & tackle): N strands give a mechanical advantage of N |
compoundpulley(id: new id, [center: (x, y)], [mA: number], [mB: number], [mC: number], [unit: number]) | constructor / setup | a compound pulley: a fixed pulley + a movable pulley with three masses A, B, C (static when mA = mB+mC) |
ramp(id: new id, [center: (x, y)], [angle: number], [mass: number], [applied: number], [unit: number]) | constructor / setup | a block sliding on an inclined plane with friction |
dropmass(id: new id, [center: (x, y)], [dropheight: number], [unit: number]) | constructor / setup | a mass dropped onto a spring-block — inelastic collision, energy lost |
inclinepulley(id: new id, [center: (x, y)], [angle: number], [m1: number], [m2: number], [unit: number]) | constructor / setup | a block on an incline tied over a top pulley to a hanging mass (incline-Atwood) |
doubleincline(id: new id, [center: (x, y)], [angle1: number], [angle2: number], [m1: number], [m2: number], [unit: number]) | constructor / setup | two blocks on a wedge’s two slopes, tied over an apex pulley (right slope rough) |
inclinebumper(id: new id, [center: (x, y)], [angle: number], [mass: number], [stiffness: number], [unit: number]) | constructor / setup | a block slides down an incline into a spring bumper at the base, then bounces back |
springchain(id: new id, [center: (x, y)], [angle: number], [unit: number]) | constructor / setup | three blocks joined by two springs on an incline — coupled oscillators / normal modes |
looptrack(id: new id, [center: (x, y)], [radius: number], [height: number], [unit: number]) | constructor / setup | a ball rolls down a ramp and around a vertical loop-the-loop (curved track) |
collideblocks(id: new id, [center: (x, y)], [m1: number], [m2: number], [restitution: number], [unit: number]) | constructor / setup | two blocks collide on a frictionless track with elastic walls (restitution e) |
bulletblock(id: new id, [center: (x, y)], [bulletmass: number], [speed: number], [blockmass: number], [unit: number]) | constructor / setup | a bullet fired into a block embeds (perfectly inelastic — most kinetic energy lost) |
newtonscradle(id: new id, [center: (x, y)], [balls: number], [pulled: number]) | constructor / setup | Newton’s cradle — pull N balls, N swing out (event-driven elastic collisions) |
gas(id: new id, [center: (x, y)], [w: number], [h: number], [count: number], [spec: string]) | constructor / setup | N hard discs bouncing elastically in a box — a general particle gas, not a chemistry builtin. Speeds are drawn from the 2-D Maxwell-Boltzmann distribution (or start=equal, to watch collisions PRODUCE that distribution), and energy is conserved by the bounces. spec is a “key=value” string: temperature (kT, the energy unit), radius (px), mass, scale (px per length unit - the density/liveliness knob), dt, steps (frames of trajectory), seed, start=maxwell|equal. Lays out {id}.box + {id}.p{i}, tagged {id} and {id}.particles; animate with run(id, secs). Add species to label populations and rule to make collisions change them; timegraph(id, ...) then draws the populations over time |
species(id: id or tag, name: new id, [weight: number], [colour: colour]) | constructor / setup | label a sub-population of a gas: species(g, A, 0.5, cyan) starts half the particles as A. Weights are relative, and a weight of 0 (or the short form species(g, C, gold)) is a population that starts EMPTY - a product waiting to be made. Colouring the species colours its particles, so the mix is readable at t=0 |
rule(id: id or tag, rule: string) | constructor / setup | a collision-triggered transition in a gas, written the way it goes on a board: rule(g, “A + B -> C + C when energy > 3”). The threshold is the relative kinetic energy along the line of centres in the SAME unit as temperature, so Ea/kT is the Boltzmann exponent - raise the temperature and more collisions clear the barrier, on their own. Drop the when clause and every meeting counts, which is how the same mechanism becomes an infection (“S + I -> I”) or a chain reaction. One product name is short for both participants becoming it; products need no prior species declaration |
speeds(id: id or tag, center: (x, y), [w: number], [h: number], [bins: number], [smooth: number], [vmax: number]) | constructor / setup | a LIVE histogram of a gas’s own speeds, with the exact Maxwell-Boltzmann prediction drawn over it on the same scale. The bars are ordinary rectangles that run(id) grows and shrinks from the same trajectory that moves the particles, so the distribution is MEASURED, not illustrated - start the gas with start=equal and watch collisions build the bell out of a single spike. smooth is how many frames each bar averages (default 9, a stated running average over a noisy small sample), and vmax sets the top of the speed axis explicitly (default 3.3 sigma) so two gases at different temperatures can share one axis. Draws {id}.speeds.axis + {id}.speeds.b{k} (tagged {id}.speeds.bars) + {id}.speeds.mb, all tagged {id}.speeds |
dominos(id: new id, [center: (x, y)], [count: number], [height: number], [thickness: number], [spacing: number], [unit: number], [transfer: number], [push: number]) | constructor / setup | a row of dominos toppling as a wave — rigid slabs pivoting on their base edge; lengths in MILLIMETRES (height 45, thickness 7.5438, spacing 9.38 are real domino numbers), unit = px per mm, transfer = 0-1 fraction of angular speed handed on at each impact, push = the first domino’s nudge (rad/s). The wave speed is not a parameter: it emerges from spacing/height/thickness/transfer, so wide spacing kills the chain. Lays out {id}.ground + {id}.d{i}, tagged {id}; animate with run(id) |
dominopath(id: new id, center: (x, y), sx: number, sy: number, x(t): string, y(t): string, [count: number], [tdomain: (x, y)], [height: number], [thickness: number], [unit: number], [transfer: number], [push: number]) | constructor / setup | dominos standing along ANY parametric curve, toppling as a wave that follows the shape - seen from ABOVE, so a standing domino is a short bar and a fallen one is a long bar lying forward (footprint = thicknesscos + heightsin). Curve written like param: x(t)/y(t) through (cx,cy) + sx/sy over tdomain (default (0,tau)) - a spiral, heart or lissajous becomes a domino run. count SETS the spacing (equal arc length), so more dominos = tighter gaps = slower wave; overlapping or unreachable spacing is a clear error. Same slab physics as dominos. Lays out {id}.path + {id}.d{i}, tagged {id}; stagger a show over {id}.d{i} to place them one by one, then run(id) |
stringwave(id: new id, [center: (x, y)], [width: number], [amp: number], [pluck: number]) | constructor / setup | a wave on a plucked string (N masses on springs, fixed ends) — the wave equation |
raft(id: new id, [center: (x, y)], [personmass: number], [raftmass: number], [unit: number]) | constructor / setup | a person walking on a floating raft — centre of mass stays fixed |
brachistochrone(id: new id, [center: (x, y)], [unit: number]) | constructor / setup | four beads race down different curves under gravity — the cycloid wins |
run(id: id or tag, [dur_or_gens: number], [dur: number]) | animation verb | replay a sim’s motion over [dur] s (or a grid’s frames: run(grid, [gens], [dur])) |
swing(id: id or tag, [dur: number]) | animation verb | replay a pendulum’s motion over [dur] seconds (alias of run) |
forces(id: id or tag, [dur: number]) | animation verb | reveal a sim’s free-body force diagram (ramp: gravity, normal, friction, a) |
phase(id: id or tag, center: (x, y), [size: number]) | constructor / setup | a sim’s phase portrait (e.g. θ vs ω); animates with swing |
well(id: id or tag, center: (x, y), [size: number]) | constructor / setup | a sim’s potential-energy well with the body as a rolling ball |
timegraph(id: id or tag, center: (x, y), [size: number]) | constructor / setup | a sim’s phase variables as curves over time (with a sweep line) |
energygraph(id: id or tag, center: (x, y), [size: number]) | constructor / setup | KE/PE/total energy as curves over time (with a sweep line) |
Rubik
| API | Kind | What it does |
|---|---|---|
cube(id: new id, n: number, center: (x, y), [size: number], [view: new id], [state: string], [scramble: number]) | constructor / setup | a Rubik’s cube of ANY size (n = 2..9) with one view of it. view = net (the unfolded 4Nx3N cross, default) or trefoil (every sticker a dot on three families of rings, so a turn slides them along their ring and the permutation is visible travelling between faces). size = sticker pitch (net) or overall span (trefoil). state = “solved” (default), a facelet string in face order U R F D L B (a scanned or solver state pastes straight in), or a scramble in move notation like “R U R’ F2”. Stickers are ordinary entities {id}.s{i} tagged {id} + {id}.stickers + their face ({id}.U … {id}.B), so show/fade/color/pulse/framebox all work; being self-contained it also sweeps over n |
rubik3(id: new id, n: number, [size: number], [state: string], [scramble: number]) | constructor / setup | the same cube as an OBJECT in 3-D: one thin plate per sticker just proud of the surface, so the state model and moves are the ones the flat views use. A turn rotates that layer’s plates about the cube’s axis. size = the cube’s edge in world units (default 2); frame it with camera3 and spin it with orbit3. Plates are ordinary 3-D entities {id}.s{i} tagged {id} + {id}.stickers + their face. state takes the same spellings as cube |
moves(id: id or tag, sequence: string, [dur: number], [ease: easing]) | state-changing verb | apply a move sequence to a cube, animated: “R U R’ U’”. Notation is the cuber’s own, so scrambles and solutions paste straight in - outer turns R R’ R2, wide Rw/3Rw/lowercase r, inner slices 2R..ceil(n/2)R, whole-cube rotations x y z, and the 3x3 middles M E S. Every intermediate state is computed at build time, so it scrubs exactly and consecutive calls continue from where the last left off. This kit animates moves; it does not search for them - feed a solver’s solution to return to solved |
Machine learning
| API | Kind | What it does |
|---|---|---|
network(id: new id, center: (x, y), layers: string, activations: string, [width: number], [height: number], [seed: number]) | constructor / setup | a deterministic feed-forward neural network with responsive layered layout and stable node/edge tags |
activation(id: new id, center: (x, y), function: id or tag, [width: number], [height: number]) | constructor / setup | a truthful plot of linear, ReLU, sigmoid, or tanh |
forward(network: id or tag, input: string, [dur: number], [ease: easing]) | state-changing verb | compute and progressively reveal one feed-forward pass with real activations and output values |
feed(network: id or tag, image: id or tag, [dur: number], [ease: easing]) | state-changing verb | the image->input bridge: flatten a tensor/image into the network input, draw connector lines into the input nodes, and run the forward pass (tensor cell count must equal the input-layer width) |
loss(network: id or tag, target: string, [kind: id or tag], [dur: number], [ease: easing]) | state-changing verb | compare the latest network output with a target using cross-entropy or mean-squared error |
backward(network: id or tag, [dur: number], [ease: easing]) | state-changing verb | compute exact reverse-mode gradients and reveal them from output to input |
update(network: id or tag, [learning_rate: number], [dur: number], [ease: easing]) | state-changing verb | apply one gradient-descent parameter update and recompute the prediction and loss |
checkpoint(id: new id, network: id or tag) | state-changing verb | save one network’s exact parameters, prediction, target, and loss for a later rollback |
restore(target: id or tag, [checkpoint: id or tag], [dur: number], [ease: easing]) | state-changing verb | restore(target, …): a network form restore(network, checkpoint, [dur], [ease]) exactly rolls back a checkpointed network state; the general form restore(id, [dur], [ease]) animates ANY entity that was savestated back to its snapshot (pos/scale/rotation/colour/opacity) |
tensor(id: new id, center: (x, y), values: string, [cell: number], [color: colour]) | constructor / setup | a finite numeric grid; semicolons separate rows and vertical bars separate channels. Draw it instead as pixel-art with #=ink, .=blank, 1-9 = grayscale (a # anywhere switches to art mode; whitespace is ignored) |
digit(id: new id, center: (x, y), digit: string, [cell: number], [color: colour]) | constructor / setup | a stylised handwritten digit 0-9 as a 12x12 pixel-art tensor (144 cells), ready to feed into a 144-input network |
kernel(id: new id, center: (x, y), values: string, [cell: number], [color: colour]) | constructor / setup | a finite convolution kernel with one grid per input channel |
convolve(id: new id, input: id or tag, kernel: id or tag, center: (x, y), [stride: number], [padding: number], [bias: number], [activation: id or tag], [cell: number]) | constructor / setup | compute a feature map from an input tensor and kernel with validated stride, padding, bias, and activation |
pool(id: new id, input: id or tag, center: (x, y), kind: id or tag, [window: number], [stride: number], [padding: number], [cell: number]) | constructor / setup | compute deterministic max or average pooling independently across tensor channels |
scan(output: id or tag, [dur: number], [ease: easing]) | state-changing verb | coordinate the receptive field, operator, arithmetic, and destination cell of a convolution or pool |
tokenize(id: new id, center: (x, y), text: string, [mode: id or tag], [width: number]) | constructor / setup | split text into a small deterministic token sequence using authored, word, or character boundaries |
embedding(id: new id, tokens: id or tag, center: (x, y), vectors: string, [position: id or tag], [width: number], [height: number]) | constructor / setup | turn a token sequence into explicit or seeded educational vectors and add sinusoidal or no positional encoding |
transformer(id: new id, embedding: id or tag, center: (x, y), config: string, [width: number], [height: number]) | constructor / setup | compute and draw a complete deterministic transformer block from an ML5 embedding and a compact heads/mask/MLP/norm/dropout specification |
encode(transformer: id or tag, [dur: number], [ease: easing]) | state-changing verb | reveal a transformer block through heads, masking, concatenation, residuals, normalization, MLP, dropout, and output |
logits(id: new id, transformer: id or tag, token: number, center: (x, y), labels: string, [temperature: number], [width: number], [height: number], [seed: number]) | constructor / setup | project one transformer hidden row into an authored educational vocabulary and compute the full temperature-scaled softmax |
sample(logits: id or tag, strategy: string, [dur: number], [ease: easing]) | state-changing verb | filter, renormalize, and deterministically select from a logits view using greedy, categorical, top-k, or top-p decoding |
attention(id: new id, center: (x, y), tokens: string, embeddings: string, [width: number], [height: number], [seed: number]) | constructor / setup | compute and draw one deterministic scaled dot-product self-attention head from explicit token embeddings |
attend(attention: id or tag, token: number, [dur: number], [ease: easing]) | state-changing verb | focus one 1-based query token and reveal its Q/K matches, softmax row, weighted V mix, and residual lane |
topk(id: new id, attention: id or tag, token: number, center: (x, y), labels: string, [k: number], [width: number], [height: number], [seed: number]) | constructor / setup | project one attention residual into an authored candidate vocabulary and draw the exact top-k softmax probabilities |
Optics
| API | Kind | What it does |
|---|---|---|
refract(id: new id, [center: (x, y)], [n1: number], [n2: number], [angle: number]) | constructor / setup | a light ray bending across a boundary (Snell’s law); run(id) sweeps the angle, showing total internal reflection |
lens(id: new id, [center: (x, y)], [focal: number], [aperture: number]) | constructor / setup | a converging lens focusing parallel rays to a focal point; run(id) sweeps the focal length so the focus slides |
prism(id: new id, [center: (x, y)], [glass: string]) | constructor / setup | white light splitting into a spectrum through a prism (real Sellmeier dispersion); run(id) sweeps the incidence angle |
achromat(id: new id, [center: (x, y)], [aperture: number]) | constructor / setup | chromatic aberration (red & blue focus apart) and its fix; run(id) sweeps in the achromatic doublet, merging the foci |
lenssystem(id: new id, [center: (x, y)], [preset: string], [object: number]) | constructor / setup | a real multi-element lens ray-traced through its spherical/aspheric surfaces (named preset OR a custom prescription string); draw(id.rays) sketches rays, run(id) sweeps a focus sensor + spot read-out. Optional finite object distance (px). |
rayfan(id: new id, [center: (x, y)], [preset: string]) | constructor / setup | the ray-fan aberration plot of a lens preset (transverse ray error vs pupil height); draw(id.curve) sketches the spherical-aberration S-curve |
spotdiagram(id: new id, [center: (x, y)], [preset: string]) | constructor / setup | the spot diagram of a lens preset at best focus (rays land in a blur disc — spherical aberration), with an RMS read-out and the ideal point focus |
fieldspot(id: new id, [center: (x, y)], [preset: string], [field: number]) | constructor / setup | the off-axis spot diagram (3-D pupil trace at a field angle) — a coma comet / astigmatic blur off-axis, with an Airy-disk diffraction-limit overlay |
Creator
| API | Kind | What it does |
|---|---|---|
creator(id: new id, spec: string) | constructor / setup | a reusable v2 creator profile: handle/platforms plus name, tagline, logo, palette, footer, CTA and safe-area keys |
socials(id: id or tag, [at: (x, y)]) | constructor / setup | draw the creator profile’s responsive footer; social mode uses normalized native YouTube/X/Instagram/TikTok/Facebook/LinkedIn/GitHub/web/email icons |
quiz(id: new id, question: string, [style: string]) | constructor / setup | start a responsive quiz: studio default; optional skin/reveal/layout/density/labels/timer/pace/seconds/motion/safe/accent controls |
option(id: id or tag, text: string, [correct: id or tag]) | constructor / setup | add one of up to six fitted answer cards with stable A–F semantic tags; a trailing correct marks the right one |
timing(…) | constructor / setup | generic named-phase timing controller (optional position) or quiz-specific pace/phase configuration; use generic controllers with timed/during |
timerstyle(…) | constructor / setup | style a quiz or generic timing controller: optional generic position plus native look, number, direction, size, colours, label and finish |
safezone(id: new id, [inset: number]) | constructor / setup | a responsive safe-area guide; optional numeric inset or shorts/reels/tiktok/clean profile |
countdown(id: new id, [at: (x, y)], [secs: number], [style: string]) | constructor / setup | a standalone Timing v2 widget sharing the quiz timer looks and style controls; play with run(id, secs) |
figure(target: id or tag, [center: (x, y)], [size: (x, y)]) | constructor / setup | fit a complete tagged group into the responsive media region, including text/images/equations and live-dependency checks |
explain(quiz: id or tag, text: string, [source: string]) | constructor / setup | attach optional author-supplied answer context and source to a quiz reveal |
endcard(profile: id or tag, [spec: string]) | constructor / setup | build a hidden responsive creator end card; reveal profile.endcard at the final beat |
Fixed language vocabularies
Colours
fg, white, void, bg, black, ink, charcoal, slate, silver, cyan, magenta, pink, accent, lime, green, gold, amber, yellow, red, crimson, orange, blue, azure, teal, turquoise, violet, purple, coral, salmon, indigo, mint, seafoam, dim, gray, grey, panel, rainbow
Easings
linear, smooth, inout, in, out, overshoot, back, bounce, elastic, spring
Named plot functions
sin, cos, tan, asin, arcsin, acos, arccos, atan, arctan, parabola, sq, square, cubic, cube, line, id, identity, abs, exp, sqrt, log, ln, recip, inv, gauss, bell, sinc, sigmoid, logistic, relu, step, heaviside
Canvas presets
16:9, 1080p, 4k, square, portrait, 4:5, 4:3, widescreen, landscape, 720p, fullhd, hd, 2160p, 1:1, 9:16, vertical, story, reel, feed
Templates and aliases
black, mono, plain, terminal, paper, blueprint, shorts, monochrome, blackwhite, black-white, bw, blank, clean, neon, shell, print, light, blue, short, punch
Language keywords
let, for, if, else, def, in, sum, prod, min, max
Reserved variables
w, h, cx, cy, pi, e, tau, inf, infinity
Systems routing and ports
Routing: orthogonal
Ports: auto, left, right, top, bottom
Speech services and curated Cartesia voices
Services: gtts, google, cartesia, elevenlabs, 11labs
Cartesia voices: katie, skylar, jameson, gemma, archie