Muse
A visual editor for running React apps. Point at an element, shape it, and Muse rewrites the real source. This page runs a live copy, and on a desktop nearly everything on it is editable.
Overview
Every visual change in code costs the same detour.
You can see the fix, but you have to make it in a file. Design tools let you shape the thing in front of you. Code makes you describe it from memory.
Muse is an overlay for your dev server. Select an element, adjust it, and Muse writes the change to the source that produced it. Anything it can’t write gets flagged for your coding agent.
Live Demo
Try it before you read how it works.
From Click to Code
A click resolves to the line of source that rendered it.
React 19 removed the fiber field that carried source locations, so I stamp them in at build time. A Babel plugin writes data-muse-loc="file:line:col" on every JSX element, and Muse reads it straight off the DOM.
The plugin never touches React internals, so it works on React 18 and 19 in any bundler that runs Babel. Turbopack can’t load SWC plugins, so Babel is the way in.
file:line:column, which is how the edit lands on the right JSX.Predictable by Design
Every gesture is one fixed transform.
Canvas probes before it writes. The offer and the write come from the same analysis, so they can’t disagree. Each edit is a deterministic Babel AST rewrite.
The same gesture lands differently depending on how an element is styled: a Tailwind class, an inline style object, a CSS Module rule, or a styled-components template. If the value comes from a design token, Muse edits the CSS variable where it’s defined instead of stamping a literal over it.
Knowing When to Refuse
The hardest design call was teaching Canvas when to refuse.
A list rendered from a .map() can’t become one provable transform, because moving the JSX moves nothing. Canvas could preview the attempt or show a confidence score, but a tool you have to re-check after every edit defeats the point of direct manipulation. So it refuses and tells you why. The actual message, word for word: “these are generated from data — reorder the list instead.”
Take the offer on a refusal, or Shift-click any element, and you get a work-order. A small MCP server routes it to your own coding agent.
muse-mcp hands to your coding agent. It gets a precise work-order rather than a prompt. Shift-click any element in the card above and your own flag appears here. On a desktop, Shift-clicking any element in the card above drops your own flag here.Outcome
Muse is shipped, and it helped build this page.
Muse installs from npm, and the flag server runs with npx muse-mcp. If you’d rather have the engine in your own tree to customize, npx skills add thientran01/Muse vendors it in. The code is public at github.com/thientran01/Muse.
I kept Muse installed while I built this case study and made a stretch of its edits using it. The page’s styling patterns also surfaced engine bugs Muse’s own demo never hit, like a reorder that landed a beat late until I measured the geometry mid-drag.
Where Muse goes next.
Canvas handles the edits it can prove, and everything else becomes a flag. Making Muse more useful means moving that line outward: teaching the work-order to carry edits Canvas still refuses, like extracting a component into its own file. Real work is what keeps showing me where the line should go next.