Embed & session reference
How work leaves the viewer and how the viewer goes inside another page: the .olvsession round-trip, share links, embed mode's URL flags, the validated postMessage bridge, and the developer diagnostics flags.
Session round-trip (.olvsession). The session Export saves the full working state — camera, render settings, active colour mode, annotations, measurements, named views, and scan metadata — to a .olvsession JSON file. Import loads one back, restoring the camera and view exactly. Older measurement-only and v2 session files still open via the v1/v2/v3 schema back-compat in the parser.
Sharing a view
The Share tool in the bottom dock copies a link that reproduces the current view — the camera position and target, the colour mode, the point sizing, and the selected annotation. The link carries no scan data: the recipient opens the same scan themselves, and the saved view is applied on top. This keeps "share this view" working with no upload and no backend.
Embedding
Append ?embed=1 to the URL to strip the chrome down to a bare canvas for use in an <iframe>. The embed surface is a small, documented set of URL flags and a validated postMessage bridge.
URL flags
| Flag | Effect |
|---|---|
?embed=1 | Embed mode — hides the dock and panels, enables the bridge |
?ui=minimal | Hides the dock and panels without enabling the bridge |
?measurements=1 | Surfaces the measurement tool layer in a bare view |
?annotations=1 | Surfaces the annotation tool layer in a bare view |
?autoload=sample:<id> | Opens a built-in sample on startup (survey or scan) |
postMessage bridge
In embed mode the viewer posts one ready message to the host page once the renderer has initialised: { source: 'openlidarviewer', type: 'ready', version }. The host page may then send commands with iframe.contentWindow.postMessage(...). Each command is validated against a small, closed set of verbs; anything unrecognised or malformed is ignored:
| Command | Shape |
|---|---|
| Load a file | { type: 'load-file', buffer: ArrayBuffer, name: string } |
| Jump the camera | { type: 'jump-camera', camera: { position, target, mode?, fov? } } |
| Toggle a layer | { type: 'toggle-layer', id: string, visible: boolean } |
| Focus an annotation | { type: 'focus-annotation', id: string } |
Embedding origin and security
The shipped deploy headers set X-Frame-Options: SAMEORIGIN, so out of the box the viewer only embeds in a page on the same origin. To embed it cross-origin, the deployer removes that header and sets a deliberate Content-Security-Policy: frame-ancestors … allow-list instead.
The bridge accepts commands only from the actual embedding parent frame. To restrict which origins may drive a cross-origin embed, pass an allow-list on the viewer URL:
?embedParent=https://host.example.com— sets both thereadytarget and the inbound allow-list to that one origin.?embedOrigins=https://a.example.com,https://b.example.com— a comma-separated inbound allow-list.
Without an allow-list the bridge still shape-validates every message and rejects any not sent by the parent frame, but it does not filter by origin — so configure one for any cross-origin deployment.
Developer diagnostics
Two URL flags surface developer diagnostics; neither appears in a normal session.
?debug=1 shows a live performance overlay — frame rate and frame time, the GPU backend (WebGPU or WebGL 2), draw calls, the displayed and total point counts, and an estimated GPU memory figure — refreshed about four times a second, alongside the most recent load's stage-by-stage telemetry. The raw error detail for any failed load is also logged to the console under this flag.
?benchmark=1 emits a structured benchmark result for each load — the time to first render and the full per-stage timing breakdown — to both the overlay and the console, so loading performance can be compared across versions.