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
flexshorthand - 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
transformlists 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_scaffoldtool hands an agent the exact starter files for a component, so it writes real component folders instead of a page of examples agent.mdgains 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=autoto 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-portfoliodisplays 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
::beforeand::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.mdrecommends::beforefor 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+.cssinto 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 intoassets/ theme.csscomes 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 anauto-height container and computed to zero — the element simply vanished. It now emitsalign-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: absolutesurvives on a flex or grid child. It was being discarded on parse and then deleted from your file on the next saveposition: stickyrenders 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+Xcuts as a single undo step, andCmd+Ccopies a multi-selectionCmd+Shift+Vpastes in place at the copied coordinates; right-click → Paste drops at the clicked pointCmd+Vnow 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_a1b2duplicates tomenu_c3d4instead of reverting torect_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:unitandnpm run test:integrationwere 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
- Component bug fixes. Components
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
- Element tree menu updates. Layers Panel
- Theme and font upgrades. Themes
- Card view for the project list. Getting Started
v0.5.3 — Layout control cleanup
- Fixed a duplicate element-ID issue. Element Naming
- Design cleanup on the layout controls. Properties Panel
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
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
100vhfloor
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-shadowvalue and round-trip through the parser, single or stacked - Promotes
box-shadowfrom acustomPropertieswarning entry to a first-class control
CSS blend modes shipped
- New "Blend mode" dropdown in the appearance section emits
mix-blend-modefor 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-modeandbackground-blend-modeadded to the parser property map - Related
isolation: isolateround-trips cleanly throughcustomProperties
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+Eexports 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
filterproperty - Per-row visibility toggle and remove button
- Separate "Backdrop filter" toggle emits
backdrop-filterwith a hint about needing a transparent background filterandbackdrop-filteradded to the parser, decomposed back into individual rows; unknown filter functions preserved incustomProperties
Visual history panel shipped
- History panel from the toolbar or
Cmd+Shift+Hlisting 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
EyeDropperAPI, 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@keyframesin place
UA margin defaults round-trip on text tags shipped
margin: 0on<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@importforms pointing atuse.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:focusback to state overrides; unrecognised pseudo-classes (:focus-visible,:checked,:disabled) preserved verbatim viacustomProperties
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
animationshorthand to the element and appends the@keyframesblock 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
@keyframesblocks — recognised preset names map back to the picker, custom keyframes preserved verbatim - Custom
@keyframeswritten by agents pass throughcustomPropertiesuntouched - 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, andmain.tsxalongside design files; infrastructure files documented inagent.mdas off-limits to agents - First open runs
npm installautomatically with a progress indicator; subsequent opens reuse the existingnode_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.jsonfiles inject mock data into the auto-generatedmain.tsxso 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 devfrom 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
hrefmatching the page file name (e.g../dashboardfordashboard.tsx) - If the element isn't already an
<a>tag, Scamp wraps its content in one and writes both.tsxand.module.cssatomically via theelement:renameIPC 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
hrefand 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
opacityproperty - Visibility — segmented control with Visible (default), Hidden (
visibility: hidden), and None (display: none) - Elements with
display: nonestay 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.csswatched 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:
h1–h6,span,label,blockquote,pre,code,strong,em,small,time,figcaption,legend,li - Media variants:
video,iframe, andsvgalongside existingimg - New input element type with its own toolbar button (
F):input,textarea,select - Tag-specific attribute fields appear inline —
href/targetfora,typeforbutton,forforlabel,rows/placeholderfortextarea, etc. - Class name prefixes stay as
rect_,text_, andimg_— 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
@mediablocks 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
transitionshorthand 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 2or explicit1 / 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+Cto copy a selected element and all its childrenCmd+Vto paste as a sibling of the current selection, or onto the page root- Pasted elements get new IDs — deep copy, not a reference
Cmd+Dto 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 inagent.md
Add new page and duplicate page shipped
- Add page: click "+ Add Page" in the sidebar, name it inline, get a blank
.tsxand.module.csscreated 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+Zto undoCmd+Shift+Z/Ctrl+Shift+Zto redo- History covers canvas changes and properties panel edits
- 50 step limit
- External file edits clear the undo history for that page
- Implemented via
zundoZustand 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.cssfile 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.csswatched 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_ortext_ - 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
.tsxand.module.cssatomically via a dedicatedelement:renameIPC 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.mdon project creation with code conventions for coding agents
Pages
- Default
homepage 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
.tsxand.module.cssfile - Atomic file writes (write to
.tmp, then rename) to prevent partial reads data-scamp-idattribute 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