Changelog

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

v0.12.0 — Learn Scamp by doing

A hands-on tutorial, Cmd-click multi-select, token values in tooltips, and fixes for large and nested components.

A tutorial teaches the basics by doing them shipped

  • After you choose a projects folder for the first time, Scamp offers a tutorial project and a Learn checklist with five short lessons: drawing, layout, editing the code, components, and tokens. Each lesson is checked off when you do it
  • You can skip it, hide the checklist, or start over from Settings. If you already use Scamp, you don't see it unless you start it from Settings. Get started

Changes shipped

  • A field's tooltip shows the token it applies and that token's value. Hold the pointer over a field whose value is a theme token, and the tooltip adds a line such as --space-md: 16px. A token that points at another token shows the value at the end of the chain
  • Cmd-click adds to the selection, and Shift-click selects a range of layers. Cmd-click (macOS) or Ctrl-click (Windows and Linux) adds an element to the selection or removes it, on the canvas and in the layers panel. In the layers panel, Shift-click selects every layer at the same level from the selected one to the one you click. On the canvas, Shift-click still adds or removes an element. Layers panel

Fixes shipped

  • A component with a large variant set opens without freezing. A component whose variant properties make more than 36 combinations used to draw every one of them. Scamp now draws only the frames the file defines, with a notice that the set is past the limit; select any other combination in the Variants section. Saving a large set is faster too, and Checks warns when a component is past the limit
  • A component inside another component draws on the page, with its own styles, size, and variant picks, instead of a purple box with its name. To change its text, open the outer component
  • An agent's edit to a component shows on the canvas right away. Scamp now re-reads a file an agent changes, whether or not it's open
  • A component with no background is transparent on the canvas, as it is in the preview. A page or component whose file sets a white background keeps it, on the canvas and when Scamp saves the file
  • Note: If a component that looked white on the canvas now looks see-through, its file doesn't set a background, and your app has always drawn it see-through. To make it white, select its root and set its background in the Background section
  • An element in normal flow stays in flow on the canvas. A child of a block element with no position was drawn at the parent's top-left corner and saved as position: absolute. Scamp now reads it as position: static, and keeps display: block on a <progress> or <meter>

v0.11.1 — Pinned elements stay pinned

Elements placed with right or bottom stay put, adding a variant no longer crashes, and the Variants section scrolls.

Fixes shipped

  • An element pinned to the right edge stays there. An element placed with right and no left drew at the left edge on the canvas, and Scamp's next save added left: 0px, which moved it in the browser too. It now draws and saves where right puts it, and the same goes for bottom. Dragging it, or anything placed with left: 50%, no longer makes it jump first
  • Adding a variant no longer crashes the canvas. When a component's root took its frame's width and an element hung past the root's edge, each variant frame grew to reach that element, and Scamp showed Something went wrong. Each frame now settles at the size that fits what it draws
  • The Variants section scrolls with the rest of the panel, instead of staying pinned at the top on a short window

v0.11.0 — Component variants

Design a component's variants as a set, pick one per instance, change them on interaction, and start from Button, Modal, and Menu.

Design component variants as a set shipped

  • A component's variant properties, such as a button's variant and size, live in the Variants section of the properties panel. The canvas draws every combination as a frame in a grid, and you edit any frame by clicking it
  • A frame that combines two values writes a rule for just that combination, and Make default changes the component's own look. Scamp writes each value as a data- attribute rule, which runs with no JavaScript
  • Pick a variant for each instance. An instance's section in the properties panel has a list for each axis, so one Button component gives you a primary and an outline button on the same page
  • Change a variant on hover, press, focus, or click. A component's Interactions change its own variant while it's used: a button's hover look, a menu that opens on a click and closes on a click outside or Escape. Hover, press, and focus are CSS; clicks run through the Scamp framework. Preview on a component opens it alone in the Preview window to try them
  • Starter Button, Modal, and Menu components. Add one from Starters in the Components list to reuse, restyle, or learn from. In a Scamp framework project, the Modal and Menu open and close by themselves, and fade in and out. Components

Variants everywhere shipped

  • A React import keeps each component's looks as variants. Where copies of a component differ only in paint, such as the current item in a navigation menu, each look becomes a variant the page's instance picks
  • Checks find variant mistakes. An instance set to a value its component lacks, and a rule for a value the component doesn't declare, are both listed
  • The Scamp Agent builds components with variants. Ask it for an outline button or a small size, and it adds variant properties, values, and interactions to one component rather than copying the component per look. It asks before it removes a property or value. Agents connected over MCP get the same guidance in agent.md

