Changelog

What's new and what's next for Scamp.

v0.7.0 — Flex, transforms, and Electron 44

Electron 44, the full flex vocabulary in the panel, a Transform section, and better guidance for coding agents.

Every flex control, in the Layout and Size sections shipped

  • Layout gains Wrap, a Reverse toggle on its own row, Align content, and separate Row gap and Column gap inputs
  • When an element sits in a flex container, the Size section gains an Advanced disclosure with Grow, Shrink, Don't shrink, Basis, Align self, and Order
  • Everything is written as longhand CSS, and hand-written flex CSS round-trips back into the panel, including the flex shorthand
  • Drawing a box into a flex container, or typing a pixel size on its main axis, turns Don't shrink on so the box keeps the size you gave it. Flex layout

A Transform section shipped

  • Add translate, rotate, scale, and skew functions in order, and set the transform origin from nine presets or any CSS value
  • Hand-written transform lists parse into the same rows. Transforms

Agents learn to create Scamp components shipped

  • The MCP server now describes itself on connect, and a new scamp_get_component_scaffold tool hands an agent the exact starter files for a component, so it writes real component folders instead of a page of examples
  • agent.md gains a Scamp components section and page conventions
  • The MCP indicator says what's wrong. The dot in the terminal header is gray until an agent connects, green after one has, and amber when Claude Code has the server disabled for this project because you declined its prompt. In the amber state the copy button copies the command that brings the prompt back. Work with AI agents

Electron 44 shipped

  • Electron 31 to 44, with electron-vite 5, Vite 7, and Node 24
  • The clipboard and folder pickers are updated for the new APIs: choosing a project folder now starts from your default projects folder and remembers the last pick, rather than opening on Downloads
  • On Linux, Scamp runs through XWayland by default. Electron 44 crashes on startup under the native Wayland backend on some systems, so Scamp asks for X11 and restarts itself once at launch. Set SCAMP_OZONE_PLATFORM=auto to opt back into native Wayland
  • A new Linux page in the user docs explains the Wayland behaviour and how to opt out. Linux

Changes shipped

  • User docs and the changelog follow the Google developer documentation style guide. Sentence-case headings, second person, present tense, and task headings as imperatives

Fixes shipped

  • Long page and component lists scroll inside their sidebar section, the way the layers list does, instead of scrolling the whole window
  • Saving from the CSS panel with Cmd+S no longer pauses sync. The app's own write was being reported back as an external edit, which showed a "nothing was saved" warning and paused syncing until the quiet window passed
  • Component instances fill at every breakpoint. An instance whose width was set to Fill at the Mobile breakpoint stayed at its desktop size on the canvas, while the preview filled correctly. The canvas now resolves the component's elements at the active breakpoint. Components

v0.6.6 — Click to select, not to move

A click inside a flex or grid container selects the element and nothing else.

Fixes shipped

  • Clicking an element inside a flex or grid container no longer moves it. Selecting one could send it to the end of its container, and selecting the last one could lift it out into a sibling, because a plain click was running the whole drag gesture
  • A mouse click emits no movement, but a trackpad tap emits a pixel or two of jitter — enough to resolve and commit a drop. Dragging now starts only after the pointer has travelled, so a click selects and nothing else
  • The same gap let a click near a container's edge reparent an absolutely positioned element; that's closed too. Canvas

v0.6.5 — Sign-in and HTML export

Sign-in arrives, the start screen gets a visual refresh, and the canvas starts rendering your page's real stylesheet instead of an approximation of it.

Sign in to a Scamp account shipped

  • An account panel at the foot of the start-screen sidebar. Signing in opens your browser, you approve there, and the app picks the result up on its own
  • Signed in, the panel shows your name, email, and a sign-out link
  • Everything is optional — Scamp works exactly the same signed out, never prompts you on launch, and there's nothing to dismiss
  • Your session lasts 30 days and renews whenever you use it, so it expires from disuse rather than on a clock
  • If your OS can't store the sign-in securely, the panel tells you so plainly rather than quietly forgetting you. Accounts

A refreshed start screen shipped

  • Project thumbnails. Each card shows a picture of the project's home page, recaptured whenever you save. Projects without one show their artboard color in the same space, so the grid stays even. Thumbnails live in <project>/.scamp/preview.png
  • The default projects folder moved from a block of sidebar chrome to a folder icon beside the Projects heading — hover for the path, click to change it
  • Project names are shown the way you read them: my-portfolio displays as "My Portfolio", with the folder name still on hover and used unchanged on disk
  • "Last opened" now stays readable past a day. It steps through minutes, hours, days, weeks, months and years, where a project opened last week previously showed a bare "14:32" with no date. Getting Started

