feat(cms): fast preview via preview server + branch-aware new chat - #5215
Closed
tlgimenes wants to merge 8 commits into
Closed
feat(cms): fast preview via preview server + branch-aware new chat#5215tlgimenes wants to merge 8 commits into
tlgimenes wants to merge 8 commits into
Conversation
Preview / Fast Preview - Add Fast Preview: render the current draft against an always-on preview server via /live/previews (pushing the working-tree decofile as a per-request override) instead of waiting for the sandbox dev server. - buildInstantPagePreviewUrl() builds the cross-origin GET URL with a URL-size cap (falls back to the published route past it). - Fast Preview NEVER swaps to the sandbox surface — it previews only on the preview server; the waking pill tracks the sandbox itself (FS/handle), not the dev server. Fast Preview off keeps the published-fallback-then-swap behavior. - URL-bar domain follows the iframe (buildPreviewLabel); open-in-new-tab is hidden unless a real sandbox iframe is shown. Settings - New CMS section: Preview (preview server URL + Fast Preview switch) + Publishing (moved in, extracted PublishPolicyField). Business-friendly copy, en + pt-br. New chat: inherit the current branch - The New chat button now creates the thread on the branch/sandbox being viewed (not the hardcoded staging default). findReusableNewChat gains an optional, branch-aware match; createNewTask threads the branch through. "Open agent X" flows stay branch-agnostic. Branch button - Always show the current branch label (truncated) on the picker and locked chip, in the chat composer too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The New chat button reused an existing empty "New chat" (navigating to it) instead of creating one. Remove the reuse short-circuit from both entry points (header NewChatCrumb + sidebar handleNewThread) so every click creates a fresh thread on the current agent + branch. - Drop the now-dead isThreadEmpty helper + its MCP client, and the reuse branch in NewChatCrumb (with its unused session/setTaskId). - findReusableNewChat no longer takes a branch (no remaining caller passes one); revert its branch-aware tests. It stays branch-agnostic for the "open agent X" flows that still reuse (navigate-to-agent, org-home, picker). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The branch selector lived inside the header's shrink-0 "never clip" right cluster, so it held full width while the centered address bar (page selector) truncated. Give the branch its own min-w-0 shrinkable slot so it yields first; keep the real actions (Edit / Submit / Publish / ⋯) shrink-0 and as the only thing rightRef measures, so the tab-count budget is unchanged. The address bar is flex-1 (basis 0) and now shrinks last. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Below `lg` (< 1024px) hide the branch label on both the picker and the locked chip, leaving an icon-only control; the branch name stays available via the already-wired tooltip. Mirrors how the view tabs collapse their labels (`max-md:hidden`). Only the branch button qualifies — the other header actions (Publish / Submit, Develop / Live) are text-only with no icon fallback, and Open-in-board is already icon-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Give the text-only header actions leading icons so they collapse to icon-only
below `lg` (< 1024px), with the label kept in the tooltip; desktop is unchanged
(text label at `lg`+):
- Primary action button: icon keyed off `button.action` (create-pr →
GitPullRequest, rebase/reopen → RefreshCw01, fix-checks → AlertTriangle,
mark-ready → CheckCircle, resolve-comments → MessageCircle01). Loading pills
collapse to spinner-only; plain status pills (Up to date / Published /
Awaiting review) keep their text.
- Side Publish button: Upload01 icon below lg.
- Develop / Live toggle: Code01 / Globe01 icons, labels hidden below lg (title
tooltip + aria-label retained).
merge-split ("Publish to <base>") renders via MergeSplitButton and is left as
text for now.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
In Fast Preview the draft is embedded in the iframe URL (`instantDraftUrl`), so a Blocks edit — which optimistically updates the decofile into a new URL — should re-navigate the frame. It didn't: the shared reload path can't `.reload()` a cross-origin frame, and the same-URL src assignment is a no-op. Drive it explicitly: when the instant URL changes (i.e. the decofile changed), point the frame at the fresh URL. Uses the already-correct optimistic decofile (revert-safe — no refetch of a possibly-committed stale blocks.gen.json), and is naturally debounced by the existing write debounce (useDebouncedSaveBlock). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The GET-with-decofile-in-URL approach fell over on real storefronts: the decofile blows past the URL/edge request-line limit, so `instantDraftUrl` came back null and the preview silently showed the published page. Render server-side through the sandbox daemon instead: - New public daemon route `GET /_deco/fast-preview` (packages/sandbox/daemon): merges `.deco/blocks/*` (dep-free, no dev server), POSTs it to the site's production `/live/previews/<component>` (which already accepts a JSON `__decofile` body — no production change, no CORS, no URL cap), and returns the HTML with an injected `<base href>` so assets resolve against production. All async (fs + fetch) per the daemon's single-thread rule. - Thread `productionUrl` (from `metadata.productionUrl`) to the daemon config: Workload → SANDBOX_START → buildConfigPayload / link-daemon → daemon `Application.productionUrl`. - Web: the Fast Preview frame now loads the daemon route (`previewUrl` origin) via `buildFastPreviewDaemonUrl` — the decofile is NOT in the URL. Falls back to the published page while the sandbox provisions. Removes the old `buildInstantPagePreviewUrl` GET builder + its test. Save → refresh: on a `.deco/*` write the daemon emits `file-changed`; the events gate is relaxed so Fast Preview reacts even with no dev server, and the handler bumps a nonce (new daemon URL → the frame re-navigates → the daemon re-reads the just-saved blocks). No decofile refetch in that mode (the daemon reads disk directly; refetching could revert an optimistic edit). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fast Preview was falling back to `new URL(path, productionUrl)` (the published page, e.g. fila.vtex.app) whenever the daemon render URL wasn't ready — a page not yet matched, or the sandbox still provisioning. That fallback shouldn't exist: Fast Preview is the daemon draft render or nothing. resolvePreviewDisplay now handles Fast Preview up-front: once the sandbox handle exists it renders on the daemon origin (`previewUrl`), and until then it shows the booting overlay — never `productionUrl`. preview.tsx drops the published fallback in that mode and shows the overlay while the daemon URL is null. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 24, 2026
Contributor
Author
|
Split into three focused PRs (same commits, cleanly separated by concern — the file sets are disjoint):
Closing this in favor of those. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CMS Fast Preview (render drafts against an always-on preview server, no dev-server wait), a reworked agent-settings CMS section, a New chat fix (always creates, on the current branch), and a set of header UX improvements (branch label, truncation priority, and small-screen icon-only actions).
1. Fast Preview
/live/previews(decofile pushed as a per-request, ALS-isolated override) — no waiting for the sandbox dev server.buildInstantPagePreviewUrl()builds the cross-origin GET URL with a URL-size cap; past it, falls back to the published route.blocks.gen.jsonreadable), not the dev server.buildPreviewLabel); open-in-new-tab is hidden unless a real sandbox iframe is shown.2. Settings — CMS section
PublishPolicyField). Business-friendly copy, en + pt-br.3. New chat — always creates, on the current branch
staging).createNewTaskthreads the branch through (panel-actions + keyboard paths). "Open agent X" flows still reuse an empty chat, branch-agnostically. No backend change — the wire schema already acceptsbranch.4. Header / small-screen UX
flex-1, shrinks last), while the publish/⋯ actions stayshrink-0and never clip.lg(< 1024px) the header collapses to icon-only + tooltip: the branch button, the primary action button (icon keyed offbutton.action—GitPullRequest/RefreshCw01/AlertTriangle/CheckCircle/MessageCircle01), the side Publish button (Upload01), and the Develop/Live toggle (Code01/Globe01). Loading pills collapse to spinner-only; plain status pills (Up to date / Published / Awaiting review) keep their text. Desktop is unchanged.Testing
preview-display.test.ts(13),preview-label.test.ts(7),section-preview-url.test.ts,reusable-new-chat.test.ts(8).bun run check(web + shared) andbun run lintpass; formatted with Biome. Layout/copy-only changes have no unit tier.Notes / follow-ups
blocks.gen.json) still works.renderToString) — no hydration/JS interactivity/in-page navigation. Lifting the URL-size cap (POST proxy / draft cookie) is a natural follow-up for large sites.merge-split("Publish to<base>") renders viaMergeSplitButtonand is still text belowlg(not yet iconified).bun install+ the dev script at boot (the decofile is a dep-free FS merge) and boot them lazily on first need — behind a default-off flag.🤖 Generated with Claude Code