Changes shipped

  • Components are purple. A component's set border, its icon in the Layers panel, and a selected instance use purple, so you can tell a component from a page element at a glance
  • A cleaner component editor. The banner above the canvas is gone; the breadcrumb, such as home › Card, names where you came from, and you click its first part or press Esc to go back. Routes no longer shows while you edit a component
  • Variants and Interactions follow Figma's layout. Each section adds with + in its header. An interaction is added from a panel with Trigger and Action, starts from the value you're editing, and is listed on one line

Fixes shipped

  • An agent's edit no longer wipes your unsaved change. Scamp now merges the two
  • Following a link to another page keeps your last edits. Jumping through the link indicator saves the page you leave first, as the sidebar does
  • Restoring a snapshot is safe. Restoring your oldest snapshot no longer deletes it without restoring, and a restore that fails partway puts the project back as it was
  • A failed save no longer leaves a page half-written. Scamp writes a page's .tsx and CSS together, or neither
  • Undo can't bring a deleted page back into a new one. A new page with a deleted page's name starts with its own history
  • Update scampjs works right after a release, instead of failing with ETARGET while npm's cache was behind
  • Security. On Linux, Scamp no longer stores your sign-in and API key when the system keyring offers only its fixed, publicly known key. MCP connection files are readable by your user only, an image download during an import is capped in size and time, the preview opens a new window only after a click, and an agent's heavy queries run one at a time

v0.10.0 — Multi-select editing and page groups

Edit several elements at once, group pages, connect more agents over MCP, and keep saving while an agent runs.

Edit several elements at once shipped

  • With two or more elements selected, a change in the properties panel applies to every selected element it fits, as one undo step. Before, only the first selected element changed
  • Typography reaches only text, and a component instance takes only a size
  • A field the selected elements disagree on reads Mixed; type a value to set it on all of them. Shadows, Filters, Transform, and Transitions show Mixed when the lists differ, and adding a row replaces them all

Group pages in the Pages list shipped

  • Cmd+click (Ctrl+click) pages or Shift+click a run of them, then press Cmd+G, or right-click and select Group. Drag pages into a group, or right-click a page and select Move to a group
  • Drag pages and groups into any order, and collapse a group to keep a big project scannable
  • Groups change only the list: a page's files, route, and code are the same wherever it sits. The groups are saved in scamp.config.json, and collapsed groups are remembered on your computer
  • Add page and Import moved to the Pages header. Add page is the + button beside the Pages title, and Import is the download button, with Import from website… and Import from React app… in its menu

Agents shipped

  • Connect Codex, OpenCode, VS Code, and other agents to Scamp's MCP server. The copy button on the terminal's MCP indicator now opens a menu of agents. Select yours to copy its connect command or config, with a note on where it goes
  • Agents can check the whole project in one call. The new MCP tool scamp_check_project runs the Checks on every page, view, and component and lists what's wrong in each. scamp_check_view now checks plain pages too, and both read your files as they are now. Work with AI agents
  • Scamp keeps saving while an agent is open in its terminal. Scamp used to pause saving whenever any program ran in the integrated terminal, including Claude Code sitting idle at its prompt. It now pauses only while files are actually changing, or when you click Pause sync. Each save still checks the file first and merges with whatever changed. Bidirectional sync

More additions shipped

  • See and update a project's scampjs version. Project Settings has a Framework section that shows the installed scampjs version and, when npm has a newer release this version of Scamp supports, an Update button that installs it
  • Shadows that use a theme token show in the panel. A box-shadow: var(--shadow-card) appears in the Shadow section by token name and keeps following the theme. Detach turns it into rows you can edit
  • Center with an auto margin. The margin field takes auto on a side, so 0 auto centers a fixed-width element
  • Set how an element sits among its neighbors. A new Display choice in the Layout section—and a Display section for text and inputs—sets Block, Inline, Inline block, Contents, or List item, and makes a flex or grid container inline

