Install
Pick the setup that matches your prototype. Both load the same panel.
For projects you run with npm run dev (Vite, Next.js, Astro…). Run this in your project folder:
npm install -D @theoldpixel/twiddle
Then add two lines to your app’s entry file, for example main.js:
import '@theoldpixel/twiddle/tokens.css';
if (import.meta.env.DEV) import('@theoldpixel/twiddle');
The import.meta.env.DEV check keeps the panel out of your production build. In a framework without it, use your own dev check, such as process.env.NODE_ENV !== 'production'.
For a static HTML file with no build step. Nothing to install: paste these into your page.
<link rel="stylesheet" href="https://unpkg.com/@theoldpixel/twiddle/dist/twiddle-tokens.css">
<script src="https://unpkg.com/@theoldpixel/twiddle" defer></script>
Add a version, for example @theoldpixel/twiddle@0.1.1, to pin a release.
Style with tokens
The panel changes the --twd-* CSS variables. Anything you style with them responds to the panel; anything with fixed values stays as it is. Let your coding agent convert your styles, or write them yourself.
Paste this into Claude Code, Cursor or any agent working on your prototype. It replaces fixed values with tokens and keeps your current look as the starting point.
Convert this prototype's styles to use the Twiddle design tokens (the --twd-* CSS custom properties from @theoldpixel/twiddle), so the Twiddle panel can tweak them live.
1. Keep the current look. In a :root rule loaded after twiddle-tokens.css, set each token below to the value this project already uses (for example, if buttons use #0f766e, set --twd-primary: #0f766e). Only set the tokens the project actually needs.
2. Replace fixed values in component styles with var(--twd-…). Map each value to the closest token by role:
- Fonts: --twd-font-heading, --twd-font-body
- Text sizes: --twd-text-xs, -sm, -base, -lg, -xl, -2xl, -3xl; line height: --twd-leading-tight, --twd-leading-normal
- Colours: --twd-bg (page), --twd-surface (cards, inputs), --twd-surface-raised (menus, popovers), --twd-text, --twd-text-muted, --twd-border, --twd-primary, --twd-primary-hover, --twd-on-primary (text on primary), --twd-focus, --twd-success, --twd-warning, --twd-danger
- Buttons, inputs, chips: --twd-radius-control, --twd-control-height, --twd-control-pad-x
- Cards, menus, modals: --twd-radius-container, --twd-border-width-container
- Borders: --twd-border-width
- Spacing (padding, margin, gap): --twd-space-1 to --twd-space-8 (4, 8, 12, 16, 24, 32, 48, 64px)
- Shadows: --twd-shadow-sm, --twd-shadow-md, --twd-shadow-lg
3. Leave values that don't match a role as they are (layout widths, one-off illustrations, icon sizes). Don't invent new --twd-* tokens.
4. Don't change the layout or how the page looks; after the change it should look the same until someone uses the panel.
5. When done, list the files you changed and any values you left fixed, with the reason.
Use the tokens wherever you want a knob to have an effect:
.button {
height: var(--twd-control-height);
padding: 0 var(--twd-control-pad-x);
border-radius: var(--twd-radius-control);
background: var(--twd-primary);
color: var(--twd-on-primary);
font-family: var(--twd-font-body);
}
.card {
background: var(--twd-surface);
border: var(--twd-border-width-container) solid var(--twd-border);
border-radius: var(--twd-radius-container);
box-shadow: var(--twd-shadow-md);
padding: var(--twd-space-5);
}
To use your own defaults, redefine any token in your stylesheet after the Twiddle tokens. The panel then starts from your values:
:root {
--twd-primary: #0f766e;
--twd-radius-control: 6px;
--twd-font-heading: "Fraunces", Georgia, serif;
}
See the token reference for the full list.
Use the panel
Open it with the dial in the corner, or Alt T (Option T on a Mac). Try it on this sample:
Sample components
Pick one of these with the crosshair to change it on its own.
| Control | What it does |
|---|---|
| Sections | Typography, Colour, Buttons, Cards, Density and Depth change the whole page. |
| Pick (crosshair) | Click an element to tweak only that element. The panel shows just the settings it uses. Switch to All .class to change every element like it. |
| Compare (half circle) | Hold it, or press Alt C, to see the original page. |
| Copy link | Copies a link to this exact version. Settings live in the ?twd= part of the address. |
| Reset | Back to the page’s own defaults. Undo brings it back. |
| Undo / Redo | In the footer, or ⌘ Z / ⇧ ⌘ Z while the panel has focus. |
| Changes | Lists every tweak with the token values before and after. Remove any one with ×. |
To decide what “all like this” means for an element, add data-twd="name" to it. Twiddle groups by that name instead of the class.
Apply the changes
Tweaks in the panel live only in the link. To make them permanent, press Apply. Twiddle writes a prompt for your coding agent (Claude Code, Cursor or similar) that lists:
- token changes for the whole page, old value → new value
- changes for every element sharing a class
- single-element changes, described so the agent can find them
- any colour pairs that fail WCAG AA contrast
Paste it into the agent working on your prototype. Use the arrow next to Apply to choose between Preview, then copy and Copy immediately.
Token reference
Every --twd-* token, its default, and the panel section that changes it
| Token | Default | Panel section |
|---|---|---|
--twd-font-heading, --twd-font-body | System sans | Typography › Fonts |
--twd-text-xs … --twd-text-3xl | 0.694rem … 2.074rem (1.2 scale) | Typography › Base size, Scale |
--twd-leading-tight, --twd-leading-normal | 1.2, 1.5 | — |
--twd-primary, --twd-primary-hover, --twd-on-primary, --twd-focus | #4f46e5, #4338ca, #ffffff, #6366f1 | Colour › Brand |
--twd-bg, --twd-surface, --twd-surface-raised | #fafafa, #ffffff, #ffffff | Colour › Neutral, Mode |
--twd-text, --twd-text-muted, --twd-border | #18181b, #71717a, #e4e4e7 | Colour › Neutral, Mode |
--twd-success, --twd-warning, --twd-danger | #16a34a, #d97706, #dc2626 | — |
--twd-radius-control | 8px | Buttons › Corners |
--twd-control-height, --twd-control-pad-x | 40px, 16px | Buttons › Size |
--twd-radius-container | 12px | Cards › Corners |
--twd-border-width, --twd-border-width-container | 1px | Cards › Border |
--twd-space-1 … --twd-space-8 | 4, 8, 12, 16, 24, 32, 48, 64px | Density › Spacing |
--twd-shadow-sm, --twd-shadow-md, --twd-shadow-lg | Soft shadows | Depth › Style, Intensity |
Troubleshooting
The panel opens, but nothing on my page changes
Your CSS uses fixed values. Replace them with var(--twd-…) tokens (see step 2).
The Twiddle panel (@theoldpixel/twiddle) opens on this prototype, but changing its settings has no effect on the page. Find out why and fix it.
First check that the Twiddle tokens load before the project's own styles: either `import '@theoldpixel/twiddle/tokens.css'` in the entry file, or a `<link>` to twiddle-tokens.css in <head>.
Then convert the styles to use the tokens:
{{TOKENS_PROMPT}}
The dial doesn’t appear
Check that the script or import runs: with a build tool, the import.meta.env.DEV check only passes on the dev server. Then press Alt T in case the panel is closed.
Twiddle (@theoldpixel/twiddle) should show a round dial in the bottom-right corner of this prototype while it runs in development, but the dial doesn't appear. Find out why and fix it. Check, in order:
1. The package is installed: @theoldpixel/twiddle is in package.json (devDependencies is fine) and in node_modules.
2. The app's entry file loads it:
import '@theoldpixel/twiddle/tokens.css';
if (import.meta.env.DEV) import('@theoldpixel/twiddle');
If this project doesn't use Vite, replace import.meta.env.DEV with this framework's own development check. In frameworks with server rendering (such as Next.js), make sure the import runs in the browser, for example inside a client component's effect.
3. For a plain HTML page: the <script src="https://unpkg.com/@theoldpixel/twiddle" defer></script> tag is present, and nothing (such as a Content Security Policy) blocks unpkg.com.
4. The browser console shows no errors from Twiddle.
Keep Twiddle out of production builds. When done, tell me what was wrong and what you changed.
A picked element lost its tweaks after I changed the page
Single-element tweaks find the element by its position in the page. Give it an id or a data-twd name before tweaking, so it can be found again.
This prototype uses Twiddle (@theoldpixel/twiddle) to tweak individual elements. Twiddle finds a picked element by its position in the page, so tweaks get lost when the markup changes. Give elements stable hooks so tweaks survive edits: 1. Give each important one-off element a unique, descriptive id (for example id="hero-cta" or id="signup-email"). Twiddle uses the id to find a single element. 2. Give each reusable component a data-twd attribute naming the component (for example data-twd="primary-button", data-twd="text-input", data-twd="card"). Twiddle uses it to apply a tweak to every element of that kind. 3. Only add attributes. Don't change styles, classes or structure, and don't rename ids that scripts or links already rely on. When done, list the ids and data-twd names you added.