session.display.render() draws to the glasses HUD. Each call describes the
whole frame: everything that should be on screen right now. The phone diffs it
against the previous frame, so elements with a stable id update in place (no
flicker), anything you leave out of the new frame comes off the screen, and
render([]) clears it. Your job is to describe the frame; the phone works out
what changed.
DISPLAY
hardware requirement in your manifest
so the miniapp only installs on glasses that can show anything.
Elements
Screen sizes
box is {x, y, w, h} in raw device pixels. Coordinates map 1:1 to the
device canvas, with the origin at the top-left:
We recommend designing your layout for 500 × 220. A frame that fits
500 × 220 renders as-is on every positioning device; on the G2’s larger canvas
it sits in the top-left with some margin. Boxes that run past the edge are
clamped, and elements past the device’s budget are dropped tail-first. Both
show up in the render result, so you find out.
When you want an exact fit instead (a full-screen caption, an element pinned
to the bottom edge), compute boxes from the connected device’s real canvas.
session.capabilities.display carries it, populated on the "ready" event:
Older glasses
Even Realities G1 and Vuzix Z100 show text but can’t place elements at coordinates, and their displays can’t show bitmaps. Render the same scene anyway: the phone converts it for them. Text elements collapse into a single full-view text layout in reading order (top to bottom, then left to right), and image and rect elements are dropped. The result tells you what happened (degraded: true, plus the dropped ids), and
session.capabilities.display.canPosition tells you up front which kind of
device you’re on.
In practice a text-first miniapp works everywhere with zero branching: a
caption app’s single full-canvas text element reads the same on every device.
If your layout leans on positioning or images, like a HUD with a minimap,
check canPosition and render a text-only variant for these devices.
Updating and clearing
Give any element that changes over time a stableid. Re-rendering with the
same id updates that element in place on the glasses, and unchanged elements
never re-cross Bluetooth, so pushing the whole frame on every change is cheap.
To take something off screen, leave it out of the next frame. To clear
everything:
Options and results
render(elements, options?) takes {view, durationMs} — view picks
"main" (default) or "dashboard", and durationMs auto-clears the frame
after that many milliseconds.
Awaiting is opt-in. A plain fire-and-forget call is fine, and the returned
promise never rejects:
Just showing text
The simplest useful frame is one text element covering the whole canvas — a status line, a caption, a “Saved” confirmation:style.breakMode ("character" | "character-no-hyphen" | "word" | "strict-word") controls how the text wraps inside its box.
Dashboard view
render(elements, {view: "dashboard"}) targets the dashboard view, the
glasses’ status view that the user brings up with a glasses-specific gesture
(head-up on G1, a double-tap on others). The default is "main".