Fixes shipped

  • An exported element keeps its padding and type. Exporting an element placed on the page, as a PNG or SVG, now draws it from the image's top-left at its own size
  • Exports embed the fonts they use, Adobe Fonts and Google Fonts included, and no longer carry Scamp's own interface fonts. Export
  • Drop images onto the canvas again. A PNG, JPEG, WebP, or GIF dragged from the file manager or a web browser is placed where you drop it. A drop Scamp can't use now says why
  • Click and drag a component instance on the canvas. A click anywhere an instance draws now selects it, so you can drag it and double-click it
  • Dragging a side handle no longer resets the other dimension. A side handle now changes only its own dimension, and a corner changes both
  • Shift-clicking on the canvas no longer selects the app's text
  • Setting Block at a breakpoint no longer hides the element. It wrote display: none instead of display: block
  • tabIndex={-1} is no longer reported as a broken binding
  • Checks no longer report valid CSS as problems. Values the panel has no control for are listed under Edit in CSS and left out of the count
  • Edits made while sync is paused are saved. Resuming writes them, and switching to another page or component writes the one you leave
  • A save that fails no longer costs you the edit. The next save writes it too, and Retry after a conflict merges instead of staying on Saving…
  • Closing or switching project stops the Scamp Agent, so a reply in progress no longer keeps spending your key or edits the project you open next
  • A CSS panel edit and a canvas save no longer overwrite each other
  • History survives a crash. The snapshot list, theme.css, DESIGN.md, and your settings are written in one step. Snapshots
  • Undo AI changes covers the agent's first edits
  • Renaming or deleting a component keeps your recent edits on the pages that use it
  • Agents connected over MCP get their requests intact, including accented and other non-ASCII text
  • The Scamp Agent recovers when your key can't be read and asks you to connect it again
  • Imported pages kept for the agent are private to your account on a shared Linux machine
  • Leaving a page while you preview a snapshot keeps the live page

v0.9.0 — The Scamp Agent

A built-in AI agent on your own Claude API key, React app imports, tables, and a Checks section.

The Scamp Agent, in beta shipped

  • Click Agent in the sidebar, connect your own Claude API key, and describe a change in plain words. The agent reads your design, edits it through the same tools the properties panel uses, and saves the result to your files
  • It works on the page you have open or across the whole project, and it can measure a page in a browser to find what overflows
  • It asks before it deletes, creates components, changes theme tokens, or makes many changes at once, and Undo AI changes puts back everything it did in a conversation
  • Each page keeps its own conversation, saved in the project, and new projects keep those conversations in version control so a team sharing a repository shares them
  • The agent needs you to be signed in, and Anthropic bills its use to your key; the connect screen says what's sent to Anthropic. Scamp Agent
  • Clean up an imported page with AI. After you import a page, click Clean up with AI in the import window. The agent makes the page easier to edit—shorthand values instead of per-side ones, flex layout, theme tokens if you want them—without changing how it looks, and shows you a plan before it changes anything. Clean up an imported page

Import pages from a React app shipped

  • Choose a React app's folder, and Scamp runs it, lists its routes, and imports the ones you pick into a new project, in one step you can undo
  • The app's own components become Scamp components, its .map() lists become repeats, and the theme tokens it used come across where it used them
  • Tidy up with AI then reads the app's source to name its lists and find what it shows only some of the time. Import pages from a React app

Tables shipped

  • Change a container's tag to table, and draw rows and cells inside it. A table is laid out as a grid with its column widths set once, on the table, so the header and the body always line up
  • Dividers, stripes, a sticky header, cell padding, and cell alignment are each set once in the new Rows and cells section
  • A table on an imported page now arrives as a table, not as loose cells. Tables

A Checks section lists what's wrong with a view shipped

  • Undeclared theme tokens, values the panel can't edit, loose text, and misplaced table parts appear at the top of the panel, grouped and worst first; click one to select the element
  • Scamp used to find these only for agents, so a project could have thousands without anyone seeing them. Find problems in a view

More additions shipped

  • An icon's color controls come first. With an SVG selected, the SVG section, with its colors and stroke width, sits above Background in the Visual panel. Icons that set their color on the <svg> tag, as Lucide and Tabler icons and agent-written icons do, now show their colors instead of "No editable colours", and Current color shows the color an icon inherits
  • The component editor has its own breakpoint. Click the size control above a component's canvas and select a breakpoint to see and edit the component at that screen size, without resizing its canvas. The editor always opens at Desktop, and a page gets its own breakpoint back when you return. Breakpoints
  • Outside agents get more from the MCP server. scamp_get_element_tree and scamp_get_element_by_id read any view or component, not only the open one, and two new tools measure overflow and read a React import's source. Agents also learn tables from agent.md. Work with AI agents

