Skip to content

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

FlagEffect
?embed=1Embed mode — hides the dock and panels, enables the bridge
?ui=minimalHides the dock and panels without enabling the bridge
?measurements=1Surfaces the measurement tool layer in a bare view
?annotations=1Surfaces 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:

CommandShape
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 the ready target 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.

MIT licensed. Local-first: the viewer never uploads your data.