Andrew Flett
Andrew Flett
<Button
variant="primary"
size="lg"
className="mt-4"
>
Get Started
</Button>
Button
components/ui/button.tsx:41:6
Tokens
Component
Page
Padding
16px
Font size
14px
Border
1px
Width
auto

Refine your AI-generated designs with a tool that sits on top of your codebase and writes changes back to source

The gap between design and engineering has always existed because the two disciplines worked in fundamentally different mediums. Designers pushed pixels in one tool, engineers wrote code in another, and the space between them filled up with handoffs, redlines, and miscommunication.

AI changes this. Code is now a pliable enough medium to be used for rapid, exploratory design, and that means it can be used much earlier in the process, by people who have never written a line of it. Code was always the final artefact. Now it can be the first one too, and whether the initial draft comes from AI or an engineer, the designer can step in and refine it directly.

@designtools/codesurface is built for that world. It scans your codebase to extract your design tokens, maps your components with their current styles and props, and provides a visual editing layer that writes changes straight back to source. No import, no export, no handoff.

Systems, not screens

The editor follows frontend code convention to encourage design-system thinking rather than freeform pixel pushing. There is a clear distinction between Token, Component, and Instance editing, and it encourages working with props and tokens first, only allowing arbitrary styles when you specifically need them.

Token

Edit design tokens. Changes write to your CSS file and propagate across the entire system. Includes contrast ratio checking against foreground/background pairs.

Token editing mode showing OKLCH colour sliders and contrast ratio checking

Component

Edit the component definition itself: the Tailwind classes applied to each variant option. Changes apply to every instance of that component. Nested tree view shows variant dimensions and their options.

Component editing mode showing variant dimensions and Tailwind classes

Instance

Edit a specific usage of a component where it appears in your app. Swap variant options, change size, override Tailwind classes. Property panel groups classes by category (layout, spacing, typography, colour).

Instance editing mode showing variant options and class overrides

Component usage

Because you are editing a real product and not a whiteboard, it also lets you quickly view every place a shared component is used, so you can see how your changes land across different contexts.

Component usage view showing all instances of a component across the codebase

Explore

The element tree shows the full structure of your page and layout, with plain HTML elements and recognised components displayed alongside their text content. Collapsible sections let you drill into nested layouts, and clicking any node selects it for editing. It is a faster way to reach deeply nested elements than trying to click the right pixel in the viewport.

Explore panel showing the page element tree with components, HTML elements, and text previews

Isolate

Because codesurface understands your components through its AST scans, it can generate live previews of every variant combination automatically. Isolate mode renders these side by side so you can see default, outline, ghost, and every other state in one place, then make edits and watch them propagate across all combinations at once. No more toggling props in Storybook or clicking through your app to check each state individually.

Isolate mode showing a Button component rendered in default, outline, and ghost variants

How it works

The editor UI runs as its own Vite-served React app alongside your dev server. Your app runs unmodified in an iframe, and the two communicate via a language-agnostic postMessage protocol that deals in tokenised and computed styles rather than framework-specific abstractions. A small Babel plugin adds source-location attributes to your JSX at compile time, giving the editor exact file:line:col mappings without modifying your source files.

When you click an element, the protocol sends its tag, classes, source coordinates, and text content to the editor. The editor cross-references this against scan data, a static analysis of your project's CSS tokens, component definitions, and route structure, then presents contextual editing controls. An Express server handles the write side, exposing API routes that update your source files via AST-aware transforms.

Understanding your codebase

Frameworks

Detects your application and styling frameworks automatically. A one-line Next.js plugin handles the compile-time instrumentation.

Tokens

Parses your CSS for custom properties, categorises them (colour, radius, spacing), groups by prefix, and resolves values per theme.

Components

Uses AST analysis to scan your components, extract variant dimensions, map current styles and props, and resolve the Tailwind classes applied to each variant option.

Edits are AST-aware where they need to be. Token changes write directly to CSS custom properties under the correct selector (:root or .dark). Component class changes find and replace within the source file. Instance prop changes locate the JSX usage by component name and text hint, then update the attribute.

Setup

Install both @designtools/codesurface and the Next.js plugin as dev dependencies:

code
npm install -D @designtools/codesurface @designtools/next-plugin

Wrap your Next.js config to enable the source-mapping Babel plugin and auto-mount the selection overlay:

code
// next.config.ts
import { withDesigntools } from "@designtools/next-plugin";

const nextConfig = {
  // your existing config
};

export default withDesigntools(nextConfig);

This injects data-source attributes into every JSX element at compile time and auto-mounts the <CodeSurface /> overlay in your root layout. Neither is included in production builds.

Then start your dev server and run codesurface from your project root:

code
# Terminal 1
npm run dev

# Terminal 2
npx codesurface

The editor opens at localhost:4400 with your app embedded in an iframe. Click any element to start editing.

FlagDefaultDescription
--port3000Port your dev server runs on
--tool-port4400Port for the editor UI

Supported frameworks

Currently codesurface supports Next.js 14+ with React 18+ and Tailwind CSS v3/v4. The postMessage protocol between your app and the editor is framework-agnostic and deals solely in computed styles, so support for other frameworks is a matter of adding new adapters rather than rethinking the architecture.

Try it

Clone the repo and run it against one of the included demos:

github.com/andflett/designtools

code
git clone https://github.com/andflett/designtools.git
cd designtools
npm install
npm run build

# Terminal 1 — start a demo
npm run demo

# Terminal 2 — start codesurface
npx codesurface

Requirements

  • Next.js 14+ with App Router
  • React 18+
  • Tailwind CSS v3 or v4
  • Node.js 18+

What it doesn't do

This is not a standalone design tool. It does not generate components, suggest layouts, or manage documentation. It is a code-first design tool for people who already work in code and want tighter feedback loops when tuning tokens, variants, and instances against the real thing. It runs on top of your codebase, not alongside it, and there is nothing to import or export.

Part of @designtools

@designtools/codesurface is part of a growing suite of open-source, CLI-based design tools that all follow the same pattern: detect your framework, scan your source files, open a visual editor in the browser, and write changes back where they came from. No config files, no plugins, no build step integration required.

Edit global shadows visually and write changes straight back to your code

The companion tool for visually editing box-shadow values across your project