Fixes shipped

  • Double-clicking a component on the canvas opens its editor. A layer over the canvas caught the double-click first. The breadcrumb and Esc now take you back to the page or view you came from
  • The component editor shows a component the way your pages do. A component with tablet styles showed them at Desktop, text inside a nested <span> was dropped on pages, and a component set to height: 100% stopped short of the row it sat in
  • Leaving a component opened from the sidebar goes back to the view you were on. In a project made of views, it showed an empty canvas
  • Esc closes the canvas size menu without leaving the component editor
  • Emphasis and other inline tags stay where they are in a sentence. Hello <em>world</em> again became Hello again world when Scamp saved. Inline tags now stay in place, with the spaces around them, on the canvas, in the files, and in the HTML export, which also now keeps styled words
  • Opening a project no longer moves a centered element. An offset written as a percentage or a calculation, such as left: 50%, was read as 0, so the next save wrote left: 0px. Scamp now keeps those values as written
  • Saving an agent-edited page no longer warns that it rewrote the whole stylesheet. The check mistook two orderings of the same rule for different designs
  • Fit keeps a page readable when something overflows it by a lot. Fit now shows overflow up to half the page's width, and you scroll for the rest
  • The breakpoint menu lines up with the right edge of the page at every zoom, not with the edge of the canvas area
  • Edits at a breakpoint close their @media block on its own line
  • Imported pages keep more of their layout. Values set per side are combined into one shorthand where they match, gaps are written once, named grid areas and form-control sizes come across, and text the page hides no longer appears

v0.8.8 — Line icons keep their outline

Imported stroke icons render with their outline and color instead of as a solid black shape.

Fixes shipped

  • Imported line icons keep their outline and their color. An icon drawn as strokes rather than fills — most icon sets — arrived as a solid black shape. Scamp writes an imported icon's markup into your .tsx file as JSX, and the canvas and the HTML export were then reading that JSX as HTML, where the icon's paint means nothing and it falls back to a black fill
  • Icons now keep their paint in a form both can read, and existing imported pages render correctly without being imported again. Import a page from the web

v0.8.7 — Style part of a text element

Style a range of words inside a text element, more faithful web imports, and the Scamp Software License.

Style part of a text element shipped

  • Select some words on the canvas and change their color or weight, and Scamp wraps exactly those words in a <span> with its own class — the rest of the sentence is untouched
  • The properties panel shows the selection's own style while a range is selected, and shows nothing at all when the selection covers two different values, rather than picking one of them

Changes shipped

  • An import writes literal colors instead of creating theme tokens. Scamp used to lift any color it saw more than once into a theme token. Counting how often a color appears can't decide what a design system should share — it produced a theme you didn't choose, and importing a second site into the same project could repaint the first one in the new site's palette. Turning imported colors into tokens is now yours to do, against a design you can see
  • Note: Views imported before this release may still reference tokens that hold another site's colors. Import those pages again to fix them
  • The import report grades what it changed in four levels, not two: lost, renders but not editable, approximated, and exact, worst first, and says what you can still change about a fallback. Import a page from the web
  • Scamp is now under the Scamp Software License. Free to use for personal and commercial work, and everything Scamp generates from your designs is yours. The source is published for transparency, not for copying or redistribution. See LICENSE

Fixes shipped

  • Imported headings no longer wrap a line early. Scamp asked Google Fonts for weights only, and Google serves a variable font with every other axis frozen at its default — so a heading set in Fraunces came back about 7% wider than the page it was copied from. Scamp now asks for each family's full set of axes. Around 158 Google families have an axis beyond weight
  • A hidden "skip to content" link no longer paints a bar down the page. Scamp read its position as a stretch instead of an offset, so it imported as a dark bar thousands of pixels tall, over the text
  • An icon with a gradient renders. Gradients, filters, and masks inside an inline SVG are saved as an .svg file in your project and referenced as an image, because they can't survive being rewritten as JSX. Plain icons are still imported inline, so they still follow the color around them
  • Words keep the spaces around a styled word. works <span>alongside</span> AI. imported as worksalongsideAI.
  • Importing two sites into one project no longer repaints the first one. See the color change above

v0.8.6 — A new home for the source

Scamp's source repository moved to the scampdesign organization.

Changes shipped

  • Scamp's source repository moved to the scampdesign organization. Help → Report a bug and the repository link in the Help menu now point to github.com/scampdesign/scamp
  • Nothing about updates changes: Scamp has taken them from updates.scamp.club since 0.7.1, and that doesn't depend on where the source lives

