Draw on bugs. Let AI fix them.
npm i usemarkupkitMarkupKit turns freehand drawings into structured context AI coding agents can act on. Six annotation modes. Seven shape types. Four output levels. Spacing visualization, contrast checking, animation pause, localStorage persistence, screenshot capture, and source file detection.
Annotation modes
Six ways to annotate. Click the tabs to try each mode:
- Draw — freehand with 7 shape types and note input after each stroke
- Text — select any text, the exact string + element selector are captured
- Click — click any element, identified by content with full computed context
- Multi — click multiple elements, grouped in one annotation
- Area — drag a rectangle to select any region and its contained elements
- Pause — injects
animation-play-state: pausedglobally to freeze all CSS animations and transitions
Shape detection
Every drawing stroke gets classified with a confidence score. Seven types: circle (enclose elements), arrow (relate elements), strikethrough (remove text), underline (emphasize), cross (delete), rectangle (select area), freehand (fallback). The classifier scores each type and picks the highest above 0.35.
Smart identification
MarkupKit builds CSS selectors the way you'd search for them in code. Hover any element below:
Building tools for the agentic web.
React component detection
Reads the fiber tree via __reactFiber$ keys, falls back to data-component and data-testid attributes. Component names appear in the output alongside CSS selectors.
Spacing visualization
When hovering elements, MarkupKit renders padding as green zones and margin as amber zones on the canvas overlay with pixel values labeled. Toggle on/off in settings. Uses getComputedStyle to read live values.
Contrast checking
Every text element gets its WCAG 2.1 contrast ratio calculated from color and backgroundColor. The ratio, AA pass/fail, and AAA pass/fail appear in detailed and forensic output. Try the live checker:
Output
Four detail levels. Click each tab to see the same annotations rendered at each level:
Source file detection — reads _debugSource from the React fiber and data-source / data-file attributes. Appears at detailed and forensic levels.
Screenshot capture — click 📷 in the toolbar to download the annotation canvas as a PNG.
localStorage persistence — annotations survive page refresh. Toggle on/off in settings. Stored under markupkit_annotations.
Layout Mode
Annotations tell the agent this is wrong. Layout Mode tells the agent here's what I want instead.
Select an element, drag it somewhere new, resize it, drop a wireframe component from the palette. Every change is tracked with precise coordinates. Hit copy, paste into Claude Code or Cursor, and the agent applies it in one pass.
This demo is live. Click any element to select it. Drag to move. Drag the blue handles to resize. Click + Components to drop wireframe primitives.
// Drag, resize, or add elements above. Output appears here live.
<Markup layout /> // adds drag + resize + palette
Install
npm install usemarkupkit -D
import { Markup } from 'usemarkupkit' function App() { return ( <> <YourApp /> {process.env.NODE_ENV === "development" && <Markup />} </> ) }
Agent sync — pass endpoint to sync annotations to a server. Sessions are created on mount, annotations POSTed on change. Pass sessionId to rejoin an existing session. onSessionCreated fires when a new session is created.
<Markup endpoint="http://localhost:4747" onSessionCreated={(id) => console.log("Session:", id)} />
Props
All optional. Works with zero configuration.
enabled | Enable/disable (default: true) |
color | Stroke color (default: "#171717") |
strokeWidth | Stroke width in px (default: 3) |
tool | "draw" | "arrow" | "circle" | "eraser" |
detail | "compact" | "standard" | "detailed" | "forensic" |
toolbar | Show toolbar (default: true) |
position | Toolbar corner (default: "bottom-right") |
root | Scope selector (default: "body") |
ignore | Tags to skip (default: []) |
shortcut | Toggle shortcut (default: "ctrl+shift+d") |
copyToClipboard | Write to clipboard (default: true) |
onAnnotationAdd | Called when annotation created |
onAnnotationDelete | Called when annotation removed |
onAnnotationUpdate | Called when note edited |
onAnnotationsClear | Called when all cleared |
onCopy | Called when copy clicked (receives markdown) |
onDraw | Called per-stroke with DrawEvent |
endpoint | Server URL for syncing annotations |
sessionId | Pre-existing session to rejoin |
onSessionCreated | Called when new session created |
Programmatic API
import { detectShape, resolveShape, formatSession, resolveClickedElement, resolveTextSelection, resolveAreaSelection, getElementSpacingAtPoint, contrastRatio, smoothPoints, strokeBounds } from 'usemarkupkit' // Shape detection detectShape(stroke) // → { type: 'circle', confidence: 0.87 } // Element resolution for each mode resolveClickedElement(x, y) // → Annotation from click resolveTextSelection() // → Annotation from window.getSelection() resolveAreaSelection(bounds) // → Annotation from rectangle // Spacing + contrast getElementSpacingAtPoint(x, y) // → { spacing, rect } contrastRatio('rgb(23,23,23)', 'rgb(255,255,255)') // → 16.0
Keyboard shortcuts
| Ctrl+Shift+D | Toggle on/off |
| Esc | Cancel / close |
| P | Pause/resume animations |
| H | Hide/show markers |
| C | Copy annotations |
| X | Clear all |
Settings
The ⚙ button in the toolbar opens the settings panel. All settings are wired and take effect immediately:
~10kb gzipped · zero dependencies · React 18+ · MIT