Glassly Miniapp SDK betaThe SDK is in beta, so its APIs may change before general availability.Developing on Mentra Live? We recommend using the
Glassly Bluetooth SDK.The developer tools are available in the Glassly App under Settings →
Miniapp Developer Settings.Share feedback with an in-app bug report, on
Discord, or by email at
help@glassly.ai.
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
Shapes beyond
rect render where capabilities.display.shapes lists the
type (the Even Realities G2 with the Glassly firmware draws all of them on the
glasses); elsewhere they are dropped and reported. color is a gray level
0..15. Points are raw canvas pixels and are not anchored.
Transitions
Give an element a stableid and a transition, and geometry changes between
renders animate on devices with capabilities.display.animation:
color and stroke widths tween;
new text or image pixels switch immediately. Devices without animation jump.
Text with a stable id can therefore tick, scroll or fade at tens of updates
per second: re-render with the new string and, optionally, a new box.
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.
Anchoring to a corner
For elements that hug a screen corner (a minimap bottom-right, a status glyph bottom-left), give the box ananchor. x/y then become insets from that
corner, growing inward, and the phone resolves the box against the connected
device’s real canvas — the element lands flush on every resolution with
nothing to clamp:
anchor is one of "top-left" (the default), "top-right",
"bottom-left", "bottom-right". Corners only — there is no center or edge
anchoring, and no scaling.
When you want an exact fit instead (a full-screen caption), 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".
