# DualView URL Parameters

This is the canonical share/embed URL schema for https://www.dualview.ai/. Both humans and agents can construct these links directly. Loading a link never uploads anything: query parameters carry state and media URLs, and the optional `#dv=` fragment carries compressed content that stays inside the browser (URL fragments are never sent in HTTP requests).

Base URL: `https://www.dualview.ai/`

## Query Parameters

| Parameter | Type | Description |
|---|---|---|
| `a` | URL | Media URL for side A. Must be `https`. The browser fetches it directly; the remote host must allow CORS. |
| `b` | URL | Media URL for side B. Must be `https`. Same CORS requirement as `a`. |
| `mode` | string | Comparison mode ID: `slider`, `side-by-side`, `blend`, `split`, `flicker`, `prompt-diff`, `json-diff`, `heatmap`, `audio`, `model-3d`, or `webgl-compare`. |
| `sp` | number | Slider position, `0`-`100` (percent from the left/top edge). Applies to slider mode. |
| `so` | string | Slider orientation: `v` (vertical divider, dragged left-right; default) or `h` (horizontal divider, dragged up-down). |
| `t` | number | Playback time in seconds (e.g. `t=12.5`). Applies to video and audio. |
| `speed` | number | Playback speed multiplier (e.g. `speed=0.5`, `speed=2`). |
| `zoom` | number | Zoom level (`1` = fit; `2` = 200%, etc.). |
| `px` | number | Pan offset X, in pixels at the current zoom level. |
| `py` | number | Pan offset Y, in pixels at the current zoom level. |
| `la` | string | Label for side A. URL-encoded, maximum 64 characters (longer values are truncated). |
| `lb` | string | Label for side B. URL-encoded, maximum 64 characters (longer values are truncated). |
| `embed` | flag | `embed=1` renders the chrome-less embed view: comparison surface only, no header, sidebar, or timeline. See [embedding.md](https://www.dualview.ai/docs/embedding.md). |
| `nozoom` | flag | `nozoom=1` disables zoom interaction (wheel/pinch). Useful inside scrollable host pages. |
| `nopan` | flag | `nopan=1` disables pan/drag interaction. |

All parameters are optional. Unknown parameters are ignored.

## The `#dv=` Fragment (Self-Contained Content)

For small files, DualView can encode the comparison content itself into the URL fragment:

```
https://www.dualview.ai/#dv=<base64url-encoded, deflate-compressed payload>
```

- The payload is compressed with the browser's CompressionStream (deflate) and base64url-encoded.
- It contains the media content and comparison state, so the link works even when the original files have no public URL.
- Because it lives in the URL fragment (after `#`), it is never transmitted to any server, including DualView's host. The receiving browser decompresses and renders it locally.
- Practical size is limited by browser/messenger URL-length limits, so this is intended for small images, text, JSON, and similar content. For larger media, use `a`/`b` URLs or the offline HTML export.

Query parameters and the `#dv=` fragment can be combined; explicit query parameters (e.g. `mode`, `sp`) take precedence over state stored in the fragment.

## Examples

Slider comparison of two remote images, divider at 35%:

```
https://www.dualview.ai/?a=https://example.com/before.png&b=https://example.com/after.png&mode=slider&sp=35
```

Side-by-side video review starting at 12 seconds, half speed, with labels:

```
https://www.dualview.ai/?a=https://example.com/v1.mp4&b=https://example.com/v2.mp4&mode=side-by-side&t=12&speed=0.5&la=H.264&lb=AV1
```

Embedded heatmap, zoomed to 200% and panned, with interactions locked:

```
https://www.dualview.ai/?a=https://example.com/a.png&b=https://example.com/b.png&mode=heatmap&zoom=2&px=120&py=-40&embed=1&nozoom=1&nopan=1
```
