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 skilldata-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.