# Preview and testing

> Show your work in the workspace's Preview window with rootsy preview, open apps that need a real browser window, and check that a page works.

This page covers the workspace's Preview window and how to check that a page works. The Preview shows your app while you build it, and an agent on the computer controls it with `rootsy preview`. Check that a change works before telling anyone it does.

## What the Preview window shows

The Preview window loads your computer's address (`https://<name>.rtsy.dev`) inside the workspace. It shows the same app visitors get, served through the same path, so a page that works in the Preview works at the address.

People rarely refresh the Preview themselves. After you change something, refresh it for them.

## Refresh the Preview after a change

```sh
rootsy preview refresh
```

This reloads the page the Preview is showing. It prints `preview refreshed (1 viewer)`, with the number of open workspaces it reached.

If no workspace has this computer open, or the open one has paused after 15 minutes without input, nothing is refreshed and it prints:

```text
no dashboard connected — the user will see the latest version when they next open it
```

Then tell the person which page to look at instead of saying you refreshed it.

## Point the Preview at a page

To show a page you've built, give its path:

```sh
rootsy preview open /pricing
```

Paths resolve against your computer's address. You can also pass a full `https://` URL. The workspace only follows it if the host is your address or one of your active custom domains, and ignores anything else. A target must start with `/` or `https://` and can't be longer than 2048 characters.

Add `--focus` to bring the Preview window to the front:

```sh
rootsy preview open /pricing --focus
```

Use `--focus` when the person should see the result now, such as the first working version or when they asked to see it. Leave it off for routine changes so you don't pull them away from what they're doing. `rootsy preview focus` brings the Preview to the front without reloading it.

## Apps with sign-ins, OAuth or browser dialogs

Embedded previews can't hold logins. Browser privacy rules block cookies in a page framed inside another site. Sign-in, sessions and OAuth redirects fail inside the Preview even when they work at the address. After you build a sign-in, run:

```sh
rootsy preview window
```

The Preview then shows "Sign-ins don’t work inside an embedded preview — browsers require a real window for that." with an "Open in its own window" button. For other features that need a real window, such as browser dialogs, use `--reason other`. The Preview then shows "This app needs browser features that only work in a real window."

```sh
rootsy preview window --reason other
```

If no workspace is open, the command prints `no dashboard connected — tell the user to use 'Open in its own window' on the Preview`. Don't say sign-in works until the person has signed in successfully in a real window.

## Check that a page works

`curl` tells you the server answered. Several common bugs only show up in a browser. A status code can't show you:

- a CSS rule that keeps a "hidden" element on screen. The `hidden` attribute loses to any `display:` rule you wrote, so `.gate { display: grid }` beats `[hidden]` and a login gate never hides. Use a class you control, or add `[hidden] { display: none !important }`.
- a stale cached response. Express sends ETags on JSON, so an API can answer `304 Not Modified` and the page keeps showing old data. Turn it off with `app.set("etag", false)`, or send `Cache-Control: no-store` on API routes.
- a form that posts nowhere.

To look at the page the way a visitor would, install a headless browser once, then take a screenshot:

```sh
npx --yes playwright install --with-deps chromium
ADDR=$(rootsy domains | awk '/^site:/ {print $2}')
npx --yes playwright screenshot --full-page "$ADDR/" /tmp/home.png
```

Then open `/tmp/home.png` and look at it. Claude Code can read images. When a change is visual or sits behind a login and you haven't looked at it, say what you checked and what you didn't.

## Check the server from inside the computer

To check the full path a visitor's request takes, request your address:

```sh
ADDR=$(rootsy domains | awk '/^site:/ {print $2}')
curl -sI "$ADDR/"
```

To check your nginx alone, skipping the platform in front of it, request port 8090 directly. The platform passes the visitor's hostname in the `Host` header. Send it too if your config matches on `server_name`:

```sh
ADDR=$(rootsy domains | awk '/^site:/ {print $2}')
curl -sI -H "Host: ${ADDR#https://}" http://127.0.0.1:8090/
```

If port 8090 answers and the address doesn't, see [Troubleshooting](https://rootsy.io/docs/reference/troubleshooting.md).

## Exit codes

`rootsy preview` exits 0 when the command was sent, including the `no dashboard connected` case where nothing was shown. It exits 1 for `preview command rejected` or `preview control unavailable on this box`, and 2 for wrong arguments. The full reference is on [The rootsy command](https://rootsy.io/docs/reference/cli.md).

---
Page: https://rootsy.io/docs/reference/preview-and-testing/ · Updated: 2026-10-21 · All docs: https://rootsy.io/llms.txt
