> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getflowpilot.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview and live mirror

> Test a flow inside the editor with preview, or mirror your edits live onto a real device.

There are two ways to test a flow before you ship it. **Preview** makes the editor canvas interactive so you can click through the flow without leaving the page. **Live mirror** streams your edits, as you make them, onto a real device running the FlowPilot preview app. Both are design and QA tools. Neither is how end users receive a flow (that is publish, a placement, and the SDK).

## Preview mode

Preview turns the static canvas into a working flow. Buttons navigate, inputs capture text, and toggles flip, so you can walk a screen path the way a user would.

### Turn preview on

You can toggle preview from two places, and they stay in sync:

* The **Preview** button in the top bar (eye icon). The tooltip shows the shortcut **⌘.**
* The **Preview** button in the floating toolbar at the bottom of the canvas.

When preview is active, the button turns purple and its label changes to **Exit Preview** (the icon becomes a crossed-out eye), and the phone frame gets a purple ring so you always know which mode you are in. Press the button again, or **⌘.**, to exit.

### What preview does

* **Navigation runs.** A button wired to `goNext`, `goBack`, `navigate`, or `closeFlow` moves the canvas to the matching screen, or closes the flow.
* **Inputs and toggles work.** Typing into an input or flipping a toggle updates the bound variable, so any dynamic value driven by that variable updates live.
* **It tracks its own screen.** Preview keeps a separate "current screen" and a back-history stack. Your editor selection is left untouched, so when you exit preview you land back on whatever screen you were editing.
* **It is non-destructive.** Preview navigation and any values you change are ephemeral. Nothing here is saved to the flow.

### Test branches with variable overrides

Conditional (dynamic) values branch on variables. To see a different branch without manually clicking to the state that sets it, override the variable directly:

<Steps>
  <Step title="Enter preview mode">
    Toggle **Preview** so the canvas is interactive.
  </Step>

  <Step title="Open the Variables panel">
    Open the left **Variables** tab. While preview is on, a purple **Preview** badge appears next to the panel title and every variable row becomes an editable override control.
  </Step>

  <Step title="Edit a value">
    Change a variable's value. The canvas re-renders immediately so you can see how conditions and interpolated text react. The panel reminds you: "Changes here affect the canvas preview only. They won't be saved to the flow."
  </Step>

  <Step title="Reset when done">
    Each overridden variable can be reset individually, or use **Reset (N)** at the top of the panel to clear all overrides at once. Exiting preview also clears every override.
  </Step>
</Steps>

### Preview is an approximation, not the device