The canvas renders your page's real stylesheet shipped

  • ::before and ::after, :nth-child, and any hand-written selector now show up on the canvas
  • Previously they were parsed, preserved and written back to your files, yet stayed invisible while you designed — which mattered most for agent-written CSS, since agent.md recommends ::before for decorative touches
  • Component instances get their own scoped copy, so one instance's styles can't leak into another or into the page around them. Components

Breakpoints resolve against the artboard shipped

  • Breakpoints now resolve against the artboard, not the app window. A 390px frame fires your mobile breakpoint no matter how wide the Scamp window is, so what you see at each size is what a browser at that size will do. Breakpoints

Export a project as HTML shipped

  • A new Export HTML button in the project header writes every page as plain .html + .css into a folder you choose — no build step and no dependencies
  • Pages keep their routes (about/index.html), links between them are rewritten to work both on a static host and straight off disk, and images are copied into assets/
  • theme.css comes along so every token still resolves
  • Component instances are flattened into ordinary markup, each with its own copy of the component's styles, so per-instance sizing and text survive
  • You pick a location and Scamp creates a folder there named after the project — re-exporting reuses it, and a name held by anything Scamp didn't write is stepped over rather than overwritten
  • The button reports progress and the result — a spinner while writing, a green count when it lands, and a red Export failed with the reason on hover — so an export that declines to run can't be mistaken for one that did nothing. Export

Semantic color tokens accept a literal value shipped

  • A semantic row could only be pointed at a primitive; a hand-written value showed as "— custom —" and couldn't be edited
  • Rows now use the same color control as the properties panel, so you can map to a primitive, type a value, or use the picker and eyedropper
  • The picker offers primitives only — pointing one semantic token at another would put a reference cycle two clicks away. Colors

An image's Source is editable shipped

  • It was a read-only filename, and the only way to change it was Replace, which imports from your assets — so there was no route to an image you hadn't imported, including one at an absolute URL
  • It's now a text field that commits on Enter or blur. Elements

Changes shipped

  • Scamp runs as a single instance. Opening it again focuses the window you already have rather than starting a second copy. Required by sign-in, which needs one known place for the browser to hand its result back to
  • The Image section moved to directly after Element in the properties panel, matching what Typography already does for text — the thing you opened the panel for now leads the style sections. It used to sit twelfth, below Background, Border, Shadows and Filters
  • Background no longer offers "Set background image" on an <img>, where it read as a second source competing with the element's own. It still appears if a background image is already set, so one added elsewhere stays removable, and it's untouched for every other element. Properties Panel

Fixes shipped

  • Boxes drawn inside a flex or grid container keep the size you drew. They were being clamped against the parent, so a box drawn to fill a container came out smaller than the drag that made it
  • Fill height works in a flex row. It emitted height: 100%, which resolves against an auto-height container and computed to zero — the element simply vanished. It now emits align-self: stretch, and the Size panel still reads Fill
  • Links and buttons keep your page's styles. The canvas reset for semantic tags was overriding styling you'd set on <a> and <button>
  • Duplicate CSS declarations are still flagged when they change nothing. A property repeated with the same winning value produced identical code, so the warning was dropped — which is exactly the case where the duplicate has no other symptom to notice it by
  • Animated elements no longer stretch the artboard. Mid-animation positions were being counted as canvas extent, so the scrollable area grew and shrank while an animation played
  • position: absolute survives on a flex or grid child. It was being discarded on parse and then deleted from your file on the next save
  • position: sticky renders at rest on the canvas. A real sticky element stuck to the canvas viewport, so it drifted away from where it sits in the page as you panned, and its coordinates were read as scroll offsets. Your generated CSS is unchanged — this only affects the canvas
  • Grid gaps round-trip through the shorthand without drifting
  • Gradient backgrounds render on the canvas, not just in preview
  • Tooltips raised by a click no longer stick open
  • Sign-in's loopback listener no longer hangs when closing

v0.6.0 — Editing improvements

A batch of editing improvements, plus image compression on import.

