Preview Site vs Live Site

Your workspace does not have a site and a staging mode. It has two complete websites. Same content, same templates, same code — built from one repository on two git branches, deployed as two separate workers, answering on two different hostnames.

The live site answers on your domain. The preview site answers on staging. plus your domain — so if your site is example.com, your preview site is staging.example.com. Both are real deployments with real certificates. The difference is who they are for, what reaches them, and a short list of things the preview one refuses to do.

The two sites side by side

Live sitePreview site
Addressyour domainstaging. + your domain
Git branchmainstaging
What it is foryour visitorsreviewing the whole site before visitors get it
What builds itpublishing in the CMS, and promotionfile changes — CLI pushes, Layouts saves, managed-file refreshes — and an automatic rebuild after every live publish

The Deploy screen mirrors this exactly: two stage cards at the top, two history columns underneath, one per site.

flowchart LR
    subgraph PV["Preview site card"]
        direction TB
        P1["What the card explains:<br/>a private copy of the whole site"] --> P2["Visit preview site"]
        P2 --> P3["Push preview live"]
    end
    subgraph LV["Live site card"]
        direction TB
        L1["The site your visitors see"] --> L2["Visit live site"]
    end
    PV -- "promotion" --> LV

Push preview live is the promotion control, and it is only offered when the preview site’s most recent deployment succeeded. If that build failed, the card replaces the button’s hint with a red notice and the control is unavailable until the error is resolved.

Which changes land where

The thing most people expect, and which is not true, is that you choose. There is no target selector anywhere in the CMS. Which site a change lands on is a fixed property of the kind of change, and it is the same for every workspace.

The rule underneath is simple once you see it: anything you edit as a record in the CMS goes straight to the live site. Anything that arrives as a file goes to preview first.

ChangeLands onReason badge
Publishing a page, now or on a scheduleLive sitePages
General site settingsLive siteCompany Settings
A logo or favicon uploadLive siteLogo/Favicon
Team member profile detailsLive siteUser Profiles
Page typesLive sitePage Types
LabelsLive siteLabels
AutolinksLive siteAutolinks
FormsLive siteForms
MenusLive siteMenus
Search indexesLive siteSearch Indexes
leed site push from the CLIPreview siteDeveloper CLI
A managed-file refresh from LeedPreview siteManaged Files
An administrative rebuildPreview siteAdmin Rebuild
The automatic catch-up after a live publishPreview sitePublished Files into Staging
Push preview liveLive sitePromoted Preview => Public

Every deployment row is stamped with the badge in the right-hand column, so the history tells you what a build was for without expanding it — the full badge list is here.

A logo or favicon upload is the one row worth reading twice: the file is committed to your live branch the moment you upload it, but it does not start a build. It appears on your site at your next deployment, whatever that deployment happens to be for.

Template files never appear in the Pending changes list, because they are not edited in the CMS: they reach preview through a developer’s leed site push. A developer’s leed site push is the other way content reaches preview, traced step by step.

flowchart TB
    CMS["CMS publish<br/>pages, settings, menus, labels, forms"] --> MAIN
    PROMOTE["Push preview live"] --> MAIN
    CLI["leed site push"] --> STG
    MF["Managed-file refresh"] --> STG

    subgraph REPO["One site repository"]
        MAIN["main branch"]
        STG["staging branch"]
    end

    MAIN -. "automatic rebase after every live publish" .-> STG
    STG -. "merged on promotion" .-> MAIN

    MAIN --> PW["Live site worker"] --> PROD(["example.com"])
    STG --> SW["Preview site worker"] --> STAGE(["staging.example.com"])

Publishing live also rebuilds preview

Click Publish 3 to live site once and two rows appear — one under Live site, one under Preview site. That is not a bug and you have not published twice.

After a live publish, Leed rebases staging onto main and fires a parallel preview build so the preview site does not silently fall behind the live one. Without it, preview would be missing every CMS change you ever published, and reviewing it would tell you nothing. The catch-up row is badged Published Files into Staging and is initiated by the system rather than by you.

Two live builds skip it, both for the same reason — nothing has moved that preview does not already have:

  • a promotion, because preview is by definition already in sync with what you just released;
  • an administrative rebuild, because the live branch’s content did not change.

What the preview site does not do

The preview site is a full build of your site with four deliberate holes in it. All four are enforced at the edge, before your site’s code runs.

  • Analytics events are swallowed. The tracking endpoint answers 204 and records nothing. Traffic to your preview site never appears in your analytics, which is what you want — reviewing your own site all afternoon should not distort your numbers.
  • Form submissions are swallowed. A form on preview answers 204 and creates no contact and no submission. The form will look like it worked, because the response is a success.
  • The Docs MCP and the site agent surfaces answer 404. The reader-facing MCP endpoint and the agent discovery documents are published-site features only.
  • Once your custom domain is connected through Domain Connect, preview’s temporary workers.dev address is switched off, leaving staging.yourdomain as the only way in. If you set your DNS up by hand instead, that switch-off never fires and the temporary address keeps working.

Preview is private-by-convention, not by lock

The card on the Deploy screen calls the preview site “a private staging copy”. Read that as not advertised, not as protected.

Telling the two apart from the outside

Every response from either site carries two headers:

  • X-Preview — true on the preview site, false on the live site.
  • X-Site-Version — the git commit the site was built from.

Together they answer both versions of “am I looking at what I think I’m looking at”: which site is this, and is this the build I just published? A request for the headers alone is the fastest check there is.

curl -sI https://staging.example.com/ | grep -i '^x-'
x-site-version: 9f3c1ab4e07d5b2a6c81f4d3e9027ab5c6d18e4f
x-preview: true

If X-Site-Version still shows the old commit after a deployment went Active, you are looking at a cached response rather than a stale build — request the URL again with a cache-busting query string before assuming the deployment failed.

When to promote

Preview is worth using when the change is one you cannot judge from a single page: a template edit, a navigation restructure, a styling change, anything a developer pushed. Look at the whole site on staging.yourdomain, click through it, and when you are satisfied, release it.

That release is a single button — Push preview live on the Preview site card. It moves everything on preview to live as one deployment; you cannot promote a subset. Promoting preview to live covers what it moves, who can press it, and every reason it is grayed out.

Before your own domain is connected, both sites answer on Leed-provided workers.dev addresses rather than example.com and staging.example.com, and the CMS’s Visit-site buttons point there. Setting the CNAME records yourself is the manual path; the one-click path is on the same page.

ESC