responsive · git:20260416.cfee010 · 2026-04-16 · sha256 69792792e9f9a964
responsive git:20260416.cfee010A
Immutable. This exact content is served forever at /api/v1/blob/69792792e9f9a964.
---
name: responsive
description: Test a web app at mobile, tablet, and desktop breakpoints. Screenshots each size, flags overflow, small touch targets, tiny text, and viewport issues. Use before shipping or after layout changes.
user_invocable: true
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, mcp__Claude_Preview__preview_start, mcp__Claude_Preview__preview_list, mcp__Claude_Preview__preview_screenshot, mcp__Claude_Preview__preview_resize, mcp__Claude_Preview__preview_inspect, mcp__Claude_Preview__preview_eval
argument-hint: [url-or-project-path]
---
# Responsive Tester
Test a web app at three breakpoints and report issues.
**Argument**: `$ARGUMENTS` is either a URL (e.g., `http://localhost:3000`) or a project path to start a dev server for. If not provided, ask.
## Breakpoints
Test at these three sizes:
- **Mobile**: 375 × 812 (iPhone baseline)
- **Tablet**: 768 × 1024 (iPad portrait)
- **Desktop**: 1280 × 800 (standard laptop)
## Process
### 1. Get a running preview
If given a URL, use it directly with `preview_start` (or confirm one is already running with `preview_list`).
If given a project path:
- Check for `.claude/launch.json` — if present, use `preview_start` with the configured name
- If not, create `.claude/launch.json` first (see preview_start docs) based on `package.json` scripts
- Start the server and get a URL
### 2. Pre-flight checks (static analysis)
Before opening the browser, grep for common issues:
```bash
# Missing viewport meta
grep -L "viewport" src/app/layout.* public/index.html 2>/dev/null
# Fixed pixel widths that break on mobile
grep -rn "width: [0-9]\{3,4\}px" --include="*.css" --include="*.tsx" --include="*.jsx"
# Absolute positioning without responsive alternatives
grep -rn "position: absolute" src/ --include="*.css" --include="*.tsx"
```
Note anything suspicious for the browser phase.
### 3. Test each breakpoint
For each of mobile / tablet / desktop:
**a. Resize the viewport:**
```
preview_resize with preset "mobile" (or "tablet", "desktop")
```
**b. Take a screenshot:**
```
preview_screenshot to capture the rendered page
```
**c. Check for horizontal overflow:**
```javascript
// Via preview_eval:
({
docWidth: document.documentElement.scrollWidth,
viewWidth: window.innerWidth,
overflow: document.documentElement.scrollWidth > window.innerWidth,
overflowingElements: Array.from(document.querySelectorAll('*'))
.filter(el => el.scrollWidth > window.innerWidth)
.slice(0, 5)
.map(el => ({
tag: el.tagName.toLowerCase(),
class: el.className,
width: el.scrollWidth
}))
})
```
**d. Check touch target sizes (mobile only):**
```javascript
// Via preview_eval:
Array.from(document.querySelectorAll('button, a, input, [role="button"]'))
.map(el => {
const r = el.getBoundingClientRect();
return { tag: el.tagName, text: el.textContent?.slice(0, 30), w: r.width, h: r.height };
})
.filter(el => (el.w > 0 && el.w < 44) || (el.h > 0 && el.h < 44))
.slice(0, 10)
```
**e. Check for tiny text:**
```javascript
// Via preview_eval:
Array.from(document.querySelectorAll('p, span, li, a, button, input'))
.map(el => {
const size = parseFloat(getComputedStyle(el).fontSize);
return { tag: el.tagName, text: el.textContent?.slice(0, 40), size };
})
.filter(el => el.size > 0 && el.size < 14)
.slice(0, 10)
```
### 4. Additional checks
**Viewport meta tag** (once, any breakpoint):
```javascript
document.querySelector('meta[name="viewport"]')?.content || 'MISSING'
```
Expected: `width=device-width, initial-scale=1` (or similar).
**Image sizing** (mobile):
```javascript
Array.from(document.querySelectorAll('img'))
.map(img => ({
src: img.src.slice(0, 60),
natural: img.naturalWidth,
rendered: img.width,
oversized: img.naturalWidth > img.width * 2
}))
.filter(img => img.oversized)
.slice(0, 5)
```
### 5. Report
Format as a scored report:
```markdown
## Responsive Test: [URL]
### Summary
- Mobile (375px): [Pass ✓ / Issues ⚠ / Broken ✗]
- Tablet (768px): [Pass ✓ / Issues ⚠ / Broken ✗]
- Desktop (1280px): [Pass ✓ / Issues ⚠ / Broken ✗]
### Viewport meta
✓ Correct: `width=device-width, initial-scale=1`
### Mobile (375px)
**Horizontal overflow**: ✗ Yes — page is 412px wide
- Element: `<div class="hero-grid">` renders at 420px
**Touch targets**: ⚠ 3 elements under 44px
- `<button>Subscribe</button>` — 32×32
- `<a>Read more</a>` — 28×20
- `<input type="email">` — 40×36
**Text sizes**: ⚠ 2 elements under 14px
- Footer copyright: 12px
- Badge labels: 11px
**Images**: ⚠ 1 oversized
- hero.jpg — natural 2400w, rendered 375w (load 6x data)
### Tablet (768px)
✓ No overflow
✓ All touch targets adequate
✓ Text sizes readable
### Desktop (1280px)
✓ Layout looks correct
⚠ Hero text-wrap may orphan — consider `text-wrap: balance`
### Priority fixes
1. **hero-grid overflow on mobile** — `src/components/Hero.tsx:42` — set `max-width: 100%` and use fluid sizing
2. **Subscribe button too small** — `src/components/CTA.tsx:18` — increase padding to 12px vertical minimum
3. **Oversized hero image** — use `next/image` or add responsive `srcset`
```
### 6. Offer to fix
After the report, ask: "Want me to fix any of these?"
## Rules
- Always test all three breakpoints — never skip one
- Take screenshots at each breakpoint (for visual verification)
- Don't flag intentional choices (e.g., sticky footer, fixed navbar)
- Keep reports concise — max 5 items per issue type
- File paths + line numbers for every actionable item
- Touch target threshold is 44×44px (Apple HIG standard)
- Text size threshold is 14px for body, can be 12px for labels/badges
- If server isn't running and no launch.json, ask before creating one