How Instatic Handles Simultaneous Multi-Breakpoint Editing in Its Visual Editor

Instatic enables designers to edit multiple responsive breakpoints at once by rendering each viewport in separate iframes while storing per-breakpoint overrides in a centralized Zustand store.

The CoreBunch/Instatic repository implements a sophisticated visual editing system that allows real-time manipulation of responsive designs across desktop, tablet, and mobile viewports simultaneously. Unlike traditional editors that force context switching between device previews, Instatic's architecture maintains a multi-frame canvas where each breakpoint operates as an isolated iframe sharing a single source of truth through Immer-based state management.

Global Breakpoint Configuration

All responsive breakpoints for a site are defined in the global store at src/admin/pages/site/store/slices/siteSlice.ts. Each breakpoint object contains an id, width value, and optional media query string. The slice exposes CRUD operations through createBreakpointActions, allowing users to add, update, or delete breakpoints dynamically.

When a user creates a new breakpoint, it registers immediately across the entire application state. This global registration ensures that every component in the tree can reference valid breakpoint identifiers when storing or retrieving override values.

Per-Node Breakpoint Override System

The editor stores style variations using a breakpointOverrides map attached to each node in the visual component tree. According to the source structure in src/admin/pages/site/store/slices/visualComponentsSlice.ts, every node follows this TypeScript shape:

{
  id: string,
  moduleId: string,
  props: Record<string, unknown>,
  breakpointOverrides: {
    [breakpointId: string]: Record<string, unknown>
  },
  children: [...]
}

This architecture allows any node to maintain base properties while overriding specific values for individual breakpoints.

Override Management Actions

The siteSlice.ts file implements two primary actions for managing these variations:

  • setBreakpointOverride(nodeId, breakpointId, patch) – Merges the provided property patch into the node's breakpointOverrides[breakpointId] object using Immer's immutable updates.
  • clearBreakpointOverride(nodeId, breakpointId) – Removes the specific breakpoint entry entirely, causing the node to revert to its base property values.

These actions are dispatched whenever a designer modifies a property while a specific breakpoint frame is active.

Multi-Frame Canvas Architecture

The visual canvas operates in design mode using state managed by src/admin/pages/site/store/slices/canvasSlice.ts. Rather than resizing a single viewport, Instatic renders one iframe per breakpoint side-by-side, each containing an independent document environment.

Simultaneous Viewport Rendering

Each iframe maintains its own rendering context while subscribing to the same underlying Zustand store. This isolation prevents CSS cascade conflicts between breakpoints while allowing simultaneous visualization of all responsive states. The canvas slice tracks two critical identifiers:

  • breakpointId – Denotes the currently focused frame that receives user input events.
  • activeBreakpointId – Tracks which breakpoint tab is selected in the inspector panel.

Focus and Active State Management

The canvas slice also manages frame visualization states, including whether specific breakpoint frames are collapsed (showing only slim headers) or expanded to full editing height. When designers click between frames, the breakpointId updates immediately, shifting input focus without requiring a page reload or state reconciliation delay.

Editing Workflow and Override Detection

When a user modifies a property in the inspector panel, the system follows a precise resolution path defined in src/admin/pages/site/panels/PropertiesPanel/usePropertiesPanelData.ts.

Properties Panel Integration

The panel performs three sequential operations:

  1. Retrieves the active node and current activeBreakpointId from the store.
  2. Checks selectedNode.breakpointOverrides[activeBreakpointId] to determine if the current value represents an override or inherited base value.
  3. Validates schema permissions by verifying the property definition includes breakpointOverridable: true before allowing modification.

Only properties explicitly flagged as breakpoint-overridable can receive override values, preventing accidental fragmentation of critical structural data.

Real-Time Synchronization Across Frames

All breakpoint iframes share the same Zustand store instance via React context. When setBreakpointOverride dispatches an update, Immer produces a new immutable state that automatically propagates to every connected iframe. The design canvas displays a visual "override" indicator (typically a dot or highlight) for any property that diverges from the base value at the current breakpoint, giving designers immediate feedback about responsive customizations.

Publishing with Breakpoint Resolution

During static site generation, the publisher at src/core/publisher/renderNode.ts resolves final property values by performing a shallow merge:

const effectiveProps = {
  ...node.props,
  ...(node.breakpointOverrides[breakpointId] || {})
};

This merging strategy ensures that published HTML contains the correct responsive values for each breakpoint context. The renderer processes each breakpoint independently, generating appropriate media queries and style sheets that reflect the overrides created during visual editing.

Summary

  • Global breakpoint definitions reside in siteSlice.ts, providing valid IDs for the entire application.
  • Per-node overrides use a breakpointOverrides map in visualComponentsSlice.ts to store breakpoint-specific property patches.
  • Multi-frame canvas renders each breakpoint in isolated iframes controlled by canvasSlice.ts, enabling simultaneous editing without CSS conflicts.
  • Override detection in usePropertiesPanelData.ts prevents unauthorized property modifications and shows visual indicators for customized values.
  • Publishing resolution in renderNode.ts shallow-merges base props with overrides to generate responsive HTML output.

Frequently Asked Questions

How does Instatic prevent style leakage between simultaneous breakpoint frames?

Each breakpoint renders inside its own sandboxed iframe with an independent document object model. Because the iframes are isolated browsing contexts, CSS styles from one breakpoint cannot cascade into another, allowing safe simultaneous display of conflicting responsive layouts while they share the same Zustand state through post-message or shared context bridges.

Can multiple team members edit different breakpoints simultaneously?

While the source code shows the technical capability for concurrent breakpoint editing through the shared store architecture, the breakpointId and activeBreakpointId fields in canvasSlice.ts track a single user session's focus state. True multi-user simultaneous editing would require additional operational transform logic or real-time collaboration layers not visible in the current slice implementations.

What happens when a breakpoint is deleted after overrides exist?

The analysis indicates that clearBreakpointOverride requires explicit invocation. If a breakpoint ID is removed from the global store without cleaning up references in node breakpointOverrides objects, those override entries likely persist as orphaned keys in the state until manually reconciled, though the renderNode merge logic would treat missing breakpoint IDs as empty objects, effectively falling back to base values.

Which properties support breakpoint overrides?

Only properties marked with breakpointOverridable: true in their schema definitions can be overridden according to the logic in usePropertiesPanelData.ts. This restriction prevents fragmentation of structural properties (like component IDs or module references) while allowing style attributes (padding, colors, font sizes) to vary across breakpoints.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →