UX strategy — mobile-first, Apple-grade¶
This page is the guide for every visual + interaction decision going forward. Not a launch checklist — a standing reference when you're about to add a button, a page, a modal.
Principles¶
- Thumb-first. Every interactive element a customer needs in under 3 steps must be reachable by the thumb of a one-handed grip.
- Every pixel justifies itself. If removing something doesn't hurt the flow, remove it.
- Server price is truth. The box builder's canonical price comes from
POST /fruitplug/v1/box/price. Client-side state is a preview. - Silent routes. Install-prompt, upsells, banners never appear on
/p/*,/cart,/checkout,/build-your-box/*,/account— the buying path is sacred. - Real content over stock. Use Instagram reels and real fruit photos. No generic food stock.
Palette (sampled from public/brand/logo.png)¶
| Token | Hex | Use |
|---|---|---|
--fp-magenta |
#fc1c80 |
Primary CTA, price, active tab, primary icon tint |
--fp-magenta-600 |
#e5006a |
Hover/pressed state for magenta |
--fp-magenta-400 |
#ff4da0 |
Lighter accents, focus rings |
--fp-magenta-900 |
#b9165c |
Shadow / depth inside the glyph |
--fp-leaf |
#03a143 |
"Fresh-picked", "In season", seasonal calendar hits |
--fp-leaf-400 |
#1fb85a |
Hover on green accents |
--fp-sticker |
#faaf3f |
Warmth — next-day badges, ripe-indicator, notifications |
--fp-pith |
#f5f5f0 |
Fruit-flesh off-white — text on colored fills |
--fp-white |
#ffffff |
Primary foreground on black |
--fp-black |
#000000 |
Canvas |
Rule of thirds: magenta is dominant, leaf is secondary accent, sticker is a rare highlight (under 5% of page surface).
Typography¶
- Display — Grit (licensed, drop
public/fonts/grit.woff2) → Caveat Brush (Google Fonts fallback) → system cursive..fp-displayon every hero, section heading, stat value. - Body — Montserrat. 16px base, 1.5 line-height. No overrides without reason.
Surfaces¶
Glass Header — .fp-glass¶
Macro/Vision Pro glass: backdrop-filter: blur(24px) saturate(180%) plus a gradient background that deepens as the user scrolls (CSS scroll-timeline, with graceful fallback). Two hairline insets: a bright 1px top highlight (light from above) and a 1px bottom divider. Passes the "premium glass" test from 2024 Apple design language.
Glass Tab Bar — .fp-glass-bottom¶
Mirror of the Header, inverted. Used on the fixed mobile bottom tab bar. 10px + env(safe-area-inset-bottom) padding so it clears the iOS home indicator.
Cards¶
rounded-2xl border border-border/60 bg-white/[0.02]. Never shadow-heavy. Hover adds border-primary/40 — no scale transform on primary lists (cheap, creates motion sickness).
Layout¶
- Header height: 64px +
env(safe-area-inset-top)+ 10px extra top clearance for iOS status bar. - Tab bar height: 64px + 5px +
env(safe-area-inset-bottom). - Body bottom padding:
calc(35px + env(safe-area-inset-bottom))on mobile only. Intentionally leaves the last ~30px of content "behind" the frosted tab bar so the glass reads as glass, iOS-Safari-style. - Max width:
max-w-6xl(72rem) for content.max-w-mdfor forms. - Horizontal padding:
px-4 sm:px-6. That's the whole rule.
Interaction¶
- Tap targets: 40×40px minimum, 44×44px for primary actions. Bottom-tab items are 20% of viewport width each on a 5-tab grid.
- Viewport: zoom locked (
maximumScale: 1, userScalable: false, viewportFit: "cover") so form inputs don't trigger iOS auto-zoom and the native-app feel is preserved. - Motion: 300ms ease-out for drawers, 200ms for state changes, 150ms for hover. Never longer.
- Haptics (future): trigger
navigator.vibrate(10)on add-to-cart and box-composition changes.
Navigation¶
Mobile (<md)¶
- Top — glass Header with logo, account icon, cart pill, hamburger (opens drawer).
- Bottom — 5-tab glass bar: Home · Shop · Build · Cart · Account. Active tab gets a 2px magenta line + magenta tint.
- Drawer — slides in from the right on hamburger. Secondary links (Subscribe, Recipes, About, FAQ). Backdrop blur + click-outside to close + Escape to close.
Desktop (≥md)¶
- Classic horizontal nav inside the Header. No tab bar.
Install prompt etiquette¶
- Appears after 25 seconds of engagement OR 3+ page views (whichever first).
- Never on:
/p/*,/cart,/checkout,/build-your-box/*,/account. - Positioned
bottom-[calc(64px+env(safe-area-inset-bottom))]so it sits ABOVE the tab bar, never hides the footer or tabs. - Dismissed: 14-day silence in localStorage.
Content hierarchy¶
Home¶
- Glass Header
- Hero — big display title, tagline, two buttons (Shop Boxes primary, Build Your Own secondary)
- TrustStrip — 3 icons in the three brand colors (green = fresh, amber = next-day, magenta = reviews)
- Social proof — stats band (clickable IG + TikTok stats link out)
- Watch the plug — featured reels grid (3 videos, IntersectionObserver-lazy, click-to-play)
- What's coming — 4 feature cards
- Footer
PDP¶
Above-the-fold on mobile must contain: gallery, name, price, Add-to-Cart. Anything else is below the fold. Description lives in a <details> only if it's >200 words; otherwise expanded inline.
Box builder¶
Sticky bottom summary on mobile. Server-validated price always displayed. Credits bar turns red on over-budget. "Save this box" redirects to /login?next=... on 401 — never silently fails.
/account¶
Hi-{firstname} greeting, logout pill, three QuickLinks (Shop again / Build / Subscribe), then the last 10 orders as cards.
SEO¶
Canonical host is https://fruitplug.co.uk regardless of where the bytes are served from. SEO_INDEXABLE=1 on production only — dev stays Disallow. Every commerce surface emits JSON-LD (Product, Organization, WebSite, BreadcrumbList, CollectionPage). See SEO & structured data.
What's explicitly NOT shipped¶
- Page transitions / route animations. Deferred until perf budget confirmed.
- Haptic feedback. Phase 2.
- Skeleton loading states. Phase 2.
- Review schema with individual Reviews. Phase 2.
- Preparation Guide schema (FAQ/HowTo). Phase 2.
- Offline-first catalog caching. Phase 2, behind the service worker.
Review cadence¶
Re-audit every 4 weeks on iPhone 14 viewport (390×844) and Pixel 7 (412×915). Capture: home, shop, PDP, cart, box builder, /account, /login. File findings against this doc — if a finding contradicts a principle here, either change the principle or fix the code.