Feat/dynamic shopping#100
Merged
Merged
Conversation
UX - Recommendation cards are now clickable links to the retailer (target=_blank, rel=noopener noreferrer nofollow) with an external-link glyph on hover. - Drop AI results that lack a real product image at the source — no more placeholder cards rendering as broken-looking tiles. Browser-side onError swaps to a neutral fallback if a real URL 404s later. - Empty-state copy now distinguishes "no recs yet" from "your budget hides N items" and tells the user how to recover. Personalization - Wardrobe summary fed to the LLM now includes brand and tags per item, so recurring signals (e.g. a user with multiple Barça shirts, or all Nike pieces) can be reinforced. - analyze_gaps prompt explicitly tells the LLM to bake brand/theme into some queries and mix gap-filling vs. reinforcement. - Whitelist gains Vinted, Depop, Grailed, and eBay so secondhand jerseys / vintage finds can surface. CI hygiene (folds in prior local fixes) - Playwright shopping spec now mocks /api/recommendations via mockBackendDefaults (the store no longer reads from a local file). - pip-audit ignores MAL-2026-4750 — malware-tracker false positive against the legitimate fastapi package.
Dismissed cards no longer reappear on refresh or after the AI cache regenerates. The store tracks dismissed items by stable key (productUrl, falling back to name) — the LLM-assigned `id` rotates on every regeneration, so it can't be used for cross-run identity. `getFilteredRecommendations` filters out anything whose key is in `dismissedKeys`; a `clearDismissed()` action is available for a future "undo" affordance.
…ring sanitization' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This was referenced May 26, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to the initial US-8.3 wiring (already squash-merged on main as 8833464). This PR adds
the personalization + UX polish that came out of the parallel code reviews and post-deploy
testing.
What's in this PR
Click-through links
<a>tags pointing at the retailer's product pagerel="noopener noreferrer nofollow"ExternalLinkglyph fades in on hover; the dismissXstill works (preventDefault +stopPropagation on the button)
No more broken-looking cards
placehold.coURL — looked broken in the grid)onErrorswaps to a neutral fallback if a real CDN URL 404s laterDismiss persists across reloads
productUrlorname— the LLM-assignedidrotates on every regeneration)
clearDismissed()action is exposed for a future "undo" affordanceSmarter empty state
"N items are hidden by your budget — raise the slider"instead of the generic "no recommendations"Brand & theme personalization
brandandtagsper itemanalyze_gapsprompt explicitly tells the model to lean into recurring signals (e.g.multiple Barça pieces → suggest more Barça-aligned items; lots of Nike → favor Nike-branded
picks)
Secondhand marketplaces
ASOS, Uniqlo, H&M, COS, Everlane)
CI hygiene
mockBackendDefaults({ recommendations })— local-storeseeding stopped working when the store switched to fetching from the API
pip-auditignoresMAL-2026-4750— malware-tracker false positive against the legitimatefastapipackage