---
title: "Previews"
description: "Review and share a running application from its cloud thread."
canonical_url: "https://hoplite.sh/docs/sandboxes/previews"
markdown_url: "https://hoplite.sh/docs/sandboxes/previews.md"
---

# Previews
URL: /docs/sandboxes/previews
LLM index: /llms.txt
Description: Review and share a running application from its cloud thread.
Related: /docs/sandboxes/scripts, /docs/sandboxes/resources, /docs/factory

# Previews

Review the running application alongside the agent's work with a managed preview. Hoplite runs your project's `run` script inside the cloud thread's workspace, and the preview link stays associated with the thread and port when the underlying runtime changes.

## Start and open a preview

1. Configure a `run` command and `ports.preview` in [`.hoplite/settings.json`](/docs/sandboxes/scripts) or **Settings → Project → Environment**.
2. Ask the agent to start the preview. Hoplite waits for the configured port to listen and reports the process state.
3. Open **Preview** in the thread's side panel. Use **Terminal** to inspect the workspace directly when needed.

Starting an already-running managed preview reuses it. If no run command is configured, Hoplite infers one for supported frameworks, including a single app inside a pnpm, Turborepo, or Nx workspace, and writes the command and ports to `.hoplite/settings.json` in the thread's checkout. That file is not git-excluded, so you can commit the inferred settings. When a repository contains several previewable apps and nothing picks one, Hoplite writes nothing and the agent asks which app to preview; a server that's already running in the sandbox is still offered in the Preview panel. Configure an explicit command for repositories that need multiple services or a particular package in a monorepo.

## Multiple ports

Hoplite detects other HTTP listeners started by the managed run and lists them in the Preview panel. To retain a name and port in project configuration, add it under `ports.additional`:

```json title=".hoplite/settings.json (ports excerpt)"
{
  "ports": {
    "preview": 3000,
    "additional": { "api": 8787 }
  }
}
```

Database and other non-HTTP listeners appear as services, rather than browser previews.

## Access and sharing

Share the preview's `usehoplite.com` URL. Visitors must sign in to Hoplite and belong to the preview's workspace. Opening a link can start or restore the workspace; a startup page remains visible until the app is ready.

Only app-preview share links are durable. Terminal and internal browser-control URLs are short-lived and stop working when the sandbox generation changes.

The proxy attaches sandbox-provider credentials server-side. Provider tokens and Hoplite session cookies are not forwarded to your application. Preview content runs on a separate origin from `hoplite.sh`.

For previews inside your own application, use the [API gateway access flow](/docs/factory#attachments-and-previews).

## Request headers your app receives

Hoplite puts a small proxy in front of your dev server inside the workspace. By default it presents every request as a local one: `Host` is `localhost:<port>`, `Origin` and `Referer` are rewritten to `http://localhost:<port>`, and no `X-Forwarded-*` headers are sent. That keeps the host and origin checks in Next.js, Vite, webpack-dev-server, Rails and Django passing without configuration. Absolute redirects your app builds for its own local origin (for example Rails `redirect_to` or Laravel `redirect()` producing `http://localhost:3000/posts/2`) come back as relative redirects, so the browser stays on the preview URL. Every `Set-Cookie` header your app sends is passed through.

If your app needs to know its public URL, for example to build absolute links, OAuth callbacks or email URLs, switch to forwarded headers:

```json title=".hoplite/settings.json (preview proxy excerpt)"
{
  "previewProxy": { "upstreamHeaders": "forwarded" }
}
```

In `forwarded` mode, `Host` stays `localhost:<port>` so dev-server host checks still pass. The app also receives `X-Forwarded-Host` (the public preview host), `X-Forwarded-Proto: https`, `X-Forwarded-Port`, `X-Forwarded-For`, and an RFC 7239 `Forwarded` header, and `Origin` and `Referer` keep the public origin so they match the forwarded host. Your framework has to trust the proxy for these to take effect. Rails needs the preview host in `config.hosts` (for example `RAILS_DEVELOPMENT_HOSTS=.modal.host,.usehoplite.com`), Laravel needs `trustProxies(at: '*')`, and Django needs `USE_X_FORWARDED_HOST = True`, `SECURE_PROXY_SSL_HEADER`, and the preview origin in `CSRF_TRUSTED_ORIGINS`. Keep the default `localhost` mode for Next.js and webpack-dev-server unless you've configured `allowedDevOrigins` or `allowedHosts`, because both reject cross-origin dev requests.

## Preview states

| State | Meaning and next action |
| --- | --- |
| `starting` | The process has started but the port is not listening. Check the configured port and startup output if it remains here. |
| `ready` | The port is serving. Open the preview to check application behavior. |
| `stopped` | The process exited, was stopped, or ended when the workspace archived. Start it again when needed. |
| `crashed` | Inspect the exit reason and available run-log tail. Correct the command, dependencies, or resource limit before restarting. |
| `unsupported` | The current runtime cannot provide the requested capability or port. |

Hoplite can attempt bounded recovery for a crashed managed preview. Repeated failure leaves it stopped with diagnostic output. Archiving or a disruptive [resource change](/docs/sandboxes/resources) ends the old process; restoring the workspace starts a new one.

## Review checklists

An agent can attach review steps to the Preview panel, including paths and controls to inspect. Mark each step reviewed after checking it. Later changes can reset a step to unreviewed; the agent cannot approve its own work on your behalf.

## Sitemap

Sitemap discovery is not enabled for this deployment.