Preview is close to the SDK runtime but not identical. Most importantly, actions behave differently here than in a real build. In preview, state and navigation actions run against preview-only state and show a toast instead of doing the real thing (for example, Open URL shows a confirmation rather than leaving the editor). For the full breakdown of which actions fire in edit mode versus preview, see [Preview is not the runtime](/editor/interactions-and-actions#preview-is-not-the-runtime). Always confirm end-to-end behavior on a real build or with live mirror.

## Move between screens on the canvas

The floating toolbar at the bottom of the canvas has a screen pager you can use in either edit or preview mode:

* **Previous** (left chevron) and **Next** (right chevron) step through screens in order. The arrow keys **←** and **→** do the same when you are not typing in a field.
* The middle button shows **current / total** (for example `2/3`) and the screen name. Click it to open a list and jump straight to any screen.

The same toolbar also has **Fit to view** (**⌘0**), a zoom slider (50 to 200 percent), and zoom in/out (**⌘=** / **⌘-**).

## Live mirror

Live mirror pairs the editor with a real device so your edits show up on the device in real time. It is the fastest way to judge spacing, fonts, animation timing, and haptics on real hardware.

### How pairing works

The **Live Mirror** control is the pill in the top bar, to the left of the schema and Preview buttons. Click it to start.

<Steps>
  <Step title="Start mirroring">
    Click the **Live Mirror** pill (or **Start Mirroring** in its popover). The editor opens a WebSocket connection to the FlowPilot backend and asks the server to create a session room. The pill shows **Creating room...** while it connects.
  </Step>

  <Step title="Get the room code">
    Once the room is created, the popover shows a **QR code** and a **6-character room code**, with the prompt "Scan this QR code with the FlowPilot app, or enter the code manually." The pill now reads **Waiting for device**.
  </Step>

  <Step title="Join from the device">
    On a device running the **FlowPilot preview app**, scan the QR code or type in the 6-character code. The QR code encodes a `flowpilot://mirror?code=...` deep link, so scanning opens the app straight into the session.
  </Step>

  <Step title="Edit and watch">
    When the device joins, you see a "Device connected" toast and the pill turns green and reads **Live · N**, where N counts the updates sent. From now on, every edit you make streams to the device automatically.
  </Step>

  <Step title="Stop mirroring">
    Click the pill and choose **Stop Mirroring** to end the session. The pill returns to its idle **Live Mirror** state.
  </Step>
</Steps>

### Connection states

The pill and popover reflect the live session state:

| State        | Pill label         | What it means                                             |
| ------------ | ------------------ | --------------------------------------------------------- |
| Disconnected | Live Mirror        | No session. Click to start.                               |
| Connecting   | Creating room...   | Opening the WebSocket and creating the room.              |
| Connected    | Waiting for device | Room is ready; QR code and code are shown; no device yet. |
| Streaming    | Live · N           | A device is connected and receiving your edits.           |
| Error        | Error              | The connection failed. The popover offers **Retry**.      |

A session room holds at most two participants (one editor and one device) and expires after about 5 minutes once it is empty. If the connection drops, the editor retries automatically with a backoff.

## Notes and warnings

<Warning>
  Live mirror needs the **FlowPilot preview app**, a separate QA and design-review app. It is not your production app and it does not use your production SDK integration. Real users never receive flows this way. They get them through [publishing](/editor/publishing), a placement, and the SDK.
</Warning>

<Note>
  Live mirror needs network connectivity to the FlowPilot backend WebSocket hub from both the editor and the device. If the device cannot reach the backend, it will not join the room.
</Note>

## Common mistakes

* **Expecting preview to match the device exactly.** Preview is an approximation. Action behavior, in particular, differs from a real build. Use live mirror or a real SDK build to confirm.
* **Confusing the preview app with your production integration.** The FlowPilot preview app is a QA tool for mirroring. Your app ships flows through the SDK after you publish and attach to a placement.
* **Testing a published flow in preview and assuming users see it.** Preview and mirror always show the current draft in the editor. Users only see a flow once it is published and attached to a placement.

## Troubleshooting

| Symptom                                                | Likely cause                                               | Fix                                                                                                                                                                             |
| ------------------------------------------------------ | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Preview button does nothing visible                    | The flow has one screen and no wired navigation            | Add a second screen and a button with a `goNext` action, then preview again.                                                                                                    |
| A wired button does not switch screens while authoring | You are in edit mode, where navigation actions do not fire | Enter preview mode (**⌘.**), then click the button.                                                                                                                             |
| Mirror pill stuck on **Waiting for device**            | No device has joined the room                              | Scan the QR code or enter the 6-character code in the FlowPilot preview app. Codes and rooms expire after about 5 minutes of inactivity; restart mirroring to get a fresh code. |
| Mirror shows **Error**                                 | The editor could not reach the backend WebSocket hub       | Check network connectivity, then click **Retry** in the popover.                                                                                                                |
| Device joined but edits do not appear                  | The device dropped its connection                          | Confirm the pill still reads **Live**; if it fell back to **Waiting for device**, rejoin from the device.                                                                       |

## Related pages

* [Publishing](/editor/publishing)
* [Interactions and actions](/editor/interactions-and-actions)
* [Variables](/editor/variables)
* [Dynamic values](/editor/dynamic-values)
* [iOS SDK quickstart](/ios-sdk/quickstart)
* [Expo SDK quickstart](/expo-sdk/quickstart)
