npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@designtools/surface

v0.1.22

Published

Visual editing CLI — hybrid architecture with selection overlays in the target app and editor UI served separately

Downloads

992

Readme

@designtools/surface

A CLI-launched visual design layer for web applications. Select elements in your running app and edit styles, tokens, and component variants — changes write back to your source files.

Getting started

Pick your framework and follow the setup below. Each one takes under a minute.

Prerequisites

  • Node.js 18+
  • A running dev server for your app
  • A supported styling system: Tailwind CSS v3/v4, CSS Custom Properties, Plain CSS, or CSS Modules

Next.js

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/surface

Vite + React

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()],
});

The plugin must be listed before @vitejs/plugin-react.

# Terminal 1 — start your app
npm run dev

# Terminal 2 — start surface
npx @designtools/surface

Remix

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/surface

Astro

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/surface

SvelteKit

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/surface

What the plugins do

In development, each framework plugin:

  • Injects data-source="file:line:col" attributes into every element, mapping each element to its source location. These only exist in the compiled output — your source files are not modified.
  • Auto-mounts the <Surface /> selection overlay component into your app.

Neither is included in production builds.

Component editing with data-slot

For Surface to recognize reusable components (and distinguish them from plain HTML elements), add a data-slot attribute to the root element of each component:

// components/ui/button.tsx
export function Button({ children, className, ...props }) {
  return (
    <button data-slot="button" className={cn("...", className)} {...props}>
      {children}
    </button>
  );
}

The data-slot value should be a kebab-case name matching the component (e.g. card-title for CardTitle). This enables component-level editing — selecting a Button in the editor will let you modify its base styles in the component file, not just the instance.

Components without data-slot can still be selected and edited at the element level.

CLI options

| Flag | Default | Description | |------|---------|-------------| | --port | 3000 | Port your dev server runs on | | --tool-port | 4400 | Port for the editor UI | | --components | auto-detected | Path to your UI components directory | | --css | auto-detected | Path to your CSS tokens file |

Both ports auto-increment if the default is busy. Component and CSS paths are auto-detected but can be overridden when detection fails.

How it works

  1. Click an element in the iframe to select it
  2. The editor panel shows its computed styles, Tailwind classes, and source location
  3. Edit values — changes are written directly to your source files
  4. Your dev server picks up the file change and hot-reloads

For Tailwind projects, changes are written as utility classes. When a project customizes its Tailwind theme (v3 config or v4 @theme blocks), Surface resolves the custom scales and uses them for class suggestions. When no matching utility exists, arbitrary value syntax is used (e.g. text-[14px]).

For CSS/CSS Modules/CSS Variables projects, writes go directly to the relevant CSS files. Inline style fallback when no matching CSS rule is found.

What it can edit

  • Element styles — layout, spacing, typography, colors, borders, shadows, opacity
  • Design tokens — CSS custom properties in your stylesheets
  • Component variants — base classes and variant mappings (works with CVA)
  • Shadows — shadow token definitions in CSS or Tailwind @theme blocks
  • Gradients — gradient token definitions
  • Spacing — spacing scale tokens
  • Borders — border radius and border width tokens

Support matrix

Frameworks

| Framework | Plugin | Status | |-----------|--------|--------| | Next.js (App Router) | @designtools/next-plugin | Stable | | Vite + React | @designtools/vite-plugin | Stable | | Astro | @designtools/astro-plugin | Stable | | SvelteKit | @designtools/svelte-plugin | Stable | | Remix | @designtools/vite-plugin | Beta |

Styling systems

| System | Write format | Status | |--------|-------------|--------| | Tailwind CSS v4 | Utility classes via resolved theme | Stable | | Tailwind CSS v3 | Utility classes via theme config | Stable | | CSS Variables | Direct property writes in CSS files | Stable | | Plain CSS | Direct property writes in CSS files | Stable | | CSS Modules | Property writes in .module.css files | Stable | | Sass / SCSS | — | Planned |

Limitations

  • Development only — the plugin and overlays are stripped from production builds
  • Next.js App Router only — the auto-mount targets app/layout.tsx. Pages Router is not supported.
  • Remix — should work via Vite plugin but is not yet fully tested

License

CC-BY-NC-4.0