Mathly Engine
Prism
A language for interactive math lessons.
Prism compiles to the IR that powers Mathly's interactive lesson engine. The compiler runs at seed-time or on the server, and its output is validated data — it never executes code, so it is safe to compile AI-generated source.
The guide
Lessons & Slides
A Prism file is either a bare scene { ... } (one visualization) or a lesson { ... } (a full multi-slide lesson). A slide is a composition: any prose, any callouts, a scene (or two, as linked views), at most one exercise, and any number of goals. Prose, callouts and the scene show up in the order you write them, then the goals, then the exercise. There is no "text slide" vs "quiz slide"; you just include the parts you need.
Exercises
An exercise is the checkable part of a slide — the thing the learner answers. Every exercise shares four optional lines: ask "..." (the prompt), hint "..." (repeatable — a hint ladder), ! "..." (the explanation shown after checking), and skill: "..." (the skill it tests).
Scene & State
A Prism file is exactly one scene <type> { ... } block. Everything else — space config, state, objects, controls, timeline — lives inside it.
Objects
Objects are the visual elements of a scene. Properties go in a trailing { key: value } block — omit it entirely if the object needs no configuration. All objects accept: color, style (solid/dashed/dotted), show:<expr>, width:<number>. Note: curve, rect, circle, polygon, arc, image require plane scenes; a numberline draws point, label, line, vector and brace (see numberline).
Annotations
Marks drawn over a diagram to say what it shows: a span, a length, a slope, an angle, a pointer, a region. They are sized in pixels, so they stay the same size when the axes change, and they take color, show, width and alpha. They work in plane and circuit scenes. A mark sits on the left of its segment as you walk from the first point to the second, so a segment written left to right carries its mark above.
Three dimensions
A scene space3 draws in 3D. It needs a z: [min, max] alongside x and y, and it projects orthographically the way a textbook draws a solid — no perspective, so parallel edges stay parallel and lengths along an axis stay comparable. Axes, arrowheads and unit ticks are drawn for you, and grid numbers the ticks, as on a plane. Point the camera: at a param and the learner can spin the figure, which is the only reliable way to resolve what is in front of what. The 3D objects below are only legal inside a space3 scene, and the 2D ones (curve, rect, circle, ...) are not.
Circuits
A scene circuit is a circuit diagram that actually conducts. Parts sit between two grid points and join wherever their ends meet, so a closed loop of parts is a working circuit. It is solved again after every change: wire colour shows potential (red high, blue low, grey for anything cut off), beads move along every part at a speed set by its current (so they slow down in a branch that carries less and stop in one that carries nothing), lamps fill with the power they take, and meters read live values (in mA or mV when the value is small) with an arrow for a few seconds when a value just went up or down.
Every named part gives you its readings to use in labels, goals and the scene beside it: I_R1 is the current through R1, V_R1 the voltage across it and P_R1 its power, all positive. A node a gives V_a, its potential above the battery's - terminal. With one battery you also get Req, the resistance the battery sees (a figure drawn with emf: 0 still reads it), and short is true while something shorts an ideal battery; the same two come as Req_B and short_B for a battery named B. Readings are worked out, so they can be read but never set.
The compiler checks the wiring: every end has to meet another part, a part that ends in the middle of a wire is an error (split the wire there) unless the two are never on together, which it works out from show: conditions on a bool or a choice (so a picker can swap between any number of layouts that overlap), and the circuit needs a battery.
Magnetic fields
A scene magnet draws magnetic fields to scale and works the field out after every change, the way scene circuit works out currents. Wires, bar magnets and uniform fields are the sources; their fields add up as vectors, so two wires, or a wire in the earth's field, give the real combined picture, neutral point and all.
The scene is flat and drawn to scale like a circuit: no axes, x: and y: just frame it. unit: cm (the default) or unit: m says what one unit of the scene means, so a distance of 5 is 5 cm. lines: 8 is how many field lines each source draws (0 draws none, at most 24). mu: 4 * PI * 1e-7 is the permeability, the default. All of these are written on their own line in the scene, like probe is in a circuit.
A wire is the source you will use most. wire W = (x, y) { I: 3, flow: out } is a long straight wire going through the page, drawn as a circle with a dot (current out of the page) or a cross (into it). Its field is B = mu I / (2 pi d) in circles round it, counter-clockwise seen from the front for flow: out, the right-hand rule. wire W = (x1, y1) -> (x2, y2) { I: 3 } is a long wire lying in the page, current running from the first end to the second; its field points out of the page on its left, looking along the current, and into it on its right, drawn as a grid of dots and crosses that are bigger and closer near the wire. Name every wire. I: is in amps, and I, B, dir, strength and every coordinate can use params, so a slider can move a wire, change a current, or flip the earth's field. flow: can be the name of a choice whose options are "in" and "out", so a picker flips the wire.
Probes give readings you can use in labels, goals and ${} text: B_P is the size of the field at probe P in tesla (from wires and uniform fields, never from a magnet), Bx_P, By_P and Bz_P its components, and B_W_P the part wire W makes alone. They are 1e-7 to 1e-3, so write them with sci(B_P, 2). A goal like when: B_P < 1e-7 asks the student to find the neutral point. Readings are worked out, so they can be read but never set, and they cannot place a source.
Field lines are drawn for each wire through the page and each magnet, as <id>_lines, and traced through the whole field: a lone wire gives circles spaced wider and wider apart, a magnet loops from N to S, two wires wrap both or crowd between them. Every source, probe and <id>_lines works in a step's indicate, focus and surround. Field lines are part of the scene, so hide them with lines: 0, not show:. A scene plane beside the magnet scene can read its readings. Put the magnet scene first.
Atoms and the periodic table
An orbitals is the orbital box diagram of an element or an ion ("Fe3+"), filled by the aufbau order and Hund, with the configuration, the unpaired electrons and the magnetic moment available to labels. A ptable is the periodic table or a slice of it, with the group names the book uses, and a hotspot can target its cells. A configuration exercise has the student fill those boxes by tapping, checked against the same logic. All of them draw in a scene plane that says aspect: equal. A tube is a test tube for what the book has you observe (it also needs axes: false): press a button to add a reagent and watch a precipitate form, a gas bubble off, a liquid change colour or a strip of paper turn.
Organic chemistry
A molecule is drawn from a SMILES string in a scene plane that says aspect: equal. SMILES writes a structure as text: C is carbon, = and # are double and triple bonds, a branch goes in parentheses, a ring is a digit that opens and closes, and lowercase letters are aromatic (c1ccccc1 is benzene). Hydrogens are filled in from the valences, so CCO is ethanol. Elements outside C, N, O, S, P, F, Cl, Br, I need square brackets ([Na+]). The compiler does the drawing, so a molecule is plain objects the rest of the scene can point at. In a scene space3 the same SMILES is a ball-and-stick model (view: ball) with the true bond angles, which spins with the camera like any other 3D figure. A reaction is a reaction SMILES (reactants>>products) with atom maps that says which atom becomes which, and morphs the one picture into the other as by goes from 0 to 1. A name exercise has the student type the IUPAC name of a drawn structure.
Controls
Controls are the interactive widgets the learner uses. They write to state variables, which re-evaluates all object expressions.
5 keywords12Timeline
A timeline is a sequence of steps the learner plays through in order. Each step can narrate, set state instantly, or animate to new values. Great for walkthroughs and guided reveals.
1 keywords13Loops & Logic
Prism has compile-time loops and conditionals that unroll before the scene is built. They use brace blocks, same as everything else. Generates static objects — the scene structure is always fixed at runtime.
8 keywords14Expressions & Math
Expressions appear in object properties (like the expr in curve f = <expr>), control bounds, and ${...} label interpolations. They're evaluated at runtime against the current state.
Videos
A video file is a talk over a board, played in the video studio (/admin/studio/video) one Space press at a time. It lives in content/videos/<slug>.prism. Words pop in with no fade, a scene keeps moving on a real clock while you talk, and nothing on the board is a lesson widget. The electron gas and its cut also work in any lesson scene.
All keywords