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

> Discover how Instatic powers simultaneous multi-breakpoint editing. Learn about its iframe rendering and Zustand store for efficient responsive design workflows.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: internals
- Published: 2026-07-30

---

**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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/src/admin/pages/site/store/slices/visualComponentsSlice.ts), every node follows this TypeScript shape:

```typescript
{
  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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/src/core/publisher/renderNode.ts) resolves final property values by performing a shallow merge:

```typescript
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`](https://github.com/CoreBunch/Instatic/blob/main/siteSlice.ts), providing valid IDs for the entire application.
- **Per-node overrides** use a `breakpointOverrides` map in [`visualComponentsSlice.ts`](https://github.com/CoreBunch/Instatic/blob/main/visualComponentsSlice.ts) to store breakpoint-specific property patches.
- **Multi-frame canvas** renders each breakpoint in isolated iframes controlled by [`canvasSlice.ts`](https://github.com/CoreBunch/Instatic/blob/main/canvasSlice.ts), enabling simultaneous editing without CSS conflicts.
- **Override detection** in [`usePropertiesPanelData.ts`](https://github.com/CoreBunch/Instatic/blob/main/usePropertiesPanelData.ts) prevents unauthorized property modifications and shows visual indicators for customized values.
- **Publishing resolution** in [`renderNode.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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.