Skip to content
Photo Store

Under the hood

How the personalisation works

The whole store is ranked by Crystallize Discovery. No separate recommendation service, no model retrained overnight — just one vector per customer and one ranking rule per surface.

1A vocabulary you own

The range is described in three vocabularies. Each dimension is a topic map in the PIM, and every topic path becomes a vector key: /brand/nikon → brand:nikon. Topics are the single source of truth — taste is derived, never maintained separately.

Brand & system

“brand”

  • brand[1, 0.5, 0.25]
  • system[1, 0.5]

Use case

“usecase”

  • usecase[1, 0.7, 0.45, 0.3]

Product type & level

“gear”

  • category[1, 0.5]
  • level[1]
  • price-tier[0.8]

The weights are positional. A lens listing brand:tamron before brand:nikon weighs 1.0 on Tamron and 0.5 on Nikon — so a Nikon owner sees third-party glass that fits, but Nikon's own lenses first.

2The profile is built from orders, not guesses

The customer's vector is calculated server-side from their order history in Crystallize. Every purchased line contributes its own product vector, weighted by quantity, by how much was spent and by how long ago it was bought (a 180-day half-life). The result is sent to Discovery as context.userTaste.

Pick a customer at the top right to see their actual order history and the vector it produces.

3Your rules stay on top

Taste is one term among several. Margin, stock, sales and campaign weight sit alongside it, and every surface has its own balance. This list is exactly what is sent as rankBy.

Front page

  • Brand & systemtasteCosine× 1.70
  • Use casetasteCosine× 1.40
  • Product type & leveltasteCosine× 0.80
  • Sold, 30 daysfieldBoost× 0.55
  • MarginfieldBoost× 0.35
  • RatingfieldBoost× 0.30
  • CampaignfieldBoost× 0.25
  • In stockinStockBoost× 0.25
  • Newnessrecency× 0.20

Category page

  • Brand & systemtasteCosine× 1.40
  • Use casetasteCosine× 1.20
  • Product type & leveltasteCosine× 1.00
  • Sold, 30 daysfieldBoost× 0.55
  • MarginfieldBoost× 0.35
  • RatingfieldBoost× 0.30
  • CampaignfieldBoost× 0.25
  • In stockinStockBoost× 0.25
  • Newnessrecency× 0.20

Search

  • Search relevancerelevance× 2.00
  • Brand & systemtasteCosine× 0.90
  • Use casetasteCosine× 0.80
  • Product type & leveltasteCosine× 0.40
  • Sold, 30 daysfieldBoost× 0.30
  • In stockinStockBoost× 0.20

Every hit gets a rankScore and a rankExplain whose contributions add up exactly to the score. Click the score badge on a card to see the maths.

4The taxonomy

Six topic maps classify the range. The same maps drive the filters on the category pages and the vectors in Discovery.

Brand /brand

  • Canon
  • Nikon
  • Sony
  • Fujifilm
  • Panasonic
  • OM System
  • Leica
  • Hasselblad
  • DJI
  • GoPro
  • Insta360
  • Sigma
  • Tamron
  • Viltrox
  • +30 more

System & mount /system

  • Canon RF
  • Canon EF
  • Sony E
  • Nikon Z
  • Nikon F
  • Fujifilm X
  • Fujifilm GFX
  • Micro Four Thirds
  • L-Mount
  • Any system

Product type /category

  • Mirrorless camera
  • Compact camera
  • Action camera
  • Video camera
  • Zoom lens
  • Prime lens
  • Telephoto lens
  • Wide-angle lens
  • Macro lens
  • Drone
  • Flash
  • Studio lighting
  • Tripod
  • Gimbal
  • +7 more

Use case /usecase

  • Wildlife & nature
  • Portrait
  • Landscape
  • Sport & action
  • Travel
  • Film & video
  • Vlog & content
  • Studio
  • Astro & night
  • Street
  • Product photography
  • Wedding & events

Level /level

  • Beginner
  • Enthusiast
  • Professional

Price tier /price-tier

  • Budget
  • Mid-range
  • Premium
  • Flagship

5The APIs

  • Discovery API

    The whole frontend: front page, campaign blocks, category listings, facets, search, similar products.

    context + rankBy + nearestTo, public and unauthenticated.

  • Shop API

    Basket and checkout.

    hydrate → place → createFromCart, with tax calculated from the market's rate.

  • Core API

    Customers, customer groups and order history.

    Read server-side to build the profile vector. Never exposed to the browser.

6Talk to the store from Claude — the MCP server

The same catalogue, ranking and basket are exposed to AI assistants through a Model Context Protocol server that runs inside this app. Nothing is duplicated: the tools call the same Discovery queries as the storefront, so Claude sees the products in the same order a shopper would.

Endpoint

https://photo-store-vector.superfast.shop/api/mcp

Claude.ai, Claude Desktop, mobile

  1. Open Customize → Connectors → Add custom connector.
  2. Paste the endpoint above as the MCP server URL.
  3. Authentication: Sign in when needed. OAuth client: Use Claude's published identity (or Register automatically — both work).
  4. Turn the connector on in a chat and ask for a camera.

Claude connects from Anthropic's cloud, so the store has to be reachable on the internet — this deployment is.

Claude Code

claude mcp add --transport http photo-store https://photo-store-vector.superfast.shop/api/mcp
claude -p "Find me a travel tripod under £150"

Run /mcp in a session to sign in when a personal tool asks for it.

Things to try

  • “What's a good second lens for a Nikon Z6 III? Show me what's in stock.”
  • “I shoot wildlife. Build me a kit under £3,000 and put it in a basket.”
  • “Which campaigns are running right now?”
  • “Sign me in and show what you'd recommend for me — and explain why.”
  • “What have I ordered before? What would complete my kit?”
  • “Add two memory cards to my basket and give me the checkout link.”

Without signing in

  • search_products
  • get_product
  • similar_products
  • campaigns
  • list_categories
  • list_brands
  • add_to_cart
  • update_cart_line
  • view_cart
  • suggest_add_ons
  • checkout

Search, details, campaigns and the basket. Ranked with the house rules, priced in GBP incl. VAT unless a market is given.

After signing in

  • whoami
  • my_orders
  • recommendations

The first call to one of these makes Claude show a Connect card. Signing in means picking a demo customer — the same people as the switcher at the top right. From then on every tool ranks with their taste vector and prices follow their market and VAT mode.

Pictures, not just text

Nine tools carry an MCP App: Claude renders product carousels, a detail card and the basket under the tool call, with real Add to basket buttons that call the same tools. get_product also returns the packshot as an image. Hosts without app support get a link to a store page with the same cards.

How the login works

The MCP server is an OAuth 2.1 resource server and, for this demo, its own authorization server — stateless, every code and token a signed JWT. Discovery documents live at /.well-known/oauth-protected-resource/api/mcp and /.well-known/oauth-authorization-server. Public tools never require a token (lazy authentication); a protected call answers 401 with a WWW-Authenticate challenge, Claude runs PKCE authorization against /oauth/authorize, and retries the same call with the token. A real shop would point authorization_servers at its own identity provider and keep everything else.

Step-by-step: add the store to Claude and sign in →

Full write-up in docs/mcp.md. Smoke-test any deployment with node scripts/mcp/smoke.mjs https://photo-store-vector.superfast.shop.

← Back to the store