The header now carries a "Shop" dropdown that fetches the collection list
the first time it's opened and links each entry to its collection page.
Fetching is deferred so the request only happens on open: useCollections
loads on mount, which would put a collections query on every page. The new
useCollectionsOnDemand holds off until load() runs, keeps the result for
later opens, and clears its guard on failure so a retry can go through.
Rendered in the desktop nav as a floating panel and in the mobile menu as
an inline section, following the hand-rolled pattern in account-menu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1vsTA4MX6qFd7nqSAKtdV
- /api/chat streams via AI SDK v7 through OpenRouter (OPENROUTER_API_KEY),
with a store-specific system prompt and five read-only tools:
searchCatalogue, getProductDetails, listCollections,
getCollectionProducts, browseProducts
- Sidebar assistant on the right that opens from a launcher and expands,
built on ai-elements (conversation, message, prompt-input, tool) with
shimmer on in-flight tool calls
- Extract services/shopify/catalog.ts so the Storefront fetchers have no
React imports and can run in a Route Handler; the client hooks now
re-export from it
- ai-elements pulled in the canonical shadcn primitives, replacing the
hand-rolled command/dialog/button variants; search dialog moved to the
cmdk-based Command and CommandDialog forwards shouldFilter
- Pin shiki to ^3.19.0 to match streamdown and drop the duplicate copy
- Add .env.example documenting the required env vars
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jWbNNJLksC1QG8z8845FX
- Collections: filters and sort via the Storefront API — the products
connection now takes `filters`/`after` and returns its facets, with
cursor-based load more on the collection page
- Extract ProductFilters (renamed from SearchFilters) and a shared
ProductToolbar so search and collections use the same chrome
- PDP: mark option values with no in-stock variant using a diagonal
strike, computed against the other selected options
- PDP: pointer drag-scrolling for the mobile image carousel, since a
scroll container doesn't drag with a mouse
- Header/cart: circular icon buttons, tighter spacing, and icon sizes
set by class (Button's base CSS clamps un-classed svgs to size-4)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jWbNNJLksC1QG8z8845FX