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.The developer tools are available in the Mentra App under Settings → Miniapp Developer Settings.Share feedback with an in-app bug report, on Discord, or by email at help@mentra.glass.
The Mentra App sends the phone’s back gesture (the left-edge swipe on iOS, the back button or gesture on Android) to your UI WebView’s browser history first:
  • While your WebView has history, back runs history.back() inside your miniapp. Your router or useHistoryState hook sees the popstate and shows the previous screen.
  • When the history is empty, back minimizes your miniapp. The UI WebView unmounts, but your background layer keeps running with its session. When the user reopens the miniapp, the UI starts again on its first screen with empty history. Keep anything that must survive in the background layer and send it to the UI when it reopens.
The host can only see browser history. A screen or dialog that exists only in React state (useState, MemoryRouter, createMemoryRouter, or wouter’s memoryLocation) never creates a history entry, so back skips past it and minimizes the whole miniapp. Anything the user should be able to go back from must push a history entry.

Pages: a router in hash mode

For page-level navigation, use your router’s hash mode. Each navigation becomes a real history entry, and hash URLs keep working when the host reloads your bundle from disk.
A back button in your own header should also go back, not forward to the parent route. Otherwise the next back gesture returns the user to the page they just left.

Tabs, dialogs, and screens: useHistoryState

For UI state that is not a route, such as tabs, dialogs, sheets, pickers, or a multi-step screen, use useHistoryState from @mentra/miniapp/ui. It works like useState, except that the phone’s back gesture undoes each change.
Rules for keys and values:
  • key names the value inside the history entry. Use a different key for each piece of state on the page. Two components that pass the same key share one value.
  • Values are stored in history.state, so they must survive structured clone: strings, numbers, booleans, null, and plain objects and arrays. For a dialog about one item, store the item’s id rather than an object with methods.
  • The value belongs to the current history entry. A component that remounts, or a page that reloads, reads it back. Minimizing the miniapp discards it along with the WebView.
useHistoryState and a hash router can live in the same app. A route change starts a fresh entry, so hook values fall back to their initial values on the new page and come back when the user returns.

Check it on a phone

  1. Open a nested page or dialog, then swipe back. You land on its parent.
  2. Open a dialog, close it with its own button, then swipe back. The dialog does not reopen.
  3. From the first screen, swipe back. The miniapp minimizes.
On Android, repeat each step with the system back button.

Next steps

The UI layer

The mentra bridge, hooks, and components.

Safe areas & layout

Keep content clear of the capsule menu.