Frames tab redesign, per-frame variant replace, and cache fixes
This release redesigns the Frames tab, enables per-frame replacement for variant frame sets, fixes variant re-render cache invalidation, and improves the dashboard's confirmation dialogs.
Frames tab redesign
The Frames tab has been replaced with a grid layout and now supports all variant frame sets alongside the base model.
- Grid layout — frames render in a
repeat(auto-fill, minmax(88px, 1fr)) grid instead of a horizontal film strip. Every frame is visible at once without horizontal scrolling.
- Source selector — a pill bar above the grid lets you switch between the base model and any Ready variant. The active source is highlighted; pending variants are shown at reduced opacity.
- Row selector — multi-row projects show row buttons above the grid. Switching source resets the row selection to prevent out-of-bounds frame requests.
- START badge — the starting frame is marked with a green badge. Only the base model tracks a starting frame.
- Hover actions — hovering a base model frame shows Set as start and Replace. Hovering a variant frame shows Replace only.
Per-frame replace for variants
Individual frames in a variant frame set can now be replaced without re-rendering the entire variant.
Hover any frame while a variant source is selected and click Replace. Upload a replacement image in the same format as the project's export. On confirmation:
- The new frame is uploaded directly to R2.
RenderVersion is bumped so CDN and browser caches immediately serve the updated frame.
- The embed viewer data cache is invalidated.
New API endpoints:
POST /api/projects/{projectId}/colorways/{colorwayId}/frames/{frameIndex}/generate-replace-url
POST /api/projects/{projectId}/colorways/{colorwayId}/frames/{frameIndex}/confirm-replace
Both follow the same request and response shape as the existing base model frame replace endpoints.
Variant re-render cache busting
Re-rendering a variant previously had no visible effect because the frame URLs were unchanged and CDN/browser caches served the old images.
Variants now carry a RenderVersion field. Every successful complete-upload bumps this value to the current Unix timestamp. The frameUrlTemplate returned by the API appends ?v={renderVersion} to all frame URLs, forcing CDN and browser caches to treat them as new resources.
Preview tab variant switching
The Preview tab now includes a Variants panel above the viewer config. Switching between Base model and any ready variant updates the Player360 embed in real time so you can compare renders without leaving the tab.
Re-export embed cache fix
After re-encoding a project from the Export tab, the embed's Next.js ISR cache was not being invalidated. Embeds served stale frames until the ISR window expired.
revalidateEmbedCache is now called immediately after every successful re-encode so the embed reflects the new frames without delay. The distributed viewer data cache was already evicted on complete-upload; this fix closes the separate ISR layer.
Delete confirmations with type-to-confirm
All destructive actions in the dashboard now use modal dialogs with a type-to-confirm input instead of browser confirm() prompts.
- Project delete, variant delete, and hotspot delete each require typing the item name (or
confirm for untitled items) before the delete button activates.
- The name is displayed inline as a monospace chip with a copy icon. Clicking the icon copies the name to the clipboard so it can be pasted directly.
- Pressing Enter submits when the input matches.
- The embed override reset dialog uses a simple Cancel / Confirm flow without a typed input.