Collapse branches in the layers tree shipped

  • A disclosure triangle on any element with children; Alt+click folds or unfolds the whole branch at once
  • A collapsed row shows a dot when your selection is hidden inside it, and selecting on the canvas expands whatever the element is nested in
  • Session-only — never written to project files, and reset when you switch page or component. Layers Panel

Cut, multi-select copy, and paste positioning shipped

  • Cmd+X cuts as a single undo step, and Cmd+C copies a multi-selection
  • Cmd+Shift+V pastes in place at the copied coordinates; right-click → Paste drops at the clicked point
  • Cmd+V now offsets from the copied position rather than pasting at the exact coordinates
  • Copy, Cut, and Paste added to the element right-click menu
  • Copying with the page selected takes everything on it. Canvas

Duplicates keep their name shipped

  • menu_a1b2 duplicates to menu_c3d4 instead of reverting to rect_c3d4, recursively for named children
  • Right-click → Duplicate added. Element Naming

Images are compressed on import shipped

  • PNG and JPEG are re-encoded to WebP, and anything larger than 3000px on its longest edge is scaled down to fit — a 7MB camera photo typically lands under 500KB
  • SVGs and existing WebP files are left alone, and the original is kept whenever converting wouldn't make it smaller
  • Conversion runs in a child process, so a large import never freezes the app, with an "Optimising image…" indicator over the container it's landing in. Elements

Anonymous usage counting shipped

  • Off unless you opt in. A random ID generated on your machine identifies the installation, not you; opting out deletes it
  • Toggle in Settings → Privacy. Settings

Drop targeting is unambiguous shipped

  • The middle of a container means "inside it"; its leading and trailing edges mean "beside it" — one shared rule for both the canvas and the layers tree
  • The destination container is outlined during the drag, and grid containers behave exactly like flex ones. Layers Panel

Fixes shipped

  • Choosing an image that's already in your assets folder links it instead of making a duplicate copy each time
  • Grid children can be reordered by dragging — previously only flex children could, and a grid child fell through to the absolute-move path where dragging did nothing
  • Pasting with a text, image, or input selected no longer nests the pasted element inside it
  • The layers tree no longer offers "drop inside" for images, inputs, and component instances
  • npm run test:unit and npm run test:integration were matching zero files and exiting as if nothing needed running

v0.5.7 — Working with AI agents

MCP server for coding agents shipped

  • Coding agents can query the live canvas — the open page, the element tree, the current selection, theme tokens, and breakpoints
  • A live context file kept up to date on disk, for agents that read files rather than call tools
  • Copy context for agent on the element right-click menu. Working with AI Agents

Code panel shipped

  • The selected element is highlighted in both the TSX and the CSS. Code Output

Documentation shipped

  • User docs for the AI agent features

v0.5.6 — Component fixes

v0.5.5 — Color and token picker polish

  • Color and token picker polish. Color Picker
  • Semantic color picker in the theme builder. Colors

v0.5.4 — Themes, fonts, and project cards

v0.5.3 — Layout control cleanup

v0.5.2 — Design system panel

Design system panel shipped

  • The token editor moved out of a side panel and into the main frame
  • Navigation moved to the sidebar
  • Palette and theme work throughout. Design System

v0.5.1 — Component canvas fix

  • Fixed canvas sizing inside components. Components

v0.5.0 — Component slots

Component slots shipped

  • Component instances can take page-owned content, so one component can wrap markup that belongs to the page it sits on. Components

Canvas and SVG shipped

  • SVG improvements. Elements
  • Aspect-ratio lock on resize, and canvas overflow controls. Canvas

v0.4.7 — Zoom control cleanup

  • Cleaned up the canvas zoom control. Canvas

v0.4.6 — Crash reporting fix

  • Fixed a Content Security Policy issue that was blocking crash reporting

v0.4.5 — Inline SVG

Inline SVGs are first-class elements shipped

  • Inline SVGs render as real <svg> on the canvas rather than a placeholder
  • They recolor reliably, are click-selectable, and are labeled in the layers tree. Elements

v0.4.4 — Drag to reparent

Drag to reparent on the canvas shipped

  • Drag an element into an absolutely positioned container to reparent it
  • Drag into a flex or grid container to drop it at a specific insert position. Layers Panel

v0.4.3 — Snapshot preview fix

  • Fixed a stuck snapshot-preview lock when canvas content is replaced. Snapshots

v0.4.2 — Updater error reporting

  • The updater shows the real error instead of a generic failure
  • App version added to Settings. Settings

