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

# Live Preview

> Iframe preview with hot module reload per project. Preview nodes on the Architecture Panel, responsive breakpoints, and per-container URLs for multi-service apps.

<img src="https://mintcdn.com/tesslate/VT6tbZolrCfpx26M/images/opensail-banner.png?fit=max&auto=format&n=VT6tbZolrCfpx26M&q=85&s=66579c47537b3464fb65b229cc9ab0fd" alt="Tesslate OpenSail" width="4712" height="1612" data-path="images/opensail-banner.png" />

## How it works

The live preview is an iframe rendered next to the code editor and the Design canvas. The iframe points at your running dev server. Every save triggers hot module reload (HMR) inside the container, the dev server pushes the update, and the iframe repaints.

No polling, no refresh buttons. Save, see it.

<CardGroup cols={2}>
  <Card title="HMR built in" icon="bolt">
    Your framework's hot reload flows straight into the preview iframe.
  </Card>

  <Card title="Per-container URL" icon="link">
    Multi-service projects get a URL per container.
  </Card>

  <Card title="Preview nodes on canvas" icon="window">
    The Architecture Panel renders live preview windows as graph nodes.
  </Card>

  <Card title="Responsive breakpoints" icon="mobile">
    Test 375px up to 1536px from a breakpoint switcher.
  </Card>
</CardGroup>

## URL pattern

Container URLs differ by runtime.

<Tabs>
  <Tab title="Local (desktop)">
    `http://127.0.0.1:{port}` direct loopback. No reverse proxy.
  </Tab>

  <Tab title="Docker">
    `http://{container}.localhost` or `http://{container}.{slug}.localhost`. Traefik routes by hostname to the right container on a shared Docker network.
  </Tab>

  <Tab title="Kubernetes">
    `https://{container}.{slug}.{domain}` in production (for example `https://frontend.my-app-k3x8n2.opensail.tesslate.com`). NGINX Ingress routes by hostname with a wildcard TLS certificate. Minikube uses `http://{container}.localhost` for local dev.
  </Tab>
</Tabs>

`GET /api/projects/{slug}/dev-server-url` returns the base URL the frontend uses to build per-container iframe URLs.

## The iframe

The preview iframe is wrapped in a mini-browser with:

* **URL bar** showing the active container URL
* **Back/forward/home/refresh** for navigating multi-page apps
* **Copy link** for sharing or opening in a standalone tab
* **Fullscreen** to dedicate the whole workspace to the preview

If the dev server is not yet ready, the preview shows a startup overlay with pulsing grid spinner, progress bar, and streaming logs (`StartupLogViewer`). If the health check times out, an "Ask Agent" button kicks the agent off to diagnose and fix.

## Preview nodes on the canvas

The Architecture Panel can host browser preview nodes alongside your containers. Drag the **Browser Preview** node from the Marketplace sidebar, drop it on the canvas, and connect it to a container with a `browser_preview` edge.

What you get:

* **Live iframe inside the canvas** with the same mini-browser chrome
* **Resizable and repositionable** so you can arrange multi-viewport previews
* **Drag to reposition** while the app keeps running
* **One incoming connection** per preview node (enforced in `isValidConnection`)

This is how you author multi-container apps while watching them run.

## Port picker for multi-container apps

When your project has more than one previewable container, the `PreviewPortPicker` dropdown appears. It lets you switch the active iframe between the frontend, API docs, worker dashboard, or any container that exposes a port.

Containers expose a port through the `effective_port` resolution chain: `internal_port` from config, then `port` column, then `3000` fallback. Always trust `effective_port`, never hardcode.

## Responsive breakpoints

In Design view, the breakpoint switcher cycles through:

| Breakpoint | Width             |
| ---------- | ----------------- |
| **Fit**    | Full canvas width |
| **sm**     | 640px             |
| **md**     | 768px             |
| **lg**     | 1024px            |
| **xl**     | 1280px            |
| **2xl**    | 1536px            |
| **Mobile** | 375px             |

The iframe width snaps to the chosen breakpoint and the canvas scales so the preview stays fully visible.

## Health checks

Every container has a readiness probe that gates preview traffic. Until the dev server responds on the effective port, the iframe shows the startup overlay. When readiness passes, the iframe loads.

On Kubernetes, readiness is HTTP-based (`GET /` on the port). Liveness is exec-based (tmux session health), so the pod stays alive even if the dev server crashes, giving the agent room to fix it.

## Manual reload

Sometimes HMR does not cover every change (service workers, new env vars, infrastructure container restarts). Click the refresh button in the preview chrome for a hard reload. The design selection and canvas state persist across reloads.

## Preview security

Preview URLs are authenticated. The dev server verifies the user's session through the `/auth/verify-access` endpoint before serving. Unauthenticated users hitting a preview URL get redirected to login. Team-visible projects also check team membership.

## Related

<CardGroup cols={2}>
  <Card title="Code editor" icon="code" href="/guides/code-editor">
    The editor that sits beside the preview.
  </Card>

  <Card title="Design engineer" icon="pen-ruler" href="/guides/design-engineer">
    Click-to-source editing on top of the iframe.
  </Card>

  <Card title="Architecture Panel" icon="diagram-project" href="/guides/architecture-panel">
    Preview nodes on the canvas.
  </Card>

  <Card title="Projects" icon="folder" href="/guides/projects">
    Container lifecycle and URL patterns.
  </Card>
</CardGroup>
