Building my shopping feed

A feed ranked off my taste, used to curate new arrivals from my favorite brands.

1Codify preferences

Build a taste profile from clothes I own or like.

I wanted to build my own taste profile to power a custom curated shopping feed. So, I built a profile from clothes already in my closet and styles I found and pinned on Pinterest.

California and Japanese heritage prep, crossed with workwear, worn relaxed.The pattern across the board
Owned · 34 Pinned · 68 hover any piece
2Catalog feed

Pull new products from favorite brands.

Many Shopify brands expose their catalog online in a JSON object. I pull new arrivals daily, normalize them, and track what changed. Some brands block that path behind Cloudflare, so in that case the feed runs through a headless browser.

Raw · drakes/products.json

// one record, as the brand serves it
{
  "title": "Forest Green Brushed
   Shetland Crew Neck Jumper",
  "vendor": "Drake's",
  "product_type": "Knitwear",
  "variants": [{ "price": "345.00",
     "available": true, … }],
  "images": [{ "src": "…_2048x.jpg" }]
}

Normalized · one row in my table

iddrakes:7791…
branddrakes
categoryknitwear
price_cents34500
availabletrue
first_seen2026-06-23
vecpending →
3Normalize

Clean up the product images.

Pins are mostly lifestyle photos, so I cut out the garment. I do the same for catalog shots to keep embeddings focused on the item, not irrelevant details like the setting or lighting.

Catalog · a product shot
Drake's product photo
cut-out jumper
Board · a Pinterest pin
lifestyle Pinterest pin
cut-out look
4Encode

Embed each product as a vector.

Each product cut-out and its text data goes through a 150M-parameter multi-modal model fine-tuned for fashion. The output vector makes similar garments searchable by visual and textual traits.

marqo-fashionSigLIPdim 768
5Score

Rank each product by similarity to the taste profile.

For each product, I find the five nearest taste-profile items and average their cosine similarity to ensure it's over a minimum similarity threshold. This helps keep out products that don't align with my aesthetic. There's no trained recommender; the taste profile sets the ranking and fit bar.

new product
Drake's · Shetland crew
0.00
Todd Snyder · Linen crew
0.00
Polo · Flag sweater
0.00
Todd Snyder · Linen crew
0.00
Todd Snyder · Merino
0.00
Polo · Henley
0.00
above floor · 0.40

The actual scoring · rerank-products.ts

taste_score = (
  SELECT sum(sim * weight) / sum(weight)
  FROM (
    SELECT 1 - (product.vec <=> t.vec) AS sim, t.weight
    FROM taste_items t
    ORDER BY product.vec <=> t.vec ASC
    LIMIT 5
  ) nearest
)
-- <=> is pgvector cosine distance · 1 - distance = similarity
6Curate outfits

Hire my own wardrobe stylist.

Outfits drive purchases, so I built a stylist agent. It styles within rules, then a deterministic verifier catches slot errors, product reuse, single-brand looks, and dishonest rationales, then sends failures back for repair.

How the stylist agent runsClaude Opus 4.8 · schema-locked · verifier + one repair
System promptstylist.ts · abridged

You are Cole's personal menswear stylist. Build complete outfits he would actually wear, from the available inventory.

  1. Mix brands. Never a whole look from one label.
  2. One outer layer at most. Don't stack jackets.
  3. Contrast, don't match. Vary texture; one piece carries the color.
  4. Keep formality coherent. One register per look.
  5. Choose the shoe on purpose; it finishes the look.
  6. Don't reuse a product; no shoe in more than two looks.

Pick only from the candidate pool, by exact id. Each "why" must describe only the pieces in that look.

Identity + pool
my wardrobe + brand-diverse in-stock, cached
Claude
structured JSON · each slot = a real product ID
Verifier
slots · no reuse · brand mix · honest rationale
✗ fail → one repair, errors fed back to the model ↺
pass
Outfit
rendered flat-lay · background removed
Evaluation Loopstylist vs cosine vs taste baselines

To tune the rules and prompt, I generated hundreds of outfits from the stylist and two baselines: plain cosine match and taste-only pick. I rated each one blind on would-wear 1 to 5 and failure flags, then kept changes that beat both baselines.

rated outfit
Would wear
✓ kept
rated outfit
Would wear
wrong season
rated outfit
Would wear
✓ kept
Rubric: would-wear 1–5, plus flags for brand collapse, double layer, monotone, formality clash, weak shoe, wrong season, wrong silhouette.
Ship bar: beat both baselines on win rate and mean would-wear, with under 10% critical failures. Scores shown are illustrative; the rubric and bar are real.
7Merchandise

Merchandise top products as outfits.

With the agent tuned, it pulls from the top-ranked products and assembles complete looks by slot. Each outfit is then rendered as a styled flat-lay to help visualize the full look without a human model.

The pieces it picks
Cool, overcast morning4 pieces · 4 brands
Layer · Nudie
Top · Polo
Bottom · Levi's
Shoe · G.H. Bass
four brands one outer layer warm enough
Warm afternoon3 pieces · 3 brands
Top · Todd Snyder
Bottom · Uniqlo
Shoe · Birkenstock
three brands no layer for the heat linen for warmth
Then rendered into one flat-lay · Nano Banana Pro
rendered outfit flat-lay
rendered outfit flat-lay
rendered outfit flat-lay
What's next

Future plans

  1. 1

    Let people sign up, onboard their taste, and run the pipeline on their own feed.

  2. 2

    Add brand discovery and search so I can pull new brands into the feed.

  3. 3

    Track price drops and restocks on pieces I have saved.

  4. 4

    Add affiliate attribution through the product pipeline so the feed can pay for itself.

  5. 5

    Generate a daily outfit that reads my calendar and the weather.

  6. 6

    Fold in light behavioral signal, saves and skips, to sharpen ranking past the cold start.

  7. 7

    Send a weekly digest of the best new arrivals across the brands.

  8. 8

    Explore pulling brand catalogs in from Shopify's Catalog via UCP.