Previews
A preview lets you see the real WordPress site rendered with a selected app or worktree theme, before any of the work is deployed. It is how a reviewer judges proposed theme changes without affecting a single live visitor: opening a preview never makes a worktree live, it only swaps the theme for that one request while WordPress posts, options, users, plugins, sessions, and uploads stay the live site’s data.
The signed preview context
Everything a preview does happens inside a signed Divine preview context. Outside that context, WordPress behaves normally: the active theme serves the frontend, and admin, REST, cron, feeds, search, sitemaps, login, and normal WP_Query all use the live theme and live data. A request only enters a preview context when it carries valid Divine preview signalling, and for the duration of that one request Divine points stylesheet, template, and the theme directory at the selected app or worktree theme.
This is a theme swap, not a database sandbox. The value of a preview is precisely that it shows how proposed theme files behave against the real site data, so a template, page, block, or asset change can be exercised end to end against the content that actually exists. The contrast between what a preview changes and what it leaves alone is shown below.
| Swapped inside a preview | Stays the live site |
|---|---|
stylesheet, template, and the theme directory |
Posts, pages, options, and uploads |
| Theme files, templates, pages, and blocks | Users, sessions, and login state |
| Worktree file changes | Installed plugins and their behavior |
Canvas renders worktree pages virtually
The Divine canvas renders worktree pages directly from files. A worktree page is a theme file under pages/, and the canvas renders it as a snapshot from that file. By design it does not create a wp_posts row for the page, and the page is not added to the WordPress pages list. This keeps an in-progress page entirely inside the worktree’s theme files until its files are deployed into the app theme, so previewing a brand-new page never writes anything into the database.
Because the canvas works from files rather than published posts, it can show pages and blocks that do not exist as real URLs yet. That is the point: you can build and review a page as theme code, see it rendered, and iterate on it before WordPress has any notion that the page exists.
The browser shows real URLs
The browser view is different from the canvas. It opens the normal site URL, so it shows the site exactly as a visitor would reach it, with the selected app or worktree theme swapped in. A same-origin service worker keeps that browser tab pinned to the selected target by attaching two pieces of state to each same-origin page request: the X-Divine-Worktree header naming the target, and a Divine preview token header. The address bar stays the clean site URL, so browser history, server logs, and copied links do not expose which worktree is selected.
The service worker injects these headers only for same-origin frontend requests; it bypasses admin. Because the browser resolves real URLs through WordPress, a worktree page that exists only as a file has no real URL to open there yet. Use the canvas to render worktree-new pages from files, and use the browser to walk the real site with the worktree theme applied. This split is intentional, and a worktree-new page returning a normal WordPress 404 in the browser is expected rather than a bug.
The block editor edits main pages only
The native WordPress block editor edits main WordPress pages only. It never edits worktree pages. Worktree pages are theme files, rendered by Divine’s canvas and previews, and they are not represented as editable posts. So when you open the block editor, you are editing the live site’s pages on the app, not the file-based pages inside a worktree.
This boundary keeps the two systems from blurring. File-based worktree pages flow through the worktree, its review step, and deploy as files. Database-backed pages flow through the WordPress editor as posts. Neither one quietly becomes the other.
Tokens are purpose-scoped and time-limited
A Divine preview token is a viewing credential and nothing more. Each token is issued for a specific purpose and a specific theme target, and it carries an expiry. Divine stores only a hash of the token, never the raw value, and checks it on every request. Once a token is expired, revoked, or otherwise invalid, Divine refuses the preview and falls back to the live theme rather than guessing.
The two purposes are summarized below.
| Purpose | Used for | Notes |
|---|---|---|
session |
The in-app browser preview | Bound to the issuing user; the in-app worker keeps it attached to same-origin navigation. |
share |
A capturable or shareable preview URL | Carried in the URL and validated on each request; expires and can be revoked. |
Tokens are also scoped to their target. A token records the stylesheet, the app slug, and the blog_id it was issued for, and validation rejects it if any of those do not match the registered worktree or the current site. Session tokens additionally fail when used by a different user than the one they were issued to. The default lifetime is one hour, with a minimum floor, and expired records are pruned after a retention window.
How dv show returns capturable URLs
dv show constructs capturable render URLs that resolve into this same signed preview context. It does not capture screenshots itself; it prints a URL, and the agent or browser tool that opens the URL takes the picture. To make the URL resolve, dv show issues a share preview token for the requested app or worktree target and appends it to the URL as a query parameter, so opening the URL enters the preview context for that one target.
dv show has two render modes. The default virtual mode produces a file-based render URL, the same files-only path the canvas uses, which is why it works for pages, blocks, and labeled comparisons including ones that have no real URL. The --live mode produces a real page URL for a page that exists, rendered with the worktree theme through the browser path. Blocks and compare URLs are virtual only, because they have no live URL to render. The commands are:
dv show page <slug> [--worktree X] [--live] [--width N]
dv show block <name> [--worktree X] [--width N]
dv show compare page:<slug>[@app|@worktree] block:<name>[@app|@worktree] [--width N]
Because each dv show URL carries a short-lived, purpose-scoped share token, treat the printed URLs as private. They render unfinished theme work, and like any preview they grant viewing only.
Sharing previews responsibly
Even though a preview grants no power to act, treat the URL as private. A preview can expose unpublished layouts, work-in-progress templates, or functionality an agent is still building, so share it only with people who are meant to see the proposed change. A share link grants no admin access and no ability to change files; an invalid, expired, or revoked link fails closed and renders the live theme. Deploying or destroying a worktree invalidates its preview state, so once a worktree is resolved its preview sessions and share links stop working on their own.