v0.8.5 — Import a page from the web

Bring any web page into Scamp as a responsive view, with a report of what changed in translation.

Import a page from the web shipped

  • ↧ Import a page… in the Pages sidebar opens a browser. Navigate to any page, click Import, and Scamp reads it as it appears on screen and writes a view from it — real elements on the canvas, real TSX and CSS Module files on disk
  • The page's images are downloaded into the project, its fonts are installed or named, repeated colors become theme tokens, and the page's own class names become element names. Import a page from the web
  • Every import says what it changed. An import is a translation into a smaller model, so the import window ends with a report: what came across differently, and what couldn't come at all. Losses are marked and listed first, and the report opens on its own when there is one, so a <canvas> you now have to rebuild isn't filed beside the bookkeeping
  • An imported page arrives responsive. After reading the page at full width, Scamp narrows the browser to each of your project's breakpoints and reads it again, so the view carries the page's own media queries as per-breakpoint overrides rather than one fixed layout
  • An agent can see the page an import came from. Two MCP tools, scamp_list_import_sources and scamp_get_import_source, return the original HTML and CSS, so tidying an imported view starts from what the page actually said instead of a guess. The copy lives in a temporary folder, never in your project, and is deleted when you close the project. Work with AI agents

Fixes shipped

  • Preview no longer goes blank when you leave the first page. In a Scamp framework project, an added or imported page had no route. Adding a page now writes the route that renders it, renaming a page moves its route, and Project settings lists every route in the project. A view that already lost its route gets a Generate route button
  • A project's start-screen card shows the project again. Scamp framework projects had a blank card from the day the format shipped. Captures also now keep the design's own fonts and its background images, and a capture can no longer be filed under the project you just closed
  • An element's inline markup renders on the canvas. A <b>, <em>, or link inside a sentence, and children of a text element, appeared in the layers panel and in the code but not on the canvas
  • A link points again. Scamp's reset uses all: unset on a, which took cursor: pointer with it, so a link behaved like a div under the mouse in the preview and the export. theme.css puts it back for a[href], and an existing project gets the rule when you open it. The canvas keeps the drawing cursor
  • The terminal's output goes to the window that asked for it. With more than one project open, a shell's output could arrive in the wrong window, which read as a terminal that wouldn't start

v0.8.0 — Views and the Scamp framework

Component-shaped views with data bindings, new projects on the Scamp framework, routes in the panel, and new MCP tools for agents.

Views shipped

  • A page's design as a component-shaped file. A view lives at views/[Name]/ with a props type and sample data, and lists under Pages by its route slug
  • + Add Page creates a view, and Convert to view… on a page's menu moves an existing page's elements across, leaving a one-line wrapper at the same route. Views
  • A view's artboard matches the size the toolbar shows. A view opens at the project's page width instead of the component default

Data bindings in the Data tab shipped

  • Bind a list to an element with Repeat this…, a flag with Show only when…, and any attribute or event handler to a prop
  • The literal on the canvas becomes the prop's sample value and its default in the file, so a view renders on its own
  • Each binding has one canonical form in the file, and hand-written files in that form round-trip. Views and components
  • Bind an image's source to data. An <img>'s Src and Alt appear in the Data tab's attribute list, so a card grid or a gallery can take its images from a prop or from a repeat's rows. The Image section shows the binding in place of the path and points at the Data tab

The Scamp framework shipped

  • New projects run on the Scamp framework. New Project writes views/, routes/, design/theme.css, and a package.json on scampjs, from the framework's own templates, instead of the Next.js layout. Existing Next.js projects open unchanged. Scamp framework projects
  • Migrate a Next.js project to the framework. A Scamp framework section in the properties panel offers the move: each page becomes a view and a route, the theme moves under design/, and the Next.js files go to a backup folder. Anything Scamp didn't write stays in place and is listed. The offer sits in the panel rather than in a bar across the top, so a project that hasn't taken it keeps its canvas. Migrate a Next.js project
  • Scamp framework projects open in Scamp. A project with a views/ folder and a scampjs dependency opens with tokens under design/, no wrapper pages, and routes/ left entirely to you. You don't need the framework installed to design; a banner appears only when an installed scampjs implements a file format this version can't read, which is the case where a save would write the wrong shape
  • Preview through the Scamp framework. Preview runs scamp dev from the project's scampjs (0.1 or later) and opens the current view at /_views/[Name]. The page list in the preview window holds the project's views. Preview a view
  • The _scamp export. Every component and view file now ends with export const _scamp, which records the file format version and the event props. Scamp writes it on every save. New files declare contract 1, and a file keeps the version it declares
  • A page on the Scamp framework in the user docs: what a project is made of, which files Scamp owns and which are yours, how a design's data becomes the shape a route provides, and where the framework's own documentation lives. The Scamp framework

