A multi-framework design tool that understands your design system, sits on top of your production code, and writes changes back to source.
Active development — things will break, APIs will change. If you like living on the edge, the source is open and the packages are published.
Pick your framework and follow the setup below. Each one takes under a minute.
- Node.js 18+
- A running dev server for your app
npm install -D @designtools/next-plugin// next.config.ts
import { withDesigntools } from "@designtools/next-plugin";
export default withDesigntools({
/* your existing config */
});# Terminal 1 — start your app
npm run dev
# Terminal 2 — start surface
npx @designtools/surfaceDemo:
demos/studio-app— Tailwind CSS v4 + CVA components
npm install -D @designtools/vite-plugin// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import designtools from "@designtools/vite-plugin";
export default defineConfig({
plugins: [designtools(), react()],
});# Terminal 1 — start your app
npm run dev
# Terminal 2 — start surface
npx @designtools/surfaceDemo:
demos/vite-app— Tailwind CSS v4
Remix uses Vite under the hood, so the setup is the same as Vite + React.
npm install -D @designtools/vite-plugin// vite.config.ts
import { defineConfig } from "vite";
import { reactRouter } from "@react-router/dev/vite";
import designtools from "@designtools/vite-plugin";
export default defineConfig({
plugins: [designtools(), reactRouter()],
});npx @designtools/surfaceDemo:
demos/remix-app
npm install -D @designtools/astro-plugin// astro.config.mjs
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
import designtools from "@designtools/astro-plugin";
export default defineConfig({
integrations: [react(), designtools()],
});npx @designtools/surfaceDemo:
demos/astro-app— Astro + React islands
npm install -D @designtools/svelte-plugin// vite.config.ts
import { sveltekit } from "@sveltejs/kit/vite";
import designtools from "@designtools/svelte-plugin";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [sveltekit(), designtools()],
});npx @designtools/surfaceDemo:
demos/svelte-app— SvelteKit + Tailwind v4
Surface auto-detects your styling approach and writes changes in your project's native format.
| System | Detection | Write format | Status |
|---|---|---|---|
| Tailwind CSS v4 | tailwindcss ^4 in package.json |
Utility classes via resolved theme | Stable |
| Tailwind CSS v3 | tailwindcss ^3 + config file |
Utility classes via theme config | Stable |
| CSS Variables | --* custom properties in stylesheets |
Direct property writes in CSS files | Stable |
| Plain CSS | .css files with class selectors |
Direct property writes in CSS files | Stable |
| CSS Modules | .module.css imports in JSX |
Property writes in module CSS files | Stable |
| Sass / SCSS | — | — | Planned |
Surface uses a hybrid architecture where the selection component (<Surface />) lives inside the target app, while the editor UI is a separate Vite-served React app. The iframe loads the target app directly (no proxy), and all communication happens via postMessage.
Editor UI (localhost:4400)
|-- <iframe src="http://localhost:3000" /> <- direct, no proxy
| |
| +-- Target app with <Surface /> component
| mounted by framework plugin
| communicates via postMessage
|
+-- Write server (API routes on same port)
Key design decisions:
data-sourceattributes (injected at compile time) map every element to its exact file:line:col- CSS property/value pairs as the universal editing primitive, with hints to preserve tokens
- Framework plugins and styling-system adapters are orthogonal
- Tailwind theme resolution for both v3 configs and v4
@themeblocks
| Package | Description |
|---|---|
@designtools/surface |
Hybrid visual editor — CLI + write server + React editor UI |
@designtools/next-plugin |
Next.js config wrapper — data-source Babel transform + <Surface /> mount |
@designtools/vite-plugin |
Vite plugin — data-source transform + <Surface /> auto-mount |
@designtools/astro-plugin |
Astro integration — .astro template transform + <Surface /> auto-mount |
@designtools/svelte-plugin |
SvelteKit plugin — .svelte template transform + <Surface /> auto-mount |
| Demo | Framework | Styling | Run command |
|---|---|---|---|
demos/next-react-tailwind |
Next.js | Tailwind CSS v4, CVA, OKLch tokens | npm run demo:next-react-tailwind |
demos/vite-react-tailwind |
Vite + React | Tailwind CSS v4 | npm run demo:vite-react-tailwind |
demos/remix-react-tailwind |
Remix | Tailwind CSS v4 | npm run demo:remix-react-tailwind |
demos/vite-react-tailwind-v3 |
Vite + React | Tailwind CSS v3 custom theme | npm run demo:vite-react-tailwind-v3 |
demos/vite-react-css |
Vite + React | Plain CSS + CSS Variables + CSS Modules | npm run demo:vite-react-css |
demos/astro-css |
Astro | Plain CSS + scoped styles | npm run demo:astro-css |
demos/svelte-css |
SvelteKit | Scoped styles + CSS Variables | npm run demo:svelte-css |
demos/svelte-tailwind |
SvelteKit | Tailwind CSS v4 | npm run demo:svelte-tailwind |
# Clone and build
git clone https://github.com/andflett/designtools.git
cd designtools
npm install
npm run build
# Install a demo and run
cd demos/next-react-tailwind && npm install && cd ../..
# Terminal 1
cd demos/next-react-tailwind && npm run dev
# Terminal 2
npm run demo:next-react-tailwindThe editor opens at http://localhost:4400.
designtools/
├── packages/
│ ├── surface/ Hybrid visual editor
│ ├── next-plugin/ Next.js config wrapper + data-source transform
│ ├── vite-plugin/ Vite plugin + data-source transform
│ ├── astro-plugin/ Astro integration + .astro template transform
│ └── svelte-plugin/ SvelteKit plugin + .svelte template transform
├── demos/
│ ├── next-react-tailwind/ Next.js + Tailwind v4 + CVA
│ ├── vite-react-tailwind/ Vite + React + Tailwind v4
│ ├── remix-react-tailwind/ Remix + Tailwind v4
│ ├── vite-react-tailwind-v3/ Vite + Tailwind v3 custom theme
│ ├── vite-react-css/ Plain CSS + CSS Variables + CSS Modules
│ ├── astro-css/ Astro + plain CSS + scoped styles
│ ├── svelte-css/ SvelteKit + scoped styles + CSS vars
│ └── svelte-tailwind/ SvelteKit + Tailwind v4
├── tests/
│ ├── e2e/ Playwright E2E tests (per-project directories)
│ └── fixtures/ Test fixture projects (integration tests)
To test local changes against your own project:
cd /path/to/designtools
npm run build# Next.js
cd packages/next-plugin && npm link
cd /path/to/your-app && npm link @designtools/next-plugin
# Vite / Remix
cd packages/vite-plugin && npm link
cd /path/to/your-app && npm link @designtools/vite-plugin
# Astro
cd packages/astro-plugin && npm link
cd /path/to/your-app && npm link @designtools/astro-plugin
# SvelteKit
cd packages/svelte-plugin && npm link
cd /path/to/your-app && npm link @designtools/svelte-plugin# Terminal 1
cd /path/to/your-app && npm run dev
# Terminal 2
cd /path/to/your-app && node /path/to/designtools/packages/surface/dist/cli.jsRebuild and the link picks up changes automatically:
cd /path/to/designtools
npm run buildThen restart the dev server and surface.
npm installin the target project removes links. Re-runnpm linkafter installing.
npm test # run all tests once
npm run test:watch # watch modePlaywright starts the required demo servers automatically via webServer config.
# Run all E2E tests
npm run test:e2e
# Run with Playwright UI
npm run test:e2e:ui
# Run a single project
npx playwright test --project=next-react-tailwind
npx playwright test --project=vite-react-tailwind
npx playwright test --project=vite-react-css
npx playwright test --project=astro-css
npx playwright test --project=svelte-css
npx playwright test --project=svelte-tailwind
npx playwright test --project=remix-react-tailwind
npx playwright test --project=vite-react-tailwind-v3
# Run a single spec file
npx playwright test --project=vite-react-css tests/e2e/vite-react-css/element-css-modules.spec.ts| Project | Demo | What it tests |
|---|---|---|
next-react-tailwind |
next-react-tailwind | Tailwind v4 classes, CVA component/instance editing, selection, color tokens |
vite-react-tailwind |
vite-react-tailwind | Tailwind v4 class editing, token CRUD (@theme block) |
vite-react-css |
vite-react-css | Plain CSS properties, CSS Modules, token add/delete (:root) |
astro-css |
astro-css | Scoped styles, CSS variables |
svelte-css |
svelte-css | Scoped styles, CSS variables |
svelte-tailwind |
svelte-tailwind | Tailwind v4 classes on .svelte files, token editing |
remix-react-tailwind |
remix-react-tailwind | Tailwind v4 class editing (Remix) |
vite-react-tailwind-v3 |
vite-react-tailwind-v3 | Tailwind v3 class editing |
CC BY-NC 4.0 — free to use and modify for non-commercial purposes with attribution. See LICENSE for details.