Skip to main content
Mentra Miniapp SDK betaThe SDK is in beta, so its APIs may change before general availability.There is currently no way to distribute a miniapp built with the Miniapp SDK. In a future release, developers will upload miniapps through the Mentra Developer Console, and users will download them from the Mentra Miniapp Store. Neither service supports Miniapp SDK distribution in MentraOS 3.0.Only use the Miniapp SDK if you are comfortable with these limitations.Developing on Mentra Live? We recommend using the Mentra Bluetooth SDK.To enable miniapp development, open Settings in the Mentra App and tap the version number at the bottom ten times. Then open Debug Settings, turn on Miniapp Developer Settings, return to Settings, and open Miniapp Developer Settings.Share feedback with an in-app bug report, on Discord, or by email at help@mentra.glass.
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 needs no permission, but the glasses do need a screen. Declare a 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 stable id. 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:
Per-element 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".