Routes in the properties panel shipped

  • A Routes section lists the open page's route with the render mode on the line under the path, and opens a route in the code panel. Project Settings has a Routes section with every route in the project, page and API
  • The properties panel shows what belongs to the page when nothing is selected. Routes, then Data with the view's props and bindings, then Keyboard shortcuts as a section you open when you want it. The Visual and CSS tabs describe a selected element, so they no longer appear with nothing selected
  • Adding a page writes its route. + Add Page creates the view and the route that renders it, so the page has an address straight away. Generate route writes a route for a view that has none — one you converted, or one an agent wrote — with the view's sample data in load()
  • Renaming a page takes its route with it. The route that renders the page follows the rename, so the project still builds and the page keeps an address. A route you placed yourself stays where it is, with only its references updated
  • The preview's request log lands in the app log, and Project Settings shows the keys in .dev.vars. Routes

Agents learn views shipped

  • agent.md gains a data bindings section, and the MCP server's new scamp_get_view_props tool returns a view's exact props type and sample data, so an agent writing the route passes the right shape
  • agent.md describes the project you actually have. In a Scamp framework project it still called the project a Next.js App Router project and named files that aren't there. It now documents the framework layout, the route file and its exports, and how an image whose source comes from data binds
  • Agents can ask what you changed. The new scamp_get_recent_edits tool reports your recent saves as the lines each one rewrote, so an agent can catch up before editing a file it read earlier
  • Agents can check what a view lost. The new scamp_check_view reports bindings that didn't parse, declarations that render but leave the panel controls blank, tokens theme.css doesn't declare, and sample rows that disagree with each other
  • Agents can read the project's conventions. The new scamp_get_conventions serves agent.md's own content through the MCP server, scoped to the project's format and a section at a time
  • Agents also get scamp_list_routes. Work with AI agents

Changes shipped

  • Scamp writes only the lines a change touches. A design change rewrites the CSS rules and the elements it affects instead of replacing both files. A file Scamp didn't write keeps its comments, its extra imports, its module-level code, and its formatting
  • An edit from outside is merged, not dropped. When a file changes on disk while you're designing, Scamp merges the two changes if they touch different lines, instead of reloading and losing yours. Only a real overlap still stops the save. Bidirectional sync

Fixes shipped

  • An image whose source comes from data renders on the canvas. src={product.image} on an <img> was read as literal text: the canvas drew a broken image, and the next save wrote the placeholder into the file. Bound src and alt now resolve, including per row inside a repeat
  • Five things that didn't work in a Scamp framework project. Replace image and Set background image did nothing; the Code panel labelled both panes "— no page —"; the Link section offered no destinations and marked every internal link broken; Export HTML wrote an empty folder; and clicking an entry in History didn't preview the snapshot
  • A failed image import tells you it failed. Every import path — the image tool, drag-and-drop, Replace image, Set background image — discarded the error. Failures now appear in the App Log
  • Saving doesn't rewrite & in a URL. An image source ending ?w=2000&q=80 came back as &amp;q=80 on the next save

v0.7.2 — Boxes stay put in layout containers

Adding text to a box in a flex or grid container no longer shifts the box.

Fixes shipped

  • Adding text to a box in a flex or grid container no longer shifts the box. A box drawn into a layout container kept the coordinates it was drawn at, and a box drawn before its parent became a flex or grid container kept its old position. The moment a text was placed inside, those leftover numbers were written as left and top on the box's positioning context, and it jumped by that much
  • New boxes under a layout parent now start at zero, and the generated CSS always writes left: 0px; top: 0px for a positioning context, so the layout owns the position and every save is stable. Flex layout

v0.7.1 — Scamp's own update server

Updates now come from updates.scamp.club instead of GitHub Releases.

Changes shipped

  • Updates now come from Scamp's own update server. Nothing changes in how you use the app: it still checks for updates on launch and every four hours, and installs them the same way
  • Under the hood, this version switches the update feed from GitHub Releases to updates.scamp.club, so future releases keep reaching you wherever the source code lives

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: h1–h6, 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.