skills/mobile-ux-optimizer/SKILL.md
Mobile-first UX optimization for touch interfaces, responsive layouts, and performance. Use for viewport handling, touch targets, gestures, mobile navigation. Activate on mobile, touch, responsive, dvh, viewport, safe area, hamburger menu. NOT for native app development (use React Native skills), desktop-only features, or general CSS (use Tailwind docs).
npx skillsauth add curiositech/windags-skills mobile-ux-optimizerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build touch-optimized, performant mobile experiences with proper viewport handling and responsive patterns.
IF screen width < 768px AND menu items > 4
→ Use bottom navigation (finger-reachable zone)
ELSE IF screen width < 768px AND menu items ≤ 4
→ Use fixed bottom tabs
ELSE IF complex gesture required (swipes, long-press)
→ Use slide-out drawer with hamburger trigger
ELSE
→ Use horizontal top navigation
IF content type = text-heavy (articles, forms)
→ Mobile-first: 320px base, lg:768px split
ELSE IF content type = media-heavy (galleries, videos)
→ Mobile-first: 375px base, md:640px grid
ELSE IF dashboard/data-dense
→ Start tablet: 768px base, xl:1280px full layout
IF fullscreen experience (modals, hero sections)
→ Use 100dvh with 100vh fallback
ELSE IF fixed bottom nav present
→ Use calc(100dvh - 64px) or h-screen-safe utility
ELSE IF content scrolls
→ Use min-h-screen (normal document flow)
IF interactive element (buttons, links, inputs)
→ Minimum 44x44px touch area
ELSE IF dense UI required (data tables, toolbars)
→ 40x40px with 4px spacing minimum
ELSE IF accessibility priority
→ 48x48px (WCAG AAA compliance)
Symptoms: Swipes/taps don't trigger, users tap multiple times Diagnosis: Touch area too small or event handlers missing Fix:
// Add minimum touch area and prevent double-tap zoom
<button className="min-h-[44px] min-w-[44px] touch-manipulation">
Symptoms: Content shifts when mobile browser chrome shows/hides Diagnosis: Using 100vh instead of dynamic viewport units Fix:
/* Replace 100vh with dynamic height */
.full-screen { height: 100dvh; }
Symptoms: Content hidden behind iPhone notch or home indicator Diagnosis: Missing safe area insets or viewport-fit=cover Fix:
<!-- Add viewport-fit=cover -->
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
.header { padding-top: env(safe-area-inset-top, 0); }
Symptoms: Page becomes unscrollable when modal/drawer opens Diagnosis: Applying overflow:hidden to body without restoration Fix:
useEffect(() => {
if (isOpen) document.body.style.overflow = 'hidden';
return () => { document.body.style.overflow = ''; };
}, [isOpen]);
Symptoms: Text unreadable on mobile, users pinch to zoom Diagnosis: Fixed pixel sizes instead of relative units Fix:
/* Replace px with rem for scalable text */
font-size: 1rem; /* 16px base, scales with user preference */
Scenario: Converting a desktop-first meeting list to mobile-optimized experience
// ❌ BEFORE: Desktop-first pain points
<div className="w-full max-w-4xl mx-auto px-4">
<nav className="flex space-x-8 mb-8">
<a href="/meetings">All Meetings</a>
<a href="/my-meetings">My Meetings</a>
<a href="/favorites">Favorites</a>
<a href="/search">Search</a>
</nav>
<div className="grid grid-cols-3 gap-6">
{meetings.map(m => <MeetingCard key={m.id} meeting={m} />)}
</div>
</div>
Expert catches: Touch targets in nav are too small, 3-column grid will be cramped on mobile, no safe area handling.
Novice misses: Would just add responsive classes without considering touch zones or navigation patterns.
Following navigation pattern logic: 4 menu items on mobile → Use bottom navigation
// ✅ AFTER: Mobile-optimized
<div className="pb-safe"> {/* Safe area handling */}
<div className="px-4 pb-16"> {/* Bottom nav clearance */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{meetings.map(m => <MeetingCard key={m.id} meeting={m} />)}
</div>
</div>
{/* Mobile: bottom nav, Desktop: hidden */}
<nav className="md:hidden fixed bottom-0 left-0 right-0 bg-white border-t pb-safe">
<div className="flex justify-around">
{navItems.map(({ href, icon: Icon, label }) => (
<Link key={href} href={href}
className="flex flex-col items-center py-2 px-3 min-h-[56px] min-w-[64px]">
<Icon className="w-6 h-6" />
<span className="text-xs mt-1">{label}</span>
</Link>
))}
</div>
</nav>
</div>
Using browser DevTools, verify each nav item is 56px+ tall with adequate finger spacing.
viewport-fit=cover for safe area support100dvh - no content cut off by browser chromept-safe/pb-safe applied to fixed elementspb-safe and doesn't block contentsizes attribute for proper mobile loadingDO NOT use this skill for:
react-native or swift-executor insteadpwa-expert skill for service workers and manifestframer-motion or animation-expert skillstailwind-expert or standard CSS documentationDelegate to other skills when:
mobile-debugging skillpwa-expert skillperformance-optimization skilla11y-expert skilltools
Building resilient distributed systems with circuit breakers, retries with full-jitter exponential backoff, retry budgets (per-request 3-attempt + per-client 10% ratio per Google SRE), deadline propagation, and the cascading-failure math (4 layers × 3 retries = 64x amplification). Grounded in Resilience4j, Microsoft Cloud Patterns, AWS Architecture Blog (Marc Brooker), and Google SRE Book.
testing
Designing HTTP cache headers that work correctly across browsers, CDNs, and shared proxies — `Cache-Control` directives per RFC 9111, `stale-while-revalidate` and `stale-if-error` per RFC 5861, the Vary header for varying responses, and surrogate keys for tag-based purging. Grounded in IETF RFCs and Cloudflare/Fastly docs.
development
Use when designing or fixing a Content Security Policy on a real site, choosing between nonce-based and hash-based CSP, adding strict-dynamic, debugging "Refused to execute inline script" errors, deploying CSP in report-only mode first, configuring report-to / report-uri, or auditing an existing policy for unsafe-inline / unsafe-eval / wildcards. Triggers: "CSP blocks legitimate inline script", strict-dynamic, nonce-{RANDOM}, sha256-{HASH}, object-src none, base-uri none, frame-ancestors, Trusted Types, X-Content-Security-Policy obsolete, report-only vs enforced. NOT for general HTTP security headers (HSTS, COOP/COEP), Trusted Types deep dive, CORS configuration, or building a WAF.
tools
Choosing and operating an HTTP API versioning strategy that doesn't break clients — Stripe's date-based pinned versions, the Deprecation/Sunset header pair (RFC 9745 + RFC 8594), URI vs header vs media-type approaches, and the version-transformer pattern. Grounded in Stripe's published architecture and IETF RFCs.