Appearance
/plans redesign — design brief
For the /plans redesign session in ~/Developer/ask-florence-plans-redesign/. Reads alongside docs/design-system.md (canonical) and the editorial home (authoritative reference).
1. What /plans is and why it matters
/plans is the marketplace browse page. After a user submits the home calculator, a hero plan + 2 compact rows render inside the takeover viewport, and the dominant CTA "Check doctor & drug coverage" routes to /plans?...household-context.
This is the second-most-visited surface on the site after the home conversion moment. Investor demos go here. Live since v0.18.0 (April 23). Right now it works for data accuracy (audited 100% across all pricing tiers) but the experience lags the editorial register that shipped with the v0.29.0 home swap.
Job to be done:
- Show every plan available to the household, with subsidy applied.
- Let the user filter by what matters to them (metal, carrier, plan type, MOOP, deductible, HSA, in the future: doctor coverage + drug coverage).
- Surface the right plan in a quiet, confident way — not the Healthcare.gov firehose of confusion.
2. Audit: what /plans has today
src/components/PlansMarketplace.tsx (~600 lines).
Currently in place
- Server-side fetch via
fetchPlansForHousehold()(same hook the calculator uses; pricing math is shared, audited). - Sticky context bar at
top-[72px]showing county / household / income / APTC. - "Edit" link back to
/#calculator. - Filter state: metalLevels, planTypes, issuers, hsaEligible, premiumMin/Max, deductibleMin/Max.
- Sort state: premium_asc / deductible_asc / moop_asc / rating_desc.
- Mobile filter trigger via
mobileFilterOpen(sheet implementation details unverified). - Always-on
<PlansWipModal />modal (v0.28.0) flagging the redesign is in progress. PlanCardprimitive (default variant) for each plan in the list.- Default Silver filter when CSR applies.
- Client-side filtering for metal/premium/deductible (server returns all plans for facet computation).
Gaps and pain points
| Gap | Impact |
|---|---|
| Visual register is legacy SaaS (florence-* tokens) | Doesn't match the editorial register on the home; jarring transition |
PlanCard default variant is dense + visually busy | Hard to scan a list of 50+ plans |
| No comparison feature | User can't compare 2-3 plans side by side |
| No "save / favorite" affordance | User loses plans across sessions |
| No drug formulary search (Phase C, data-ready) | Conversion-blocking question goes unanswered |
| No provider directory search (Phase D, data-ready) | Same |
| No persistence of filter state | Refresh = lost filters |
| Mobile filter pattern is unverified / not editorial | Mobile probably worst surface |
| No empty state for "no plans match filters" | Silent failure |
| No loading skeleton (just blank) | Feels broken on slow networks |
| No URL-encoded filters | Can't share a filter view |
| Issuer filter is a list of all issuers; long lists are noisy | Hard to scan |
| Premium/deductible sliders not implemented (only number ranges in state) | Filter UI not built |
| Sort dropdown unverified | Probably a native select; should be a styled pill row on mobile |
3. Competitive UX: what the existing marketplaces do badly
Healthcare.gov
Direct experience with the federal flow tells you everything. Concrete issues users hit:
- Burying subsidies — the marketplace shows the sticker price first, then asks if you want to see "discounts." Users who don't click that toggle see $960/mo plans they qualify for at $7. AskFlorence exists because of this.
- Bronze-first sort — the default sort surfaces lowest premium (Bronze) which has the worst deductible. Users without health literacy take the cheap-looking option and end up with $18,300 deductibles.
- Filter chaos — the sidebar has 15+ collapsed filter groups. No hierarchy. Categories like "Plan benefits" hide critical things like HSA-eligible.
- No plan comparison — to compare two plans you open a separate page each in new tabs. There's a "compare" mode but it's hidden behind a checkbox and a button.
- Drug + provider lookups happen LAST — only after you click into a plan detail page. By then the user has already mentally narrowed to 1-2 plans and is stressed.
- Mobile is broken — the filter sidebar collapses behind a collapsing accordion that's hard to tap. Plans render full-width with the same dense info → endless scrolling.
- Plan names are noise — "Value Expanded Bronze 6900" tells the user nothing. Users don't know what these mean.
- Star ratings appear without context — what does 3 stars vs 4 stars mean for THIS user?
Covered California (CoveredCA)
The state-based marketplace for CA. Built newer than Healthcare.gov. Better in some places, worse in others:
- Better: simpler filter sidebar (~5 categories), savings highlighted upfront, mobile filter is a bottom-drawer (right pattern).
- Worse: plan card design is busier than Healthcare.gov (4-5 badges per card, color blocks for metal that compete with brand).
- Same: no built-in plan comparison, drug lookup is in plan detail page only, no save/favorite.
What every marketplace gets wrong
- Treating the user like a power-user. They show 80 plans, 15 filters, 6 sort options, and assume the user can figure it out.
- Surfacing legal noise instead of the price. Plans show "Premium: $7 / Deductible: $0 / MOOP: $6,000" all at the same visual weight. The premium is what matters first.
- No "best for me"-style hint. No system says "this is probably the right plan for you" with a calm explanation.
- Dense scannability. Cards are visually loud — the user has to work to compare them.
- No mobile-first design. Mobile is an afterthought; usually the desktop layout shrunk down.
What modern e-commerce / hotel / travel sites do well (transfer to /plans)
- Booking.com / Airbnb pattern: results list with sort + filter bar above, sticky on scroll. Quick filters as chips ("Free WiFi", "Pool"). Save/favorite in a heart icon. Compare via a small drawer.
- Apple Card / Wealthfront pattern: editorial card list with generous whitespace, single CTA per card, the savings/value number is the hero of each card.
- Apple Music / Spotify pattern: sticky filter pill row at top, bottom-sheet on mobile for full filter set, results stream below.
- Best Buy compare drawer: floating bottom-sheet on mobile with selected items + a "Compare X items" CTA. Desktop: right-side drawer with selected plans persistent.
4. Design principles for our /plans
Apply these throughout:
- Default-Silver, no exceptions — when CSR applies (which it does for most users), the page opens filtered to Silver. Other metals are still selectable. Help users land on the right plan without making them ask.
- Subsidized price first, always — the big price on every card is the post-subsidy price. Sticker price is a strike-through secondary.
- The proof block lives at the top — show the user's savings summary above the plan list. They land on the page with a confidence anchor.
- One screen = one decision — don't try to be a power-user tool. Show 3-5 visible filters by default, "more filters" expands the rest. Never overwhelm.
- Compare is a first-class action — make it discoverable. Heart-style "save" + "Compare" mode that builds a drawer.
- Coverage is the sale — drug + provider lookups must be 1 click from the plan card, not buried in a detail page.
- Mobile is app-quality — bottom-sheet filters, sticky compare bar, swipe to save, hapticky. Not just "responsive web."
- Editorial register holds throughout — cream paper backgrounds, ink text, gold-italic accents on emotional moments, Outfit on prices. Even at 50+ cards, the page reads as one editorial spread.
5. Desktop design proposal
5.1 Page composition
┌──────────────────────────────────────────────────────────────┐
│ Sticky nav (existing) │
├──────────────────────────────────────────────────────────────┤
│ Sticky context bar │
│ Salt Lake County, UT · 2 ppl · $21K/yr · $1,031/mo APTC │
│ [Edit] │
├──────────────────────────────────────────────────────────────┤
│ │
│ Hero: savings anchor │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ EYEBROW: AskFlorence shows you │ │
│ │ │ │
│ │ 37 plans available in Salt Lake County. │ │
│ │ *Best Silver:* $7.78/mo · $0 deductible. │ │
│ │ Save up to $29,729/yr vs. Healthcare.gov. │ │
│ │ │ │
│ │ [See best Silver →] [Compare top 3 →] │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
├──────────────────────────────────────────────────────────────┤
│ │
│ Filter bar (sticky on scroll) │
│ Metal: [Silver*] [Bronze] [Gold] Sort: [Premium ↑] │
│ Carrier: [Select Health] [Cigna] [+] HSA: [On/Off] │
│ More filters... │
│ │
├─────────────────────┬────────────────────────────────────────┤
│ │ │
│ Sidebar filters │ Plan list (3-col grid? or 1-col?) │
│ (expanded) │ │
│ - Metal │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ - Carrier │ │ Plan A │ │ Plan B │ │ Plan C │ │
│ - Plan type │ │ $7.78 │ │ $32 │ │ $48 │ │
│ - HSA │ │ Silver │ │ Silver │ │ Silver │ │
│ - Deductible range │ │ [Save] │ │ [Save] │ │ [Save] │ │
│ - MOOP range │ └─────────┘ └─────────┘ └─────────┘ │
│ - Premium range │ │
│ - QRS rating │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ - Doctors covered │ │ Plan D │ │ Plan E │ │ Plan F │ │
│ - Rx covered │ │ ... │ │ ... │ │ ... │ │
│ (Phase C/D) │ └─────────┘ └─────────┘ └─────────┘ │
│ │ │
│ │ [Load more / pagination] │
│ │ │
└─────────────────────┴────────────────────────────────────────┘
Floating compare drawer (when 1+ plans saved):
┌──────────────────────────────────────────────────────────┐
│ 3 plans saved [Compare →] [×] │
└──────────────────────────────────────────────────────────┘Key decisions:
- Hero block at top with savings anchor (the "you're saving $29K" message) and 2 primary CTAs (best plan, compare top).
- Filter bar below hero, sticky on scroll — ALWAYS visible as user scrolls plan list. Acts as the global control surface.
- Sidebar is full filter set — left column on desktop (240-260 px wide). The filter bar above is a quick-access subset (metal, sort, carrier).
- Plan grid is 3 columns at ≥1240px viewport. 2 columns at 768-1239. The card density should be similar to Apple Card account cards (light, scannable).
- Save/heart action on every card. Plus a "Compare" toggle.
- Compare drawer floats at bottom-right when 1+ plan saved. Click "Compare" → opens full-screen comparison view with up to 4 plans side-by-side.
5.2 Hero block
This is the conversion confidence anchor. Inspired by the home's proof block but smaller:
html
<div class="af-l2-plans__hero">
<div class="eyebrow">
<rule />AskFlorence shows you
</div>
<h1>
37 plans available in Salt Lake County.<br>
<em class="italic-gold">Best Silver: $7.78/mo, $0 deductible.</em>
</h1>
<p class="sub">
Save up to <strong class="green">$29,729/yr</strong>
vs. Healthcare.gov for your household.
</p>
<div class="ctas">
<a class="primary">See best Silver →</a>
<a class="tertiary">Compare top 3</a>
</div>
</div>5.3 Plan card (marketplace variant)
NEW variant: variant="marketplace" on PlanCard.tsx. Or a purpose-built MarketplacePlanCard.tsx. Either way, editorial register, NOT the legacy SaaS PlanCard.
Layout:
┌────────────────────────────────────────┐
│ Select Health [♥ Save] │
│ Signature Benchmark Silver │
│ Silver · HMO · ★★★★☆ │
│ ───────────────────────────────────── │
│ $7.78 /mo │
│ was $1,051.30 Save 99% │
│ ───────────────────────────────────── │
│ Deductible $0 │
│ Max Out-of-Pocket $6,000 │
│ Primary care $5 │
│ ───────────────────────────────────── │
│ ⚕ Check doctors 💊 Check Rx │
│ ───────────────────────────────────── │
│ [See plan details →] │
└────────────────────────────────────────┘Key elements:
- Editorial register — paper bg, hairline border, 4px gold-deep left accent (the metal-tier strip).
- Save heart in top-right corner, always visible.
- Carrier + plan name at top, plan name in Playfair italic might be too much — keep Inter 600.
- Pills row — metal pill (4px radius), plan type (HMO/PPO), star rating.
- Big save-green premium with sticker strike + Save% pill.
- Stat list — Deductible / MOOP / Primary care copay (3 max, most-asked).
- Coverage check buttons (Phase C/D) — when integrated, two pills: "⚕ Check doctors" and "💊 Check Rx" each with their own search drawer. When the user has searched, replace with checkmarks ("⚕ 3 of 3 covered ✓ · 💊 2 of 2 covered ✓").
- Plan details CTA — text-link tertiary in gold-deep dashed underline.
5.4 Filter sidebar (desktop)
Persistent left column. Filters in priority order (most-used at top):
- Metal level (toggle pills, multi-select)
- Carrier (checkboxes with count)
- Plan type (HMO/PPO/EPO/POS — toggle pills)
- HSA-eligible (single switch)
- Premium range (slider, $/mo)
- Deductible range (slider)
- Max Out-of-Pocket range (slider)
- QRS rating (1-5 stars, dropdown or pill)
- (Phase C) Drug coverage — search input that adds pills per drug
- (Phase D) Doctor coverage — search input that adds pills per provider
Filter bar above the list is a quick-access subset:
- Metal pills (most-used)
- Sort dropdown
- HSA switch
- "More filters" → opens the full sidebar on tablets where the sidebar is hidden by default
5.5 Sort options
Pill row, not a dropdown. Sticky with the filter bar.
Options:
- Premium (low to high) — default
- Deductible (low to high)
- Max OOP (low to high)
- Star rating (high to low)
- (Phase C/D) Best doctor coverage / Best Rx coverage
5.6 Plan comparison
Compare drawer accumulates as user clicks "Save" on cards. When 2+ plans saved:
- Floating bottom-right drawer pill: "3 plans saved · Compare →"
- Click "Compare" → modal full-screen view with 2-4 plan cards in a vertical row, each row a different attribute (premium, deductible, MOOP, doctors covered, Rx covered, plan type, network, formulary).
- Highlight winning value per row in green.
- Permalink the comparison so user can share.
6. Mobile design proposal
Mobile is app-quality, not "responsive web." Treat it like a native iOS / Android marketplace browse experience.
6.1 Page composition (mobile)
┌─────────────────────────────┐
│ Nav (sticky 64 px) │
├─────────────────────────────┤
│ Context bar (sticky 56 px) │
│ SLC, UT · 2ppl · $21K · ⓘ │
├─────────────────────────────┤
│ │
│ Hero block (compact) │
│ 37 plans available. │
│ *Best: $7.78/mo* │
│ [See best →] │
│ │
├─────────────────────────────┤
│ Sticky filter pill row │
│ [≡ Filters (3)] [↓Premium ▼]│
│ │
├─────────────────────────────┤
│ │
│ Plan card (full width) │
│ ... │
│ │
├─────────────────────────────┤
│ │
│ Plan card (full width) │
│ ... │
│ │
├─────────────────────────────┤
│ │
│ ... endless scroll ... │
│ │
└─────────────────────────────┘
Sticky bottom: when 2+ plans saved
┌─────────────────────────────┐
│ ♥ 3 saved · Compare → │
└─────────────────────────────┘
Filter bottom-sheet (when [≡ Filters] tapped):
┌─────────────────────────────┐
│ [×] Filters │
│ │
│ Metal level │
│ [Silver] [Bronze] [Gold] │
│ │
│ Carrier │
│ ☐ Select Health (12) │
│ ☐ Cigna (8) │
│ ☐ ... │
│ │
│ Plan type, HSA, etc. │
│ │
├─────────────────────────────┤
│ [Clear all] [Apply (37)] │
└─────────────────────────────┘6.2 Mobile-specific patterns
- Bottom-sheet filters — full-height sheet that slides up. Not a side drawer (those feel desktop-y). Sheet has a drag-handle at top. "Apply" button shows count of plans matching ("Apply (37)").
- Sticky filter pill row below the context bar. Two pills visible: filter trigger + sort. Counts inside pills ("Filters (3)").
- Plan cards single column, full-width — same content as desktop, but vertical orientation. Coverage check buttons sit side-by-side in a row.
- Sticky compare bar at viewport bottom when plans are saved. Slim height (52 px), gold-tinted accent, bold ink text.
- Tap to save — heart icon top-right of card, 44×44 px hit area.
- Long-press to compare — alternative gesture; tap-and-hold on any plan card adds it to comparison drawer. Subtle haptic.
- Pull-to-refresh — swipe down at top to refetch (in case household context changed).
- Empty state — "No plans match your filters. [Reset] [Edit filters]"
- Loading skeleton — 5 plan-card-shaped skeletons with shimmer pulse from left to right at 12% gold alpha.
- Drug + Doctor lookup is its own bottom-sheet (Phase C/D). Tap "💊 Check Rx" pill on a plan card → bottom-sheet slides up with search field + autocomplete + "X of 5 covered" indicators.
6.3 Mobile interaction details
- Tap targets: ≥48 px (HIG primary).
- Bottom-sheet drag-to-dismiss + tap-overlay-to-dismiss.
- Animations: spring(stiffness: 300, damping: 30) for sheet transitions. Faster than the home's editorial pace because mobile marketplace is action-heavy.
- iOS Safari URL bar handling: use
100svh+safe-area-inset-bottomfor sticky CTAs. - Reduced motion: skip sheet animations entirely; show/hide instantly.
7. Component spec summary
The redesign needs these new components / variants. Add each to the design system as it ships:
| Component | Pattern |
|---|---|
MarketplaceHero | Compact savings-anchor hero |
MarketplacePlanCard (or PlanCard variant="marketplace") | Editorial plan card |
FilterBar (sticky on scroll) | Quick-filter row + sort pill |
FilterSidebar (desktop) | Full filter set in left column |
FilterBottomSheet (mobile) | Slide-up sheet |
SortPills | Sort options as a pill row |
MetalPills | Multi-select metal filter |
CarrierCheckboxList | Checkboxes with counts |
RangeSlider | Premium / deductible / MOOP ranges |
SaveButton (heart) | Top-right of plan card |
CompareDrawer (desktop, mobile) | Floating drawer with saved plans |
ComparisonModal | Full-screen 2-4 plan comparison |
EmptyState | "No plans match" + reset CTA |
PlanLoadingSkeleton | Shimmer placeholder card |
RxLookupSheet | Phase C drug-search drawer |
ProviderLookupSheet | Phase D doctor-search drawer |
Each component needs full state set (default / hover / focus / active / disabled / loading / error / empty) per docs/design-system.md §11.
8. Phasing recommendation
This is multi-session work. Ship in waves:
Wave 1: foundation (1-2 sessions)
- Editorial register on the page (paper bg, ink text, gold accents)
- Hero block with savings anchor
- New
MarketplacePlanCard(no save / compare yet) - Filter sidebar (desktop), filter bottom-sheet (mobile)
- Sort pills
- Empty state
- Loading skeleton
- Remove
<PlansWipModal />
Wave 2: comparison + save (1 session)
- Save heart on cards
- Compare drawer (desktop + mobile)
- Comparison modal (4 plans max)
- Permalink-able compare URL
Wave 3: filter URL state + polish (½ session)
- URL-encode filters (so user can bookmark / share filter views)
- Restore filter state from URL on load
- Filter count badges in pill row
- Sticky filter bar with scroll-shadow
Wave 4: integrate Phase C (drug formulary)
- Wait for Phase C ingest in
~/Developer/ask-florence-doctor-rx/ - Add Rx lookup pill + bottom-sheet on plan cards
- Filter "Plans that cover X drug" in sidebar
Wave 5: integrate Phase D (provider directory)
- Wait for Phase D ingest in same worktree
- Add Doctor lookup pill + bottom-sheet
- Filter "Plans that cover Dr. Y"
9. Constraints (every session)
Reminders specific to /plans work:
- Editorial register: cream paper bg
--af-cream, ink text--af-ink, italic-gold accents on emotional copy. - No round pills (4px radius everywhere).
- Touch targets ≥ 44 px (48 preferred).
- WCAG AA on every text-on-bg combination — see
docs/design-system.md §9. - All interactive elements ship full state set (default / hover / focus / active / disabled / loading / error / empty).
- No em dashes or en dashes in copy. Hyphens only.
- Don't touch
src/lib/owned-plans.ts,src/lib/fetch-plans.ts,src/lib/csr.ts,src/lib/types.ts,src/lib/hooks/use-calculator.ts, or any/api/*routes. Pricing/data layer is audit-locked. - Run
scripts/audit/calculator-baseline-diff.tsif anything you touch could affect pricing math (you shouldn't be touching that layer). - Update
docs/design-system.mdAND the visual/design-systempage with each new component as you ship it. Don't let the system lag the build.
10. Reference reading
docs/design-system.md— canonical design system/design-system(runnpm run dev) — visual reference/brand-guide— public-facing brand identity guidesrc/app/_home/— authoritative implementation registersrc/components/PlanCard.tsx— current plan-card primitive (legacy SaaS register; will need editorial-register variant)src/components/PlansMarketplace.tsx— current /plans implementation
External:
- Healthcare.gov plan results (study what they do badly)
- CoveredCA.com plan compare flow
- Booking.com hotel results (filter pattern + compare drawer)
- Apple Card account cards (editorial restraint)
- Apple Music genre browse on iOS (mobile bottom-sheet pattern)