Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ jobs:
- run: npm ci
- run: npm run typecheck
- run: npm run build
- run: node scripts/size.mjs
- run: node scripts/brand-export.mjs --check
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
node_modules
dist
.vercel

# Brand docs: kept locally, not part of the repo
site/brand/
docs/brand-*.md
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to PixelSpec are listed here. The site's changelog page (`site/changelog.html`) shows the same entries.

## Unreleased (0.3.0)

New look.

### Changed

- New PixelSpec mark and an original outline icon set, all drawn on the same grid so they line up.
- Keyboard shortcuts show as keycaps. Glows removed from the toolbar and popover.
- The toolbar stays pinned to its corner and can no longer be dragged. Positions saved by older versions are ignored.

## 0.2.1 (2026-10-20)

Bug fixes.
Expand Down
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ In a second terminal, run `npm run dev` to rebuild on every change, then refresh
| `src/panel.ts` | The spec card and the "All properties" list |
| `src/inspect.ts` | Reading the element: selectors, components, accessibility, AI and CSS export |
| `src/styles.ts` | All UI styles (the overlay lives in a shadow root) |
| `src/icons.ts` | Hugeicons used in the UI, bundled at build time |
| `src/icons.ts` | The UI icons. They are generated from `scripts/icons.mjs` into `src/brand.gen.ts` by `npm run brand` |
| `site/` | The pixelspec.dev landing page |
| `src/react.ts` | The `<PixelSpec />` React component |
| `src/auto.ts` | The drop-in `<script>` build |
| `demo/` | A test page for trying changes |
Expand Down
39 changes: 25 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
# PixelSpec
# PixelSpec: visual feedback and CSS inspector for AI coding agents

**Design inspector and spacing overlay for any website, with AI-ready feedback.**
**Pixel-perfect UI feedback for AI agents. Inspect your live site, pin notes to any element, and copy feedback your agent can act on.**

[![CI](https://github.com/yesith0106/pixelspec/actions/workflows/ci.yml/badge.svg)](https://github.com/yesith0106/pixelspec/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/pixelspec.svg)](https://www.npmjs.com/package/pixelspec)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

**Website and live demo: [pixelspec.dev](https://www.pixelspec.dev)**
**[pixelspec.dev](https://www.pixelspec.dev)** · [Install](#quick-start) · [How to use it](#how-to-use-it) · [Copy for AI](#copy-for-ai)

PixelSpec lets you measure spacing between elements right in the browser: padding, margin, gaps, distances, letter spacing, line height, colors and contrast, like a design tool's inspect panel on top of the live page. Click any element to leave feedback, then copy it all as a compact prompt for your AI coding agent. It is an open-source [agentation](https://agentation.com) alternative with built-in design inspection.
PixelSpec is a free, open-source design QA tool that runs as an overlay on your website in development. Measure padding, margin, gaps and the distance between elements, check typography and color contrast, and click any element to leave a note. Then copy every note as a compact prompt with the selector, component, size and styles, and paste it into Claude Code, Cursor, Codex, Copilot or any AI coding agent.

![PixelSpec demo: hover to inspect, click for specs, measure distances, leave feedback and copy it for your AI agent](docs/demo.gif)

- Works on any site and any framework. React, Vue and Svelte component names are detected automatically.
- Zero runtime dependencies. The overlay lives in a shadow root, so it never touches your styles.
- One file for a plain `<script>` tag, or an npm package with a React component.
## Who it's for

- **Designers** doing design QA on the real build. Check spacing, type and color on the shipped page and leave notes on the exact element instead of sending annotated screenshots.
- **Vibe coders** building with AI. Stop describing visual bugs in words. Click the element, say what should change, and your agent gets the selector and styles it needs to fix it in one pass.
- **Frontend developers** who want a fast spacing inspector and pixel-perfect redlines without opening DevTools.

## Why PixelSpec

- **Exact, not approximate.** Real computed values from the browser: padding, margin, gap, redline distances, font, line height, letter spacing, colors and WCAG contrast.
- **Made for your agent.** Feedback copies as two compact lines per element to save tokens, or as full Markdown.
- **Invisible to your app.** It lives in its own shadow root, has zero runtime dependencies and is about 28 KB gzipped. Load it in development only.
- **Works everywhere.** Any site and any framework: React, Next.js, Vite, Vue, Svelte or plain HTML. React, Vue and Svelte component names are detected automatically.

## Quick start

Expand Down Expand Up @@ -66,13 +75,13 @@ To work offline, download `pixelspec.global.js` from the [latest release](https:

Optional attributes: `data-active="true"` to start open, `data-hotkey="alt+shift+i"`, `data-position="bottom-left"` and `data-ai-detail="full"`.

**Then open your page.** Click the round button in the bottom-right corner, or press <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd>.
**Then open your page.** Click the PixelSpec button in the bottom-right corner, or press <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd>.

## How to use it

1. **Hover** anything to see its name and size.
2. **Click** an element. A popover opens where you clicked, with the key specs: size, padding, margin, gap, layout, font, color, contrast, radius and shadow. Click any value to copy it. The spacing icons use the overlay colors: green is padding, orange is margin, pink is gap.
3. **Hover another element** to see red redline distances between them. Hold <kbd>Alt</kbd> to measure to the parent.
3. **Hover another element** to see red redline distances. Hold <kbd>Alt</kbd> to measure to the parent.
4. **Type feedback** and press <kbd>Enter</kbd>. A numbered marker appears on the element. Hover a marker to read the note, click it to edit or delete.
5. **Select text** on the page to leave feedback that quotes it.
6. **Copy** with the toolbar's copy button or <kbd>C</kbd>, and paste it into your agent.
Expand All @@ -81,7 +90,7 @@ In the popover header, click the element name to copy its selector, or the code

### Toolbar

The toolbar can be dragged anywhere, and it remembers where you put it.
The toolbar stays pinned to its corner (bottom right by default, or `position: 'bottom-left'`).

| Button | Key | What it does |
| --- | --- | --- |
Expand All @@ -105,9 +114,10 @@ While the toolbar is open, clicks on the page are blocked so links and buttons d
Copied feedback uses a compact format by default to save tokens. It has two lines per element and only non-default values:

```
Make this button bigger
body>header>button.cta "Start free trial"
126×34 p:10 18 r:999 | system-ui 14/14 w600 ls:0.01em | c:#FFF bg:#3581F6 contrast:3.7(fails AA)
UI feedback for /pricing (1440×900):
1. Make this button bigger
body>header>button.cta "Start free trial"
126×34 p:10 18 r:999 | system-ui 14/14 w600 ls:0.01em | c:#FFF bg:#3581F6 contrast:3.7(fails AA)
```

Key: `p` padding, `m` margin, `b` border, `r` radius, `14/14 w600` size/line-height and weight, `ls` letter spacing, `c` text color, `bg` background. Contrast only appears when it fails AA. Containers skip text and typography.
Expand Down Expand Up @@ -137,6 +147,7 @@ The React component takes the same options as props, plus `enabled`. The instanc
- Rendered font detection is a heuristic based on loaded font faces and canvas measurement.
- Component source paths need a dev build. React 19 removed `_debugSource`, so React 19 shows names only.
- Elements inside closed shadow roots and cross-origin iframes can't be inspected.
- Needs a browser with CSS `color-mix()`: Chrome 111, Safari 16.2, Firefox 113 or newer.

## Contributing

Expand All @@ -151,4 +162,4 @@ npm run demo # http://localhost:5178/demo/

## License

[MIT](LICENSE). Icons are from the free [Hugeicons](https://hugeicons.com) set, also MIT, and only the icons in use are bundled.
[MIT](LICENSE). Free for personal and commercial use.
82 changes: 82 additions & 0 deletions demo/hero/pricing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Northwind pricing</title>
<!-- Scene for the landing page demo clip (site/assets/demo.webm). Recorded at 1280 x 720. -->
<style>
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
overflow: hidden; background: #F6F7F9; color: #111827;
font: 400 16px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}
header { display: flex; align-items: center; justify-content: space-between; height: 72px; padding: 0 56px; background: #fff; border-bottom: 1px solid #E5E7EB; }
.logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 19px; letter-spacing: -0.02em; }
.logo i { width: 26px; height: 26px; border-radius: 7px; background: linear-gradient(135deg, #6366F1, #8B5CF6); }
nav { display: flex; gap: 32px; font-size: 14px; font-weight: 500; color: #4B5563; }
.cta { padding: 10px 18px; border: 0; border-radius: 8px; background: #111827; color: #fff; font: 600 14px/1 inherit; font-family: inherit; }
.hero { text-align: center; padding: 48px 0 32px; }
.eyebrow { margin: 0 0 12px; font-size: 13px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: #6366F1; }
h1 { margin: 0 0 12px; font-size: 44px; line-height: 1.1; letter-spacing: -0.03em; font-weight: 700; }
.lede { margin: 0 auto; max-width: 520px; font-size: 17px; color: #6B7280; }
.plans { display: grid; grid-template-columns: repeat(3, 300px); gap: 24px; justify-content: center; }
.card { position: relative; padding: 28px 26px; background: #fff; border: 1px solid #E5E7EB; border-radius: 16px; box-shadow: 0 1px 2px rgba(17,24,39,.04); }
.card.pop { border-color: #6366F1; box-shadow: 0 12px 32px -12px rgba(99,102,241,.35); }
.badge { position: absolute; top: -12px; left: 26px; padding: 4px 10px; border-radius: 999px; background: #6366F1; color: #fff; font-size: 12px; font-weight: 600; }
.card h3 { margin: 0 0 6px; font-size: 18px; font-weight: 600; }
.card .desc { margin: 0 0 18px; font-size: 14px; color: #6B7280; }
.price { display: flex; align-items: baseline; gap: 4px; margin-bottom: 18px; }
.price b { font-size: 38px; letter-spacing: -0.03em; }
.price span { color: #6B7280; font-size: 14px; }
.card ul { list-style: none; margin: 0 0 22px; padding: 0; display: grid; gap: 8px; font-size: 14px; color: #374151; }
.card li::before { content: '✓'; margin-right: 8px; color: #10B981; font-weight: 700; }
.buy { width: 100%; padding: 12px; border-radius: 10px; border: 1px solid #D1D5DB; background: #fff; font: 600 14px/1 inherit; font-family: inherit; color: #111827; }
.pop .buy { background: #6366F1; border-color: #6366F1; color: #fff; }

/* Headless recordings don't capture the real cursor, so draw one. */
#cur { position: fixed; left: 0; top: 0; z-index: 2147483647; width: 18px; height: 26px; pointer-events: none; transform: translate(-100px, -100px); }
</style>
</head>
<body>
<header>
<div class="logo"><i></i>Northwind</div>
<nav><span>Product</span><span>Pricing</span><span>Customers</span><span>Docs</span></nav>
<button class="cta">Start free trial</button>
</header>
<section class="hero">
<p class="eyebrow">Pricing</p>
<h1>Plans that scale with you</h1>
<p class="lede">Start free, upgrade when your team grows. Every plan includes unlimited projects.</p>
</section>
<section class="plans">
<article class="card">
<h3>Starter</h3><p class="desc">For side projects</p>
<div class="price"><b>$0</b><span>/ month</span></div>
<ul><li>3 collaborators</li><li>Unlimited projects</li><li>Community support</li></ul>
<button class="buy">Get started</button>
</article>
<article class="card pop">
<span class="badge">Most popular</span>
<h3>Pro</h3><p class="desc">For growing teams</p>
<div class="price"><b>$12</b><span>/ user / month</span></div>
<ul><li>Unlimited collaborators</li><li>Version history</li><li>Priority support</li></ul>
<button class="buy">Start free trial</button>
</article>
<article class="card">
<h3>Enterprise</h3><p class="desc">For large organisations</p>
<div class="price"><b>Custom</b></div>
<ul><li>SSO and SCIM</li><li>Audit logs</li><li>Dedicated manager</li></ul>
<button class="buy">Contact sales</button>
</article>
</section>

<svg id="cur" viewBox="0 0 12 19" shape-rendering="crispEdges" aria-hidden="true"><path fill="#111" d="M0 0h1v18H0zM1 1h1v1H1zM2 2h1v1H2zM3 3h1v1H3zM4 4h1v1H4zM5 5h1v1H5zM6 6h1v1H6zM7 7h1v1H7zM8 8h1v1H8zM9 9h1v1H9zM10 10h1v1h-1zM6 10h4v1H6zM6 11h1v2H6zM3 12h1v1H3zM2 13h1v1H2zM1 14h1v1H1zM7 13h1v2H7zM8 15h1v2H8zM6 17h2v1H6zM4 12h1v2H4zM5 14h1v2H5z"/><path fill="#fff" d="M1 2h1v12H1zM2 3h1v10H2zM3 4h1v8H3zM4 5h1v7H4zM5 6h1v8H5zM6 7h1v3H6zM7 8h1v2H7zM8 9h1v1H8zM6 13h1v4H6zM7 15h1v2H7z"/></svg>
<script>
const cur = document.getElementById('cur');
addEventListener('pointermove', (e) => { cur.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`; }, { passive: true, capture: true });
</script>
<script src="../../dist/pixelspec.global.js"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 25 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pixelspec",
"version": "0.2.1",
"description": "Design inspector and spacing overlay for any website: measure padding, margin, gaps, distances, typography, colors and contrast, then copy AI-ready feedback.",
"version": "0.3.0",
"description": "Visual feedback and CSS inspector for AI coding agents. Measure spacing, typography and color contrast on your live site, pin notes to any element, and copy pixel-perfect feedback for Claude Code, Cursor, Codex or Copilot.",
"license": "MIT",
"author": "Yesith (https://github.com/yesith0106)",
"homepage": "https://www.pixelspec.dev",
Expand Down Expand Up @@ -40,6 +40,8 @@
"dev": "tsup --watch",
"typecheck": "tsc --noEmit",
"demo": "node scripts/serve.mjs",
"brand": "node scripts/brand-export.mjs",
"size": "node scripts/size.mjs",
"prepare": "npm run build"
},
"peerDependencies": {
Expand All @@ -59,18 +61,30 @@
"keywords": [
"design inspector",
"css inspector",
"spacing",
"measure",
"redline",
"pixel perfect",
"spacing inspector",
"design qa",
"visual feedback",
"ui feedback",
"pixel perfect",
"redline",
"measure",
"padding",
"margin",
"typography",
"color contrast",
"wcag",
"devtools",
"overlay",
"typography",
"letter spacing",
"contrast",
"ai agent",
"visual feedback",
"agentation alternative"
"ai coding",
"vibe coding",
"claude code",
"cursor",
"copilot",
"codex",
"design handoff",
"react",
"nextjs",
"vite"
]
}
Loading
Loading