Responsive Breakpoints

SkillMedia

Lets your agent add, edit, and manage responsive breakpoints in a design across mobile, tablet, and desktop widths.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the Responsive Breakpoints skill

About this skill

Framer-style responsive breakpoint editing in Design: one DOM tree per screen with cascading width-scoped overrides. Use when adding/removing breakpoints, editing a design at a specific device width, resolving which value renders at a width, or persisting responsive style changes.

What this skill tells your AI

The instructions your AI receives, as published by builderio/agent-native in templates/design/.agents/skills/responsive-breakpoints/SKILL.md and read by ahel’s review.

Design uses the Framer model: every screen is ONE document (one DOM tree). Breakpoint frames are the SAME document rendered at different viewport widths — never separate copies. Edits cascade:

  • The base is the primary (widest) frame. Base edits are plain unprefixed classes / inline styles and cascade down to every narrower breakpoint unless overridden there.
  • Edits made while a narrower breakpoint is active persist as width-scoped overrides that apply from just below the next-wider frame down to zero. Narrower breakpoints layer their own overrides on top.

The bound for an override is next-wider frame width - 1 (e.g. breakpoints 390/810 with a 1280 primary: editing 810 scopes to ≤ 1279px, editing 390 scopes to ≤ 809px). breakpointUpperBoundPx in shared/responsive-classes.ts is the canonical implementation.

Managing breakpoints

A newly generated design's frame set comes from generate-design's devices param (("mobile"|"tablet"|"desktop")[], default ["desktop","mobile"]). The cascade is desktop-base: the widest requested device is the primary/base frame and each narrower device is a breakpoint frame. The default injected set is therefore a Desktop base plus a single Mobile (390) breakpoint frame — the narrower frame(s) only, never a frame at the primary desktop width and never an auto-added tablet.

  • add-breakpoint — adds a device-width frame to designs.data.breakpointSet (Framer defaults: Desktop 1200 / Tablet 810 / Phone 390, or custom 320-3840). Duplicate widths are ignored.
  • remove-breakpoint — removes one by id (overrides already written stay in the document until removed).
  • set-active-breakpoint — persists the active edit scope to application state (design-active-breakpoint:<designId>); the UI mirrors it in the design-selection state (activeBreakpointId). Check the active breakpoint via view-screen before making responsive-only edits. Its editScope is cascade-smaller by default (edits at this breakpoint also apply to every narrower one); pass only when the user explicitly wants a bounded, breakpoint-only override.

The UI's breakpoint bar (chips above the focused screen) and the overview's side-by-side linked frames drive the same state — a chip click changes the iframe viewport width AND calls set-active-breakpoint.

Editing responsively (agent parity)

Use apply-visual-edit with activeFrameWidthPx set to the ACTIVE breakpoint frame width. This scopes BOTH class and style intents uniformly through one class-vs-media decision:

  • Values that are Tailwind utilities (text-lg, p-4) become width-scoped classes: max-[809px]:text-lg (arbitrary max-width variants the Tailwind CDN JIT compiles to @media (max-width: 809px)).
  • Raw CSS values (137px, rgb(...), calc(...)) persist into the managed <style data-agent-native-breakpoints> block as @media (max-width: <bound>px) rules targeting the element's data-agent-native-node-id. The block is deterministic (wider buckets first so narrower ranges win by source order) and readable/editable in the Code panel.

Other targeting options:

  • maxWidthPx — explicit desktop-down bound, overrides derivation.
  • intent.kind: "breakpoint-style" — direct managed-media write/remove: { target, maxWidthPx, property, value, operation: "set" | "remove" }.
  • activeBreakpoint: "md" etc. — LEGACY min-width prefix scoping for class edits only (mobile-first md:text-lg). Still supported for documents authored mobile-first; prefer activeFrameWidthPx for breakpoint-bar parity.

When the design has no breakpoint set, activeFrameWidthPx falls back to the legacy min-width prefix behaviour for class edits. When the active frame IS the widest context, edits are base writes (correct — the widest frame is the base).

Resolving and inspecting overrides

  • effectiveUtilityAtWidth(className, stem, widthPx) — which utility renders at a width (narrowest applicable max-width scope wins, then min-width prefixes, then base).
  • getBreakpointOverrideState({ className, html, nodeId, property, breakpointWidths, baseWidthPx, activeWidthPx }) from shared/breakpoint-media.ts — aggregates class + media overrides for the inspector's overridden-at-this-breakpoint indicators.
  • To RESET an override: remove the scoped class (responsive-class remove with maxWidthPx + stem) or the media rule (breakpoint-style with operation: "remove"); the base value cascades back down.

Cautions

  • Managed media rules anchor on data-agent-native-node-id. Inline (SQL) designs keep these ids; localhost write-back strips them — for local-file sources prefer scoped classes.
  • Never rewrite the managed block wholesale by hand; use the edit intents so same-property writes replace instead of accumulate. The parser tolerates Code-panel edits but unknown selectors are ignored.
  • Adding a breakpoint between two existing widths changes the bound for NEW overrides only; previously written overrides keep their original bounds.

Signals

GitHub stars
7k
Forks
613
Last commit
Sep 2026
Advanced
Item type
skill
Key
responsive-breakpoints
Source
github.com/builderio/agent-native