Reading A Lesson
Interactive embeds
Simulators and lesson-local widgets: a small self-contained web app framed inside a lesson, with Enlarge, parameters from the fence, and the same privacy as the book it belongs to.
Suggest an editInteractive embeds
Some ideas need a control the reader can push: a slider, a Step button, a packet you drag through the network stack. For those a lesson can frame a simulator — a small, self-contained web page that the content repository ships beside its prose.
A widget that belongs to one lesson
The binary-search stepper below lives beside this lesson, in the chapter folder's
_assets/_simulators/index.html. Press Step and watch the range halve:
The fence that draws it is one line with an empty body:
```simulator src=_assets/_simulators/index.html?target=23 height=170 title="Binary search, one step at a time"
```src=is a path inside the lesson's own_assets/_simulators/folder, with an optional query. It may not contain...height=is the frame's height in pixels;title=captions it and labels it for screen readers.- The query reaches the widget as
window.synapseSimulator.params, so one widget can serve several figures — this page could frame the same file again with?target=72. - The Enlarge button opens the widget full screen, like any diagram.
The files are served at /content-assets/<book>/<chapter>/<lesson>/_assets/_simulators/… and are
gated exactly like the book: on a public book anyone can load them; on a private book only the
readers on its list can (ADR RS012). Anything else a lesson keeps in _assets/ — its D2 sources in
_assets/_diagrams/, for example — is never served.
A simulator a whole repository shares
When several lessons use the same app, it goes at the root of the content repository instead, in
_simulators/<id>/, and the fence names it:
```simulator name=osi-encapsulation height=560 title="OSI Encapsulation Simulator"
```That example is real: the system-design guide's networking lesson frames an OSI encapsulation
simulator this way (ADR RS006). The bundle is a static app — index.html plus its assets — served at
/simulators/<id>/.
Writing one
A simulator is any static web page that works inside an iframe:
- Keep it self-contained:
index.htmland files beside it, referenced by relative paths. - Read your parameters from
window.synapseSimulator?.params ?? new URLSearchParams(location.search). On a private book the reader page fetches the widget with the reader's credentials and frames it assrcdoc, which has no query string — so the page provides the parameters for you. - Respect
prefers-color-schemeso it matches the reader's theme. - Keep it small and free of network dependencies, so it works for a reader on a slow connection.
If a fence is malformed — a missing src, a path with .. — the lesson shows a visible authoring-error
card with the raw fence, never a silently missing embed.