# A power-tool store built natively on Crystallize

> Tools Universe is a demo for the Nordic tool trade: six manufacturers, buy or rent, trade accounts and consumers, four languages. Everything is plain Crystallize: the storefront reads the Discovery API and the Shop API and nothing else.

- **416** products from six manufacturers, 611 versions
- **~2,800** typed spec values, 106 components with an ETIM code
- **13** battery platforms
- **24** rental machines, 75 units at five depots
- **4** languages and three currencies

## How it fits together

One tenant, two APIs. The seed writes the tenant through the PIM API; everything a visitor, an assistant or a crawler sees is read back through Discovery and the Shop API.

- **Manufacturer sources:** Spec sheets, list prices, images from the six brands’ own sites. No retailer data.
- **Seed pipeline:** `npm run seed`: ten idempotent steps, model to customers
- **PIM:** Shapes, typed pieces, topics, ETIM classes, vectors
- **Discovery API:** Search, facets, `rankBy` with the shopper’s taste
- **Shop API:** Cart, checkout, orders, quotes, rental bookings
- **Storefront:** Next.js 16, cached Discovery reads, per-shopper data streamed in
- **Who reads it:** Shoppers (Four languages, VAT toggle, account switcher); On-site assistant (Claude with the catalogue tools); MCP clients (Claude, Claude Code, any MCP host); Crawlers and LLMs (JSON-LD, llms.txt, .md pages)

## Specs are typed, not text

No properties tables. Every spec is its own component, so it can be filtered, ranked, translated and exported without parsing.

A tool has two shared pieces, `power` (source, voltage, motor) and `physical` (weight, size, vibration, noise), and one **spec family** chosen per product: drilling, concrete, sawing, abrasive, woodworking, fastening, installation, measuring, extraction, battery-charging, site, storage, outdoor or consumable. The family is a single choice, so a breaker cannot carry a saw’s fields.

Numbers are numeric components with a unit (`230 Nm`, `18 V`, `5 Ah`), yes/no are booleans, fixed sets are selections. 106 components carry their ETIM 10.0 feature, and the spec labels in Norwegian, Swedish and Dutch are ETIM’s official names. Each product sits in its ETIM class.

The same typed values drive the category facets (range filters on impact energy, blade diameter …), the spec sheet, the JSON-LD with UN/CEFACT unit codes, and the assistant’s and MCP server’s spec filters.

- **Impact energy:** `specs.concrete.impactEnergy` · J (JOU) · EF002831
- **Tool holder:** `specs.concrete.toolHolder` · SDS-max · EV005657
- **Weight:** `physical.weight` · kg (KGM) · EF011121

## Taxonomy, brands and battery platforms

Eleven topic maps describe every product the way the trade thinks about it, in four languages.

Brand, battery platform, product type, trade, material, level, price tier, feature, availability, image type and ETIM class: 188 topics. They drive navigation, facets and the taste vectors.

Brands, battery platforms and technologies are documents with their own story pages. The **battery platform** (Milwaukee M18, Makita LXT, Hilti Nuron …) is the decision a professional has already made: it decides which batteries fit, and it is the strongest signal in personalisation. Accessories, blades and batteries name the machines they fit; machines have the manufacturer’s pairings.

## Rentals with real booking

Heavy equipment is rented per day, weekend, week or four weeks, from five depots in Oslo, Bergen, Stockholm, Gothenburg and Rotterdam.

Each rental item is a bookable product with a pool of named units, the physical machines. The storefront shows live availability per depot and period from the Shop API, books the unit into the basket, and confirms the booking at checkout, linked to the order.

Three booking policies set lead times and a **cancellation window** of 24 or 48 hours: inside it, a rental can still be removed from the basket and the unit is released. Operator certificates, deposits and site delivery are part of the rental item.

## Four languages, three currencies, VAT both ways

Names, copy, topics, image alt text and URL paths are translated. The language picks the market.

English and Dutch sell in EUR (21% VAT), Norwegian in NOK and Swedish in SEK (25%). Prices are stored net, per currency, with volume tiers. The **incl./excl. VAT** toggle in the top bar switches every price on the page; trade accounts default to excl.

Trade customers get their company’s price list from Crystallize markets: Discovery returns `nokPriceFor(marketIdentifiers)` and the Shop API cart uses the same list. Invoice with PO reference, quotes into their own pipeline, and an account page with orders, rentals and quotes by stage.

## Ranked for each customer

No separate recommendation service. One taste vector per shopper, and Discovery does the ranking.

Topics become three vocabularies: **ecosystem** (brand and platform), **work** (trade and material) and **gear** (product type, level, features). Every product has a vector in each. A customer’s taste vector is built from their order history in the Shop API and sent with each query as `context.userTaste`, with a `rankBy` rule that blends it with sales, margin and stock.

Switch demo customer in the header and the store re-ranks: the front page, the category order, the mega-menu images, pairings and alternatives. Sindre, a cabinetmaker who only buys Festool, has the clearest vector; Lotte, a weekend woodworker on DeWalt, sees a very different store.

## Manufacturer data only

Nothing comes from retailers.

Specs, list prices and images come from the six manufacturers’ own sites, gathered by research agents and normalised into the model with a source per product. Product copy is written for the demo. Bosch, Festool and Hilti prices are list prices; the rest, and NOK and SEK, are estimated and rounded to shelf price points. Depots, units, customers and review counts are fictional.

## An idempotent seed

The tenant is code. Change data or model, rerun a step, and the tenant follows.

`npm run seed` runs ten steps in order: tenant settings, content model, taxonomy, images, catalogue, rental, translations, landing pages, vectors, customers. Every step can be rerun on its own; it updates what exists instead of duplicating it. Taste vectors are computed last, written to drafts, then published and indexed.

The build is recorded step by step for playback, and what the Crystallize skills should have told us is written down as it is found.

- **00–02:** Tenant, 29 pieces and 11 shapes, 11 topic maps
- **03–05:** 1,104 images, 416 products, 24 rental items
- **06–07:** Norwegian, Swedish, Dutch; landing pages
- **08–09:** Vectors and index; customers and their history

## An assistant on the site, and an MCP server for any agent

The same catalogue, the same ranking, two ways in.

The **Ask** button in the header opens a shopping assistant running on Claude with the store’s own tools: search with typed spec filters, product details, platforms, rentals and the basket.

The store is also an MCP server. Add it to Claude as a connector, sign in as a demo customer, and shop from the chat: compare tools on a platform, book a rental, fill a basket and check out in the store. Every page is set up to be read by search engines and language models as well.

## What to try

1. Switch customer in the header (try Sindre, then Lotte) and watch the front page and categories re-rank.
2. Search for a spec, not a name. https://tools-universe.superfast.shop/en/search?q=sds%20max%20breaker
3. Open a battery platform from the menu and see every tool, battery and charger on it.
4. Rent a breaker for a weekend: pick a depot, see which units are free, book it into the basket.
5. Flip incl./excl. VAT in the top bar, then switch language to see NOK and SEK.
6. Ask the assistant: “Which batteries fit my tools, and which is the best value?”
7. Append .md to any URL to see what a language model reads.

[Connect Claude to the store](https://tools-universe.superfast.shop/en/mcp.md): MCP setup, demo sign-in, and how the store is set up for AI search

---

Web page: https://tools-universe.superfast.shop/en/about
Markdown version of this page, for language models. Prices are net (excl. VAT) unless marked incl. VAT.
