Docs
How midcode works
Install it, open your project, edit on the canvas and publish. With the code for each step.
What midcode is
midcode is a Mac app that opens a site you built in code and lets you edit it visually: click an element, change its text, its size, its color, move it, add a section. Every change is written into your project’s own files, as the code you would have typed.
There is no export and no proprietary format. Your project stays a normal repository: you can keep working on it in your editor or with an agent, and midcode shows whatever is there.
Install
midcode runs on macOS (Apple silicon and Intel). Install it with Homebrew:
brew install --cask agusdellaquila/midcode/midcodeOr download the disk image, open it and drag midcode to Applications. Opened from the disk image, midcode offers to move itself there, which it needs to update itself.
It’s free for 3 days. After that it’s one payment, with every update included. Your license key works on 3 Macs; paste it when the trial ends, or in Settings.
What you need
- A project with its dependencies installed (
node_modules). If they’re missing, midcode offers to install them. - Git, if you want to publish from midcode. Everything else works without it.
- Nothing else. midcode brings its own Node to run your dev server.
Open a project
Press ⌘ O and choose your project’s root folder, or drop the folder on the window. midcode starts your dev server and shows the site at every breakpoint, side by side. Projects you opened stay in the hub, and each one opens in its own tab.
| Project | What you can do |
|---|---|
| Next.js (App Router or Pages) | Everything: edit on the canvas, pages, site settings, the canvas outside the breakpoints. |
| Vite + React, React Router, Remix | Edit on the canvas, styles, components, insert, publish. |
| Astro | Its React islands are edited on the canvas. |
| SvelteKit, Vite + Svelte | Edit text, classes, attributes; insert, move and delete elements. |
| Nuxt, plain HTML, anything with a dev script | View every breakpoint, play the site and leave comments. |
midcode doesn’t change your config to do this. It marks each element with where it’s written while your dev server runs, and only then.
The canvas
Each breakpoint is your real site, running. Click an element to select it; the right panel shows where it’s written (file:line) and everything you can change. Double-click a text to edit it in place.
- Move: drag an element on the canvas or in Layers. A blue line shows where it lands.
- Resize: drag a handle. Handles show on the sides whose size is Fixed.
- Nudge: arrow keys move a floating or absolutely positioned element 1 px, and with ⇧ by the nudge amount you set in Settings.
- Right-click: duplicate, delete, copy and paste styles, rename the layer, open its code.
- Preview: press P to use the site at full size, with its animations and menus.
Breakpoints
One breakpoint is the primary: what you change there applies everywhere. A change made in another breakpoint is an override for that width, shown in blue; right-click it to remove it. You can add, rename and resize breakpoints from the bar above each one.
Layers
The Layers tab lists each breakpoint with the page’s layers under it, and then what floats on the canvas. Picking a layer under a breakpoint selects it there, so what you change is written for that breakpoint.
Outside the breakpoints
In Next.js projects, anything you draw (F), drop or paste on the empty canvas floats there: a place to build something before it goes into a page. Drag it onto a breakpoint to put it in the page. It lives in app/midcode-scratch/page.tsx, which answers 404 in production and is never published.
Insert
The + in the toolbar opens the Insert panel: frames, stacks, grids, text, media, embeds, forms, whole sections, interactive components (carousel, tabs, slideshow, ticker) and icons. Drag one onto the canvas, or select an element and click it.
What you insert is plain JSX in your file. Interactive components are written once into components/midcode/ as real source files; from then on they’re yours.
Paste works too: with an image on the clipboard, ⌘ V copies it into public/images and places it on the canvas, or next to the selected element.
Components
Double-click a component’s instance (or open it from Assets) to edit the component itself, alone on the canvas. Columns are its variants, rows its states: Default, Hover, Pressed, Focus. What you change in a cell is written for that variant and state, in the component’s own file.
midcode writes variants the way you would by hand: a typed prop and a data attribute.
export function Card({ title, variant = 'primary' }: { title: string; variant?: 'primary' | 'ghost' }) {
return (
<article className="group/card rounded-2xl p-6 data-[variant=ghost]:bg-transparent" data-variant={variant}>
<h3 className="group-hover/card:underline">{title}</h3>
</article>
)
}A component’s props show in the right panel as typed controls, read from its TypeScript types.
Styles
The right panel edits position, size, layout (stacks and grids), typography, fill, borders, radius, shadows and effects. midcode writes styles as utility classes on the element, and how depends on the project.
Projects with Tailwind 4
midcode writes Tailwind’s own classes and swaps only the ones that change, so each edit is a minimal diff. Your @theme tokens show up in the panel as colors, fonts, sizes and radii, and the Design panel edits them.
<section className="px-6 py-16">
<section className="px-6 py-24">Projects without Tailwind
You don’t need Tailwind. In any other project (plain CSS, CSS modules, Bootstrap, Tailwind 3) midcode uses its own utilities, mid:, and turns them into plain CSS itself. Nothing is installed in your project.
<h1 className="title mid:text-[80px] mid:md:text-[56px] mid:hover:text-[#ff5b2e]">Hello</h1>@layer mid-utilities {
.mid\:text-\[80px\] { font-size: 80px !important; }
@media (width >= 48rem) {
.mid\:md\:text-\[56px\] { font-size: 56px !important; }
}
}- The syntax is Tailwind 4’s with the prefix first:
mid:<variant>:<utility>. - Your own classes are never touched, even if one is called
.flexor.p-3. Onlymid:classes are compiled. - Every declaration is
!important, so an edit made in midcode wins over the rule your CSS already has for that element. - Your site isn’t reset. What midcode inserts carries
mid-base, which scopes a small reset to it. - On your first style edit midcode creates
midcode.cssnext to your app’s entry and imports it there (the root layout in Next.js,main.tsxin Vite,root.tsxin React Router). It’s one undoable edit, and the file is published with your site.
Your theme
Colors, fonts and text styles you make in the Design panel go in .midcode/theme.css, and become utilities.
@theme {
--color-brand: #ff5b2e; /* mid:bg-brand, mid:text-brand */
--font-display: "Fraunces"; /* mid:font-display */
}
@utility lead { /* mid:lead, mid:md:lead */
font-size: 20px;
line-height: 1.5;
}The midcode package
The app keeps midcode.css up to date while your project is open in it. To build it anywhere else (your production build, CI, or after you or an agent wrote mid: classes by hand) add the package. It works the same with npm, pnpm and yarn.
npm install -D midcode
pnpm add -D midcode
yarn add -D midcodeAny project
{
"scripts": {
"prebuild": "midcode",
"dev:css": "midcode --watch"
}
}Vite, Astro, SvelteKit, React Router, Remix
import { defineConfig } from 'vite'
import midcode from 'midcode/vite'
export default defineConfig({ plugins: [midcode()] })Next.js
import withMidcode from 'midcode/next'
export default withMidcode({
// your config
})Starting without the app
If the project has no stylesheet yet, say where it goes and import it in your entry:
npx midcode --out src/midcode.cssimport './midcode.css'| Command | What it does |
|---|---|
midcode | Builds midcode.css once. |
midcode --watch | Builds it, and again whenever your code or theme changes. |
--root <dir> | The project folder. Default: the current one. |
--out <file> | Where midcode.css goes when the project has none. |
Code and your agent
Switch from Design to Code in the top bar for your project as files: a tree, tabs, an editor and a terminal. Saving there is undoable and shows up in Publish like any other edit.
The Agent tab runs your own agent (Claude Code, Codex, Gemini, Cursor or OpenCode) in your project, with your account. Send it the selected element or your open comments in one click; what it changes is undoable too.
Comments you leave on the canvas (C) are stored in .midcode/comments.json, each one with the file and line of its element, so any agent can read them without midcode.
Pages, content and languages
- Pages (Next.js): a tree you can reorder, add to and remove from. Dynamic routes list their pages.
- Site settings (Next.js): title, description, favicon and social image, written as Next.js metadata.
- CMS (beta): the lists in your code, JSON files and Markdown posts as tables. Each change is written into the file.
- Languages: every text of your site, per page and per language. Translate what’s missing on your Mac with Apple Intelligence, or hand it to your agent.
Publish
Publish lists what changed, in words. Choose the files, write a message, and midcode commits and pushes them. It never force-pushes and never touches files you didn’t choose. If the push fails, the commit stays local and you can retry.
Connecting GitHub and Vercel in Settings is optional: GitHub lets midcode push over https without git credentials set up, and Vercel shows the deploy each publish starts.
Until you publish, everything is undoable with ⌘ Z, one step per edit.
Shortcuts
| Key | Action |
|---|---|
| V | Inspect (select) |
| C | Comment |
| P | Preview the site |
| F | Frame: draw one on the canvas |
| S T | Insert a stack, a text |
| ⇧ G · ⇧ I · ⇧ V | Insert a grid, an image, a video |
| ← ↑ → ↓ | Move 1 px (with ⇧: the nudge amount) |
| ⌘ Z · ⇧ ⌘ Z | Undo, redo |
| ⌘ C · ⌘ V · ⌘ D | Copy, paste, duplicate an element |
| ⌥ ⌘ V | Paste styles |
| ⌫ | Delete the selection |
| Space + drag | Pan the canvas |
| ⌘ + scroll | Zoom |
| ⌘ 1 · ⌘ 0 | Zoom to fit, actual size |
| ⇧ ⌘ C | Copy the element’s reference (file:line) for your agent |
| ⌘ ↑ | Select the parent |
| ⌘ , | Settings |
| Esc | Let go: the tool, the selection, the component |
Good to know
What does midcode add to my project?
A .midcode/ folder (comments, layer names, your breakpoints, the theme). In projects without Tailwind 4, midcode.css and one import. In Next.js, the canvas page app/midcode-scratch if you use it. All of it is plain files you can read, commit or delete.
Can I stop using it?
Yes. Your project never depends on the app. If you used mid: classes, keep midcode.css (or the package) and the site keeps working.
The style I changed doesn’t show
In a project without Tailwind, check that midcode.css is imported in your app’s entry. midcode says so when it can’t find where to import it.
My dev server is already running
Next.js allows one dev server per folder. midcode offers to stop the other one, or close it yourself and reload.