The technical-verification layer of the thumb-first suite. Where thumb-first-design decides what the mobile design should be (platform-agnostic judgment), this skill verifies that the implementation holds up on the actual device — objective defects with file:line and fixes, rated by severity.
Run /thumb-first for a combined design + platform review; use this skill directly for technical checks only.
Step 0 · Detect the Target (do this first)
The relevant defects are completely different for a web/PWA vs. a native app. Determine the target before doing anything else.
Sniff the repo:
- Web / PWA →
next.config.*,vite.config.*, anindex.html, a web appmanifest.json/manifest.webmanifest, a service worker, Tailwind/CSS. This is this skill's home turf — proceed to the principles and routing below. - Native →
react-native/expoinpackage.json,app.json/app.config.*(Expo), anios/+android/pair,*.xcodeproj/Package.swift/*.swift(SwiftUI/UIKit), orpubspec.yaml(Flutter). - Ambiguous or both (e.g. an Expo app with a web target) → ask which target to audit.
If the target is NATIVE — do not fake a web audit. This skill's checks (Safari quirks, viewport units, service workers, web manifest) do not apply. Instead:
- Check for an installed native skill to hand off to — scan available skills /
~/.claude/skills/for ones describing React Native, Expo, SwiftUI, native iOS/Android, or Flutter (e.g.react-native-design,building-native-ui,vercel-react-native-skills). - If one exists → hand off. Name it explicitly: "For the native technical pass, use
<skill>— it covers native performance, lists, and platform APIs." Note thatthumb-first-designstill covers the design judgment for native, since that layer is platform-agnostic. - If none exists → say so plainly. Do not overreach:
thumb-first-platform covers mobile design judgment (via
thumb-first-design) and web/PWA technical defects. It is not set up to run native-platform (React Native / SwiftUI / Flutter) performance or technical audits. For that, install a native-specific skill, or use platform-native tooling — Xcode Instruments, Android Studio Profiler, Flipper, or the React Native performance monitor.
The design layer applies to every target. This technical layer is web/PWA-deep and native-aware-but-delegating. Be honest about that boundary.
Mobile Web & PWA — Core Principles
1. iOS Safari is the problem child
Most quirks and limitations live here. Always test on real iOS devices — simulators miss critical behaviors. Key pain points:
- PWAs require Safari for installation (Add to Home Screen)
- Push notifications only work when installed to home screen (iOS 16.4+)
- 7-day storage cap for non-installed web apps; 50MB cache limit; no background sync
- WebKit-only rendering (even Chrome on iOS uses WebKit)
2. Viewport units matter
Never use 100vh for full-height layouts on mobile — browser chrome causes overflow.
.hero { height: 100vh; height: 100svh; } /* svh for static elements (90% of cases) */
.menu { height: 100dvh; } /* dvh only for elements that should resize */
dvh causes layout shifts — use sparingly.
3. Safe-area insets are required
Notches, Dynamic Islands, and home indicators are everywhere.
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
.header { padding-top: max(1rem, env(safe-area-inset-top)); }
.bottom-nav { padding-bottom: max(1rem, env(safe-area-inset-bottom)); }
4. Touch targets ≥ 44px
Apple HIG requires 44×44pt minimum; Google recommends 48×48dp. Never go smaller for tap targets.
5. Test on real devices
Chrome DevTools emulation lies — it doesn't simulate address-bar behavior, safe-area insets, touch-delay nuances, iOS Safari CSS bugs, or real mobile-hardware performance. Use real devices or BrowserStack/Sauce Labs.
Intake & Routing
What do you want to do?
- Audit an existing mobile app/PWA for issues
- Fix iOS Safari–specific problems
- Set up PWA (manifest, service worker, icons)
- Optimize mobile performance (Core Web Vitals)
- Debug touch/gesture issues
- Set up push notifications
- Test mobile compatibility
Wait for the response, then read the matching workflow and follow it.
| Response | Workflow / Reference |
|---|---|
| 1 · "audit", "check", "review", "issues" | workflows/audit-mobile-pwa.md |
| 2 · "ios", "safari", "iphone", "apple" | workflows/fix-ios-issues.md |
| 3 · "pwa", "manifest", "service worker", "install" | workflows/setup-pwa.md |
| 4 · "performance", "slow", "vitals", "lcp", "cls" | workflows/optimize-performance.md |
| 5 · "touch", "gesture", "tap", "swipe", "scroll" | read references/touch-interactions.md, then fix |
| 6 · "push", "notification", "vapid" | read references/push-notifications.md, then implement |
| 7 · "test", "debug", "emulate" | workflows/test-mobile.md |
Intent-based routing (specific problem described):
- "100vh not working", "viewport", "height issue", "notch", "safe area", "dynamic island" →
references/viewport-layout.md - "images too big", "slow images" →
references/image-optimization.md - "rubber band", "bounce scroll" →
references/ios-safari-quirks.md
When run via
/thumb-first: the umbrella invokes the audit path only (workflows/audit-mobile-pwa.md) and merges its defects into the combined report. The setup/push/perf workflows are build tasks — available on direct invocation, but outside the one-stop review.
Verification Loop — After Every Change
- Build succeeds?
pnpm build - Lighthouse audit? Chrome DevTools → Lighthouse → Mobile + PWA
- Real iOS device? Safari Web Inspector, or ngrok/localtunnel
- Safe areas handled? Portrait and landscape, with and without notch
Report findings as: Build: ✓ · Lighthouse PWA: X/100 · iOS Safari: [specific issues].
Reference Index
All in references/:
| File | Contents |
|---|---|
| ios-safari-quirks.md | iOS Safari bugs, CSS workarounds, limitations |
| android-pwa.md | Android Chrome PWA behavior, WebAPK |
| viewport-layout.md | 100vh issues, dvh/svh/lvh, safe-area insets |
| pwa-manifest.md | manifest.json, icons, splash screens |
| service-workers.md | Caching strategies, offline support, Next.js integration |
| push-notifications.md | Web push, VAPID, iOS vs Android |
| touch-interactions.md | 300ms delay, touch-action, gestures |
| performance.md | Core Web Vitals (LCP/INP/CLS), mobile optimization |
| image-optimization.md | Next.js Image, responsive images, WebP/AVIF |
| responsive-patterns.md | Common mistakes, anti-patterns |
| testing-debugging.md | Lighthouse, testing tools, iOS debugging |
Workflow Index
| File | Purpose |
|---|---|
| audit-mobile-pwa.md | Comprehensive audit of a mobile app/PWA (the path /thumb-first calls) |
| fix-ios-issues.md | Fix iOS Safari–specific problems |
| setup-pwa.md | Configure a PWA from scratch |
| optimize-performance.md | Improve Core Web Vitals |
| test-mobile.md | Testing procedures |
Common Issues & Quick Fixes
/* 100vh overflow on mobile */ height: 100svh; /* or min-height */
/* 300ms tap delay */ button, a { touch-action: manipulation; }
/* rubber-band scroll */ html { overscroll-behavior: none; }
<!-- safe area not working --> <meta name="viewport" content="..., viewport-fit=cover">
<!-- iOS status bar style --> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
PWA not installable: valid manifest.json · HTTPS · service worker registered · icons include 192×192 and 512×512.