v0.4.1 — Component sizing fix

  • Components no longer inherit the page root's 100vh floor

v0.4.0 — First tagged release

The first tagged build, containing the bulk of the app. Release attribution before this point isn't reliable — the notes below cover the capabilities that landed in this window.

Canvas, elements, and layout shipped

  • The canvas and element model — draw, select, move, resize, and nudge rectangles, text, images, and form inputs. Canvas
  • CSS Grid containers with column and row tracks and per-item placement. Grid Layout
  • Group and ungroup into flex containers. Grouping
  • Change an element's HTML tag without breaking its CSS class. Elements

Components shipped

  • Reusable components shared across pages, with a dedicated editor
  • Per-instance text overrides, and detach an instance back into plain elements. Components

Styling and theming shipped

  • Color picker with alpha, hex entry, project swatches, and theme tokens. Color Picker
  • Color tokens and typography tokens backed by a real theme.css. Design System
  • Hover, active, and focus styles via the State Switcher. Element States
  • Transitions between states, and preset keyframe animations with full timing control. Animations
  • Per-breakpoint overrides, with the canvas switching to the breakpoint's width. Breakpoints

Code, output, and the app itself shipped

  • Bidirectional file sync — real TSX and CSS Module files written as you design, and external edits reflected back on the canvas. Bidirectional Sync
  • Export the page or a selected element as PNG or SVG. Export
  • Preview mode running a real Next.js dev server. Preview Mode
  • Snapshots and the visual History panel. Snapshots
  • Crash reporting, automatic updates, and Windows/macOS packaging

v0.3.0

Box shadow shipped

  • New Shadow section in the WYSIWYG panel for every selected element, with a "+ Add shadow" button for stacking multiple shadows
  • Each row has X offset, Y offset, Blur, Spread, a color picker with hex and opacity, and an Inset toggle
  • Per-row visibility toggle and remove button; inset shadows get a subtle inset icon
  • Multiple shadows emit as a comma-separated box-shadow value and round-trip through the parser, single or stacked
  • Promotes box-shadow from a customProperties warning entry to a first-class control

CSS blend modes shipped

  • New "Blend mode" dropdown in the appearance section emits mix-blend-mode for every value other than Normal
  • Full value set grouped by Darken, Lighten, Contrast, Inversion, and Component
  • Separate "Background blend" dropdown maps to background-blend-mode, shown only when both a background color and a background image are set
  • Rendered natively on the DOM-based canvas; mix-blend-mode and background-blend-mode added to the parser property map
  • Related isolation: isolate round-trips cleanly through customProperties

Export pages and elements shipped

  • Export the full canvas viewport from the toolbar, or a selected element and its children from the right-click menu; Cmd+Shift+E exports the current selection
  • Export panel with format (PNG / SVG / PDF), scale, and a live size preview that remembers the last used settings per session
  • PNG export at 1x / 2x / 3x via html-to-image, capturing design content only with transparent backgrounds preserved
  • SVG export with a best-for-simple-layouts hint; PDF export via Electron's printToPDF() with Canvas / A4 / Letter / A3 page sizes and a portrait / landscape toggle
  • Read-only operation that reflects current canvas state and never touches project files

CSS filters shipped

  • New Filters section with a "+ Add filter" button; filters apply in order and reorder via drag and drop
  • Supports blur, brightness, contrast, grayscale, hue-rotate, invert, opacity, saturate, and sepia, combined into a single filter property
  • Per-row visibility toggle and remove button
  • Separate "Backdrop filter" toggle emits backdrop-filter with a hint about needing a transparent background
  • filter and backdrop-filter added to the parser, decomposed back into individual rows; unknown filter functions preserved in customProperties

Visual history panel shipped

  • History panel from the toolbar or Cmd+Shift+H listing up to 100 changes for the current session, most recent first
  • Human-readable entry labels (Drew rectangle, Changed [property] — [name], Pasted [name], etc.) with relative timestamps
  • Click any entry to jump backward or forward; the canvas, properties panel, and file on disk update immediately
  • Shares the same underlying undo stack as Cmd+Z / Cmd+Shift+Z; consecutive same-property changes within 500ms collapse into one entry
  • Per-page, in-memory history; element names update retroactively on rename, and external agent edits appear as a single "External edit detected" entry

Color picker rework shipped

  • Drag interaction now updates at 60fps by keeping picker state local during the drag and committing to the store only on mouseup
  • Eyedropper button samples any pixel on screen via the native EyeDropper API, with Escape to cancel
  • Recent colors row of the last 8 swatches; hex input expands shorthand (#fff#ffffff) and click-to-copy with a "Copied" confirmation
  • Separate numeric opacity input alongside the hex field
  • Same smooth local-then-commit pattern applied to the hue and opacity sliders

Crash reporting and feedback shipped

  • One-time opt-in prompt on first launch; Sentry is never initialised unless the user opts in
  • Privacy-safe configuration strips file paths, project data, and request data, sending only the error, OS, and app version
  • "Privacy" toggle in Settings enables or disables crash reporting immediately and persists the choice
  • "Report a bug" in Help opens a pre-filled bug report with app version and OS

Toggle CSS property groups shipped

  • Section header toggle comments out an entire group of properties at once as a labelled block (e.g. /* layout off */)
  • Covers Layout, Sizing, Background, Border, Shadow, Typography, Filters, Visibility, Blend, Transitions, and Animation groups
  • Toggled-off groups persist in the file, survive reloads, and show as inactive in the panel
  • Sizing toggle warns before collapsing an element; stretch-mode 100% width and height cannot be toggled off
  • Parser maps labelled comment blocks back to toggledOffGroups; the animation toggle leaves @keyframes in place

UA margin defaults round-trip on text tags shipped

  • margin: 0 on <p>, <h1>, <ul>, <blockquote>, and other text tags now survives generate → parse → generate cycles
  • Text tags with no margin declaration still render the browser's UA margin on the canvas
  • Per-element font-size changes no longer desync the canvas from what the browser would render
  • Extends the existing UA-aware tag-default model (previously padding-only on lists) to cover em-based text-tag margins

Adobe Fonts (Typekit) support shipped

  • Paste an Adobe Fonts embed link into the same Project Settings → Fonts box already used for Google Fonts
  • Accepts <link> and @import forms pointing at use.typekit.net
  • Each font family is listed below the paste box, matching the Google Fonts flow

Agent coexistence shipped

  • Makes Scamp safe to use while an external AI agent edits the same project files
  • External edits always win at the file level: if disk changed underneath, Scamp never overwrites
  • Sync engine backs off from active edit zones instead of racing bursts of external writes
  • Clear UI surfaces whether canvas changes are in-sync, paused, or diverged from disk

Components shipped

  • Convert any element and its children into a reusable component, or create a blank one from the components list
  • Each component lives in its own components/[Name]/ folder as PascalCase TSX and a CSS module
  • Dedicated component editor with the same canvas, properties panel, and CSS editor, plus a breadcrumb and an "editing affects all instances" banner
  • Drag a component onto any page to place an instance; edits propagate to every instance automatically via chokidar
  • New Data tab exposes each text element as a dynamic prop or a locked static string

v0.2.4

Per-element states (hover, active, focus) shipped

  • State switcher at the top of the properties panel: Default / Hover / Active / Focus
  • Edits made in a non-default state write to a pseudo-class block in the CSS module (e.g. .rect_a1b2:hover { ... })
  • Properties with overrides for the active state are highlighted; inherited properties show at reduced opacity with a "same as default" label
  • Only changed properties are written to the pseudo-class block — no redundant declarations
  • Dot indicator on each state button signals when overrides exist; clearing all overrides removes the pseudo-class block entirely
  • Pseudo-class blocks written directly after the base class block, grouped by element
  • Parser maps :hover, :active, and :focus back to state overrides; unrecognised pseudo-classes (:focus-visible, :checked, :disabled) preserved verbatim via customProperties

CSS animations (preset keyframes) shipped

  • New Animation section in the WYSIWYG panel with a searchable preset picker grouped by category
  • Property controls: Duration, Easing, Delay, Iteration (number or ∞), Direction, Fill mode, Play state
  • Selecting a preset writes the animation shorthand to the element and appends the @keyframes block to the bottom of the CSS module — one copy per file regardless of how many elements use it
  • Preset library covers entrances (fade-in, fade-in-up, slide-in-left, scale-in, bounce-in, etc.), exits (fade-out, slide-out-right, scale-out, etc.), attention (pulse, shake, bounce, spin, ping), and subtle loops (float, wiggle)
  • Play button in the panel triggers the animation once on the canvas; animations don't loop on the canvas during editing
  • Parser handles @keyframes blocks — recognised preset names map back to the picker, custom keyframes preserved verbatim
  • Custom @keyframes written by agents pass through customProperties untouched
  • Animations written inside @media (prefers-reduced-motion: no-preference) for accessible defaults

Preview mode shipped

  • "Preview" button in the toolbar (Cmd+P) opens a new window running a real Vite dev server pointing at the project folder
  • Real React, real CSS Modules, real HMR — transitions, animations, hover states, and links all work as they would in a true browser
  • Project folder auto-scaffolded with package.json, vite.config.ts, index.html, and main.tsx alongside design files; infrastructure files documented in agent.md as off-limits to agents
  • First open runs npm install automatically with a progress indicator; subsequent opens reuse the existing node_modules
  • Preview window toolbar: back, forward, refresh, read-only URL bar showing the current page, viewport width selector (Mobile 390 / Tablet 768 / Desktop 1440 / Custom)
  • Vite picks a random available port; only one server per project runs at a time and is stopped when the window or project closes
  • Optional [page-name].data.json files inject mock data into the auto-generated main.tsx so React expressions like {user.name} resolve to real values in preview — establishes the convention for full data binding later
  • Vite's error overlay surfaces TSX syntax errors with file and line number
  • Generated project is fully standalone — npm run dev from a terminal produces the same preview outside Scamp

Linking between pages shipped

  • "Link to" dropdown in the Element section of the WYSIWYG panel lists every page in the project plus an External URL option, with an "Open in new tab" toggle
  • Selecting a page writes a relative href matching the page file name (e.g. ./dashboard for dashboard.tsx)
  • If the element isn't already an <a> tag, Scamp wraps its content in one and writes both .tsx and .module.css atomically via the element:rename IPC pattern
  • External URL option accepts a free-text URL and opens in the system browser from preview mode, not the preview window
  • Removing a link clears the href and removes any auto-added <a> wrapper
  • Links navigate naturally inside the preview window via React Router; back/forward and the URL bar update to follow page history
  • Linked pages that are later deleted surface a "Linked page not found" warning on the canvas instead of silently breaking

v0.2.2

Visibility and opacity controls shipped

  • New Visibility section in the WYSIWYG properties panel for every element
  • Opacity — number input (0–100) and range slider, synced — maps to the CSS opacity property
  • Visibility — segmented control with Visible (default), Hidden (visibility: hidden), and None (display: none)
  • Elements with display: none stay visible on the canvas with a faded checkerboard overlay so you can still select them
  • Flex layout toggle auto-disables with a tooltip when an element is set to display: none
  • Round-trips through the parser and shows up in the raw CSS editor like any other property
  • Default values (opacity: 1) omitted from output to keep CSS clean

Typography tokens in theme.css shipped

  • New Typography section in the theme panel alongside Colors
  • Font sizes, font families, and line heights stored as CSS custom properties in theme.css
  • Token type inferred from the value — rem/px/em = size, quoted string = font family, unitless number = line height
  • Token picker next to font-size, line-height, and font-family inputs in the WYSIWYG panel
  • Autocomplete for typography tokens in the raw CSS editor
  • theme.css watched by chokidar — new tokens appear in the picker immediately
  • Add, rename, and delete typography tokens with the same flow as color tokens

Save status indicator shipped

  • Persistent indicator in the toolbar with four states: ✓ Saved, ↑ Saving…, ● Unsaved, ⚠ Save failed
  • Only shows Saved when canvas state, the file write IPC, and chokidar confirmation all agree
  • Save failed state shows a retry button and persists until the next successful write
  • Failed writes also logged to the terminal panel when it is open

HTML element types shipped

  • Change any rectangle or text element's HTML tag from a new Element section at the top of the properties panel
  • Rectangle variants: section, article, aside, main, header, footer, nav, figure, form, fieldset, ul, ol, li, details, summary, dialog, button, a
  • Text variants: h1h6, span, label, blockquote, pre, code, strong, em, small, time, figcaption, legend, li
  • Media variants: video, iframe, and svg alongside existing img
  • New input element type with its own toolbar button (F): input, textarea, select
  • Tag-specific attribute fields appear inline — href/target for a, type for button, for for label, rows/placeholder for textarea, etc.
  • Class name prefixes stay as rect_, text_, and img_ — only the tag changes
  • Unknown attributes round-trip through the parser untouched

Canvas size rework shipped

  • Root element defaults to width: 100%; height: auto — no more hardcoded pixel dimensions bleeding into exported CSS
  • Canvas viewport size (the white rectangle your design sits inside) is separate from root element CSS and saved in project metadata
  • Canvas height grows with its content, the way a real browser page does
  • Width presets in the toolbar: Mobile 390, Tablet 768, Desktop 1440, Wide 1920, or a custom value
  • Overflow hidden toggle clips content that extends past the viewport width
  • One-time migration notice on first open for existing projects

Mobile and tablet breakpoint toggles shipped

  • Toolbar viewport toggle: Desktop, Tablet, Mobile
  • Switching breakpoints resizes the canvas and scopes every edit to that breakpoint's @media (max-width: …) block
  • WYSIWYG panel shows the current value for the active breakpoint, with a small indicator when a property overrides the desktop base
  • Default breakpoints 1440 / 768 / 390, configurable per-project
  • @media blocks appended at the bottom of each CSS module, grouped by breakpoint
  • Parser reads and writes media query blocks; custom breakpoints preserved verbatim
  • Depends on the canvas size rework shipping first

Transitions shipped

  • New Transitions section in the WYSIWYG properties panel for every element
  • Per-row controls: Property (all, opacity, transform, background, color, border, width, height), Duration (ms/s), Easing (ease, linear, ease-in, ease-out, ease-in-out, custom cubic-bezier), Delay (ms/s)
  • Defaults: all, 200ms, ease, 0ms
  • "+ Add transition" appends another row; each row has a remove button
  • Output is a single transition shorthand per element, e.g. transition: opacity 200ms ease, transform 300ms ease-in-out
  • Custom cubic-bezier opens a four-point input — cubic-bezier(0.4, 0, 0.2, 1)
  • Round-trips through the parser — both shorthand and longhand forms read back correctly
  • Animations play in preview mode and when paired with hover/active states; static canvas viewport does not animate

CSS Grid layout shipped

  • Layout section gains a display toggle: None / Flex / Grid
  • Grid container controls replace flex controls when Grid is active: Columns and Rows (free-text, accept 1fr 1fr, repeat(3, 1fr), minmax, auto-fill, auto-fit, etc.), Column gap, Row gap, Align items, Justify items
  • Grid child controls appear in the sizing section for direct children of a grid container: Column span, Row span, Align self, Justify self — accept span 2 or explicit 1 / 3
  • Canvas renders grids using the browser's native grid engine, same as flex
  • Selecting a grid container shows a dashed overlay marking column and row lines
  • Parser handles display: grid, grid-template-columns, grid-template-rows, column-gap, row-gap, grid-column, grid-row, align-items, justify-items, align-self, justify-self
  • Implicit/auto-placement grids work out of the box — no extra handling required

v0.2.1

Copy and paste elements shipped

  • Cmd+C to copy a selected element and all its children
  • Cmd+V to paste as a sibling of the current selection, or onto the page root
  • Pasted elements get new IDs — deep copy, not a reference
  • Cmd+D to duplicate in place
  • CSS for new classes written to the module file on paste

Images shipped

  • As an img element: click the image button in the toolbar (I) or drag an image file onto the canvas to place an <img> element
  • As a background: select a rectangle and click "Set background image" in the background section of the properties panel to set background-image
  • Background controls expand on image set: background-size, background-position (9-point grid), background-repeat
  • All image files copied into an assets/ folder in the project directory
  • assets/ documented in agent.md

Add new page and duplicate page shipped

  • Add page: click "+ Add Page" in the sidebar, name it inline, get a blank .tsx and .module.css created immediately
  • Duplicate page: right-click a page → Duplicate, new name defaults to [name]-copy, editable inline
  • Both flows use the same inline naming input component
  • Name validation: lowercase, alphanumeric and hyphens only, unique within the project

Nudge with arrow keys shipped

  • Canvas: arrow keys move a selected element 1px; Shift + arrow moves 10px
  • Properties panel: up/down arrow in any number field increments/decrements by 1; Shift + up/down by 10
  • Canvas nudge triggers the normal debounced file write
  • Panel nudge commits on blur or Enter — not on every keydown
  • Values clamp at 0 for properties where negative is not meaningful

v0.2.0

WYSIWYG properties panel shipped

  • Full visual properties panel alongside the raw CSS editor — users can switch between the two at any time using the CSS / Visual toggle at the top of the panel
  • Changes in either panel stay in sync — edits in the visual panel update the CSS editor and vice versa

Remove layout section from text elements shipped

  • The flex/layout section is hidden in the properties panel when a text element is selected
  • Padding controls remain visible for text elements

Shorthand box property inputs shipped

  • Padding, margin, border, and border-radius inputs accept CSS shorthand format
  • Accepted formats: x, x x, x x x x — spaces or commas both work
  • Parsed values shown as a resolved preview on blur
  • Invalid input reverts to the previous value without crashing

Undo / redo shipped

  • Cmd+Z / Ctrl+Z to undo
  • Cmd+Shift+Z / Ctrl+Shift+Z to redo
  • History covers canvas changes and properties panel edits
  • 50 step limit
  • External file edits clear the undo history for that page
  • Implemented via zundo Zustand middleware

Project color swatches shipped

  • Color picker swatches default to a built-in neutral palette
  • Once the project has any colors in its CSS files, swatches switch to colors used in the project
  • Colors extracted from CSS modules at load time and on every file change
  • Swatches ordered by frequency of use, duplicates removed

Project themes and CSS variable tokens shipped

  • Each project gets a theme.css file with CSS custom properties
  • Token picker in the WYSIWYG panel lets users insert var(--token-name) as a value
  • Token swatches show the resolved color, not just the variable name
  • CodeMirror CSS editor shows token autocomplete suggestions
  • Theme panel for adding, renaming, and deleting tokens
  • theme.css watched by chokidar — changes hot-reload into the token picker
  • Deleting a token that is in use shows a warning

Element naming and layers panel shipped

  • Elements can be renamed — name becomes the CSS class prefix (e.g. "Hero Card" → hero-card_a1b2)
  • Unnamed elements default to rect_ or text_
  • Layers panel in the left sidebar shows the full element tree for the active page, indented to reflect nesting
  • Click a layer to select the element on the canvas
  • Selected element highlighted in the layers list
  • Renaming writes both the .tsx and .module.css atomically via a dedicated element:rename IPC channel — never one without the other

v0.1.0 — Initial Release (POC)

The first working version of Scamp. A proof of concept covering the full end-to-end loop: draw visually, get real code, edit with an agent, canvas reloads automatically.

Project management

  • Create a new project by choosing any folder on your machine
  • Open an existing project folder
  • Recent projects list on the start screen (last 5 projects)
  • Missing project folders shown as greyed out with a "Folder not found" label
  • Auto-generated agent.md on project creation with code conventions for coding agents

Pages

  • Default home page created with every new project
  • Pages listed in the left sidebar
  • Switch between pages by clicking in the sidebar

Canvas

  • DOM-based canvas viewport (1440×900, scales to fit the window)
  • Rectangle tool — click and drag to draw a rectangle (R)
  • Select tool — click to select, drag to move, handles to resize (S)
  • Text tool — click to place a text element, double-click to edit (T)
  • Nested rectangles — draw inside any selected rectangle
  • Selected element shown with a blue outline and 8 resize handles
  • Checkerboard background outside the viewport frame

Properties panel — raw CSS editor

  • CodeMirror editor loads the selected element's CSS class body on selection
  • Edit any CSS property in any format — shorthand, longhand, anything valid
  • Commit on blur or Cmd+S — triggers a targeted class patch and file write
  • Unknown properties preserved in output and shown with a ⚠ warning label
  • Placeholder shown when no element is selected

Code output

  • Every canvas change auto-saves to a .tsx and .module.css file
  • Atomic file writes (write to .tmp, then rename) to prevent partial reads
  • data-scamp-id attribute on every element as a stable identity anchor
  • Class names follow the [type]_[4-char-id] pattern (e.g. rect_a1b2, text_c3d4)
  • Only non-default properties emitted — output stays clean and readable
  • Read-only code panel at the bottom shows live TSX and CSS with syntax highlighting

Bidirectional sync

  • chokidar watches project files for external changes
  • External edits (agent, editor, terminal) parsed and reflected on the canvas automatically
  • parseCode() diffs against current state before updating — no unnecessary re-renders
  • Unknown CSS properties round-trip through the file untouched

Built-in terminal

  • Full terminal panel (`Ctrl+``) powered by node-pty and xterm.js
  • Opens in the project folder automatically
  • Up to 3 terminal tabs per session

See Scamp in action.

Book a 30 minute call. No slides. We walk through how you design and ship today, and I show you exactly where Scamp fits.

30 minutes, no cost, with the person who builds Scamp.