Embedding models in pages and docs
solid export (see the command line reference) turns a
node into a static directory that renders the model in any browser —
animations and driver controls included, since operations are exported
as raw symbolic expressions over $t and qualified driver ids and
evaluated client-side. No server-side code is needed: any static file
host works.
What an export contains
export/
├── manifest.json # the document (see below)
├── models/ # one STL per distinct rigid part
│ └── ...
├── index.html # standalone viewer page
└── solid-widget.js # the viewer bundle (three.js based)
manifest.json and models/ are the data; index.html plus
solid-widget.js are the viewer (omitted with --no-widget).
Opening index.html over HTTP shows the model with orbit controls,
play/pause and a timeline for animated nodes, and the
driver controls for a machine that declares them.
The manifest is a solid-node-export document carrying format
and version, the animation parameters, a drivers table
(qualified id → default, range, unit, dtype, scale), an
instructions table, the root node tree with its symbolic
operations, and the printed-pieces inventory. The declared
version is a property of the content: a document with no drivers
is version 1, drivers make it version 2, and a flexible part makes it
version 3, so documents published by earlier releases keep rendering.
Warning
The viewer gained a version gate in 0.6, and older viewers have
none: a 0.5.x bundle pointed at a version 2 or 3 document will
silently render only the part of the machine it can evaluate
rather than refusing. If your host pins its own copy of
solid-widget.js, upgrade it together with the framework. This
release’s viewer refuses a document schema it cannot read, naming
the version.
Embedding in any web page
Host the export directory and point an <iframe> at its
index.html:
<iframe src="export/index.html" style="width: 100%; height: 480px; border: 0;">
</iframe>
Two URL query parameters control playback:
t(0.0 to 1.0)The initial animation time.
autoplay=0Start paused. Combined with
tthis shows a static pose:index.html?t=0.25&autoplay=0.
These two are the whole URL surface: a driver cannot yet be preset or the control chrome suppressed from a query string. A host that needs either drives the widget programmatically, below.
The JavaScript API
Hosts that load solid-widget.js directly may call
SolidNodeWidget.mount(target, manifestUrl, options). The package’s
solidNodeViewerApi declaration, browser global, and each mount
handle all report API version 5, and the viewer accepts document
schema versions 1, 2 and 3.
Camera options: view (camera and target), up and fov; each
vector may be a three-number tuple, and fov is in degrees. When
omitted they preserve the established Z-up direction and 50° field of
view. driverControls: 'none' suppresses the built-in sliders,
buttons and breadcrumb, for a host that builds its own control UI:
const viewer = await SolidNodeWidget.mount('#model', 'manifest.json', {
view: { camera: [80, -60, 40], target: [0, 0, 0] },
up: [0, 0, 1],
fov: 22.5,
driverControls: 'none',
});
Driving from the host
The mount handle exposes the machine:
drivers()The document’s driver table: qualified ids with default, range, unit, dtype and scale.
driver(id)/setDriver(id, value)Read and write one driver’s current value. Values are in the driver’s native units (the units its default and state are kept in), and ids are verbatim from the document. A declared
rangeis presentation metadata and never clamps.onDriverChange(fn)Subscribe to value changes, whatever their source — a slider, a running ramp, or another
setDrivercall.instructions()/trigger(name)List the declared instructions, and run one.
triggerreturns{done, cancel()}: the ramp runs client-side over the instruction’s declared duration and lands exactly on target, and a latertriggerreplaces an active ramp.
Moving one driver does not recompute the tree: which operations
re-evaluate is decided by the free variables read off each parsed
expression, so a host can wire a gauge to onDriverChange and
drag values at frame rate. The handle also keeps the earlier
navigation surface — assembly metadata, subtree focus and visibility,
setTime — unchanged.
Embedding in Sphinx documentation
The solid_node.sphinx extension provides a directive that embeds an
export in the built HTML. In conf.py:
extensions = [
# ...
'solid_node.sphinx',
]
Then, in any document:
.. solid-node:: exports/my_model
:height: 300px
:t: 0.25
:autoplay: no
The argument is the path to an export directory, relative to the
current document (or to the documentation source directory, with a
leading /). The directory is copied into the HTML output and
embedded as an <iframe>.
Options:
:height:Height of the embedded viewer. Default:
480px. The width always follows the page.:t:Initial animation time, 0.0 to 1.0.
:autoplay:yes(default) orno. Withno, the animation starts paused — combine with:t:for a static pose.
The exports are generated ahead of the documentation build and
committed (or produced by a CI step) — the Sphinx build itself never
runs the CAD stack. A missing or invalid export directory fails the
build with a message saying which solid export invocation would
create it.
The directive’s options are :height:, :t: and :autoplay:
only — like the URL surface, it cannot yet preset a driver or
suppress the control chrome, so a driven model embeds with its
controls showing at their defaults.
Exports referenced by the directive may be made with --no-widget:
the extension completes them with the viewer files from the installed
solid_node package at build time, so the repository only needs to
carry each model’s manifest.json and STLs, and every embedded
model shares one copy of the viewer source.