Agent skill
alignment-verification
Zero-tolerance alignment verification protocol. Alignment is binary - elements are either in line or they're not. Report exact measurements, no tolerances, no "close enough."
Install this agent skill to your Project
npx add-skill https://github.com/adilkalam/orca/tree/main/skills/alignment-verification
SKILL.md
Alignment Verification Skill
RULE: Alignment is BINARY. In line or not. Zero tolerances.
Core Principle
Alignment verification has exactly two outcomes:
- Delta = 0px --> ALIGNED: YES
- Delta > 0px --> ALIGNED: NO (report exact deviation)
There are NO tolerances. A 2px deviation in a row of chips is visible. A 1px misalignment between form labels is noticeable. "Close enough" does not exist.
When you claim something is aligned, you MUST prove it with pixel measurements.
Mental Model
Alignment is a RELATIONSHIP between elements, not a property of a single element.
Every alignment check requires:
- Target Element(s) - What you are checking
- Reference Element - What you are aligning TO (parent, sibling, baseline)
- Alignment Type - How they should relate (center, edge, spacing)
- Container Space - For alignment to work, there must be space to align within
Example mental model:
"Button should be horizontally centered in its parent"
- Target: the button
- Reference: the parent container
- Type: horizontal center
- Container: parent must be wider than button for centering to be meaningful
Verification Protocol
Step 1: Identify What Should Align
Before measuring, explicitly state:
- Which elements are being checked
- What type of alignment is expected
- What the reference point is
Step 2: Extract Exact Pixel Values
Use Puppeteer's evaluate to get precise measurements:
// Get element bounding box via puppeteer_evaluate
puppeteer_evaluate({
script: `
const el = document.querySelector('[selector]');
const box = el.getBoundingClientRect();
JSON.stringify({ x: box.x, y: box.y, width: box.width, height: box.height });
`
})
// Returns: { x, y, width, height }
Extract ALL values needed for your alignment type.
Step 3: Calculate Exact Deviations
Calculate with full precision. DO NOT round. DO NOT apply tolerances.
// For horizontal centering in parent
const parentBox = await page.locator('[parent]').boundingBox();
const childBox = await page.locator('[child]').boundingBox();
const parentCenter = parentBox.x + (parentBox.width / 2);
const childCenter = childBox.x + (childBox.width / 2);
const deviation = Math.abs(parentCenter - childCenter);
// Report: deviation === 0 ? "ALIGNED: YES" : `ALIGNED: NO (${deviation}px off)`
Step 4: Output ALIGNMENT_CHECK Block
Every alignment verification MUST produce this output:
ALIGNMENT_CHECK:
- Task: [alignment goal in plain language]
- Type: [horizontal_center|vertical_center|left_edge|right_edge|top_edge|bottom_edge|spacing]
- Elements measured:
- [selector]: [value]px
- [selector]: [value]px
- ALIGNED: YES/NO
- Max deviation: Xpx
- Deviations: [list if multiple elements]
Alignment Types with Code
Center Horizontally in Parent
// Measure
const parent = await page.locator('.parent').boundingBox();
const child = await page.locator('.child').boundingBox();
// Calculate
const parentCenterX = parent.x + (parent.width / 2);
const childCenterX = child.x + (child.width / 2);
const deviation = Math.abs(parentCenterX - childCenterX);
// Report
console.log(`Parent center: ${parentCenterX}px`);
console.log(`Child center: ${childCenterX}px`);
console.log(`Deviation: ${deviation}px`);
console.log(`ALIGNED: ${deviation === 0 ? 'YES' : 'NO'}`);
Center Vertically in Parent
// Measure
const parent = await page.locator('.parent').boundingBox();
const child = await page.locator('.child').boundingBox();
// Calculate
const parentCenterY = parent.y + (parent.height / 2);
const childCenterY = child.y + (child.height / 2);
const deviation = Math.abs(parentCenterY - childCenterY);
// Report
console.log(`Parent center Y: ${parentCenterY}px`);
console.log(`Child center Y: ${childCenterY}px`);
console.log(`Deviation: ${deviation}px`);
console.log(`ALIGNED: ${deviation === 0 ? 'YES' : 'NO'}`);
Left Edge Alignment (Multiple Elements)
// Measure all elements
const elements = await page.locator('.item').all();
const leftEdges = [];
for (const el of elements) {
const box = await el.boundingBox();
leftEdges.push(box.x);
}
// Calculate deviations from first element
const reference = leftEdges[0];
const deviations = leftEdges.map((x, i) => ({
index: i,
value: x,
deviation: Math.abs(x - reference)
}));
// Report
const maxDeviation = Math.max(...deviations.map(d => d.deviation));
console.log(`Reference left edge: ${reference}px`);
deviations.forEach(d => {
console.log(`Element ${d.index}: ${d.value}px (deviation: ${d.deviation}px)`);
});
console.log(`Max deviation: ${maxDeviation}px`);
console.log(`ALIGNED: ${maxDeviation === 0 ? 'YES' : 'NO'}`);
Right Edge Alignment
// Measure
const elements = await page.locator('.item').all();
const rightEdges = [];
for (const el of elements) {
const box = await el.boundingBox();
rightEdges.push(box.x + box.width);
}
// Calculate deviations from first element
const reference = rightEdges[0];
const deviations = rightEdges.map((r, i) => ({
index: i,
value: r,
deviation: Math.abs(r - reference)
}));
// Report
const maxDeviation = Math.max(...deviations.map(d => d.deviation));
console.log(`ALIGNED: ${maxDeviation === 0 ? 'YES' : 'NO'}`);
Top Edge Alignment
// Measure
const elements = await page.locator('.item').all();
const topEdges = [];
for (const el of elements) {
const box = await el.boundingBox();
topEdges.push(box.y);
}
// Calculate deviations from first element
const reference = topEdges[0];
const maxDeviation = Math.max(...topEdges.map(y => Math.abs(y - reference)));
// Report
console.log(`ALIGNED: ${maxDeviation === 0 ? 'YES' : 'NO'}`);
console.log(`Max deviation: ${maxDeviation}px`);
Equal Spacing Between Elements
// Measure
const elements = await page.locator('.item').all();
const boxes = [];
for (const el of elements) {
boxes.push(await el.boundingBox());
}
// Calculate gaps between consecutive elements
const gaps = [];
for (let i = 1; i < boxes.length; i++) {
const gap = boxes[i].x - (boxes[i-1].x + boxes[i-1].width);
gaps.push(gap);
}
// Calculate deviations from first gap
const referenceGap = gaps[0];
const deviations = gaps.map((g, i) => ({
index: i,
value: g,
deviation: Math.abs(g - referenceGap)
}));
// Report
const maxDeviation = Math.max(...deviations.map(d => d.deviation));
console.log(`Reference gap: ${referenceGap}px`);
deviations.forEach(d => {
console.log(`Gap ${d.index}: ${d.value}px (deviation: ${d.deviation}px)`);
});
console.log(`ALIGNED: ${maxDeviation === 0 ? 'YES' : 'NO'}`);
Common Pitfalls
CSS: margin: auto needs flex/grid parent
/* WRONG - margin auto alone does nothing in block layout */
.child {
margin: 0 auto;
}
/* RIGHT - parent must be flex or block with defined width */
.parent {
display: flex;
justify-content: center;
}
/* OR */
.child {
width: 200px; /* must have explicit width */
margin: 0 auto;
}
SwiftUI: .center needs frame larger than content
// WRONG - no frame means content hugs, nothing to center within
Text("Hello")
.frame(alignment: .center)
// RIGHT - explicit frame provides space to center within
Text("Hello")
.frame(maxWidth: .infinity, alignment: .center)
Transforms affect visual but not bounding box
getBoundingClientRect() returns the ORIGINAL position before CSS transforms. If you use transform: translateX() or similar, the visual position differs from the measured position.
// Element visually at 100px but boundingBox shows 0px due to transform
// Solution: account for transforms or use offsetLeft/getBoundingClientRect
Asymmetric content (icon in button)
A button with an icon on one side may APPEAR off-center even when the button IS centered, because the visual weight is asymmetric.
[ Icon Text ] <-- Button is centered but looks left-heavy
Solution: Either accept true center or adjust with padding to achieve
optical center (but document this explicitly).
Anti-Patterns (FORBIDDEN Language)
The following phrases are REJECTED in alignment verification:
| Phrase | Why Rejected |
|---|---|
| "within tolerance" | There is no tolerance. 0px or report deviation. |
| "close enough" | Not a measurement. What is the actual deviation? |
| "approximately aligned" | Approximate is not aligned. Give the number. |
| "looks aligned" | Visual assertion without ALIGNMENT_CHECK block. |
| "alignment seems fine" | "Seems" is not measurement. Prove it. |
| "roughly centered" | "Roughly" is not a pixel value. |
How to Fix
WRONG:
"The chips look aligned to me."
RIGHT:
ALIGNMENT_CHECK:
- Task: Verify horizontal alignment of chip row
- Type: top_edge
- Elements measured:
- chip[0]: y=142px
- chip[1]: y=142px
- chip[2]: y=142px
- chip[3]: y=144px
- ALIGNED: NO
- Max deviation: 2px
- Deviations: chip[3] is 2px below reference
Complete Verification Example
Task: "Center the modal horizontally in the viewport"
// Step 1: Identify
// - Target: .modal
// - Reference: viewport
// - Type: horizontal_center
// Step 2: Measure
const viewport = await page.viewportSize();
const modal = await page.locator('.modal').boundingBox();
// Step 3: Calculate
const viewportCenterX = viewport.width / 2;
const modalCenterX = modal.x + (modal.width / 2);
const deviation = Math.abs(viewportCenterX - modalCenterX);
// Step 4: Output
console.log(`
ALIGNMENT_CHECK:
- Task: Center modal horizontally in viewport
- Type: horizontal_center
- Elements measured:
- viewport center: ${viewportCenterX}px
- modal center: ${modalCenterX}px
- ALIGNED: ${deviation === 0 ? 'YES' : 'NO'}
- Max deviation: ${deviation}px
`);
Integration with Other Skills
- debugging-first: Use alignment verification AFTER confirming elements render
- design-qa-skill: Alignment checks are one component of full design QA
- lovable-pitfalls: Avoid premature "looks good" claims by measuring
When to Apply This Skill
ALWAYS apply when:
- User says "center this"
- User says "align these"
- User says "make them line up"
- Reviewing spacing consistency
- Verifying layout implementation
SKIP when:
- No alignment requirements mentioned
- Working on non-visual code (APIs, logic)
- User explicitly says "don't worry about exact alignment"
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
web-interface-guidelines
Web UI quality rules: interactions, forms, loading, animations, layout, content, performance, accessibility, design. Apply to all web UI work. Adapted from Vercel Design Guidelines.
react-performance
React/Next.js performance patterns with wrong/right code examples. Apply when building or reviewing React components. Adapted from Vercel React Best Practices by @shuding.
stripe-integration
Payment integration patterns for Stripe. Covers checkout sessions, subscriptions, webhooks, idempotency, and the sharp edges that cause real-money bugs. Backend-agnostic with examples for Next.js App Router and Django REST Framework.
testing-strategy
Testing strategies and best practices for unit, integration, and end-to-end tests. Use when setting up test infrastructure, writing test cases, or deciding what to test. Covers test pyramid, mocking strategies, and coverage guidelines.
frontend-aesthetics
Global frontend aesthetics skill that helps Claude avoid generic "AI slop" UI and make bold, intentional visual decisions while still honoring each project's design-dna, tokens, and architecture.
pg-style-editor
Edit writing to adopt Paul Graham's exceptionally clear style for research and long-form content - concrete language, varied sentence rhythm, accessible formality, specific evidence. Use when user wants to rewrite content in PG's style or asks to "make this clearer" or "simplify research writing."
Didn't find tool you were looking for?