Build yours with AI

A store like Block Builder Universe, with your brand

Copy this prompt and paste it into a coding agent (Claude Code, Cursor or Codex) in an empty folder. It asks for your Crystallize tenant, your products and your brand, then builds the store on your own tenant.

Raw Markdown

I want a storefront for my business that works like Block Builder Universe (https://block-builder.superfast.shop), a demo store built on Crystallize: A 3D block builder where the build is the basket: every block placed is a real variant in Crystallize, so a model made by hand, from a ready-made set or by an AI from a sentence is priced as you build and ordered as exactly the blocks it is made of.

The content model and the wiring below are proven in that store: keep them for the features I want, and rename things to fit my trade. If a feature doesn't fit my business, leave its parts out rather than forcing it. Everything I see is mine to decide: brand, colours, typography, layout, copy and pages. Don't copy the demo's look; build my brand.

What the demo does: product configurator, ai concierge, large variant sets. It is B2C, in English; my markets and languages may differ.

How to work with me

  • You need to run commands, edit files and use MCP tools. If you can't (for example in a plain chat), tell me, and suggest I paste this prompt into Claude Code, Cursor or another coding agent instead.
  • Ask your questions a few at a time (three to five), in the order of the steps below, and suggest a sensible default for each so I can just say yes. Ask each thing once, even where two lists overlap, and ask the ones that change the build first. Don't start a step before the one before it is done.
  • The technical detail below is for you. Talk to me in plain words, and explain a choice only when I need to make it.
  • Keep the folder empty until step 5, apart from .env.local.
  • Never ask me to paste an access token secret into the chat, and tell me not to paste a filled-in command or its output either. Tell me which command to run or which file to put it in, and I'll do it.
  • Before you create or change anything in Crystallize, show me the plan (shapes, pieces, topics, price variants, markets) and wait for my yes. Before an import, show me a sample of five items.
  • Use the Crystallize skills (the skills MCP tool, or the use-crystallize plugin) for how-to: content-model, information-architecture, taxonomy, data-creation, mass-operations, pricing, query, mutation, js-api-client, responsive-images, payments, and when this store needs them subscriptions, bookable-resources, vector-ranking and permissions. Where this prompt and a skill disagree, the skill wins. Check the live schemas with the MCP instead of guessing field names.
  • When something I asked for isn't possible in Crystallize the way I pictured it, say so and offer the closest thing that is.
  • The storefront never reads from the Core API on customer-facing pages. Products, public prices, stock and content come from the Discovery API and the Catalogue API; confidential prices (negotiated B2B price lists) from the Catalogue API on the server.
  • Use the Shop API for everything about customers: carts, checkout, customers, orders (including orders created directly, such as renewals), order meta, pipeline stages, payments and subscription contracts. Take the customer identifier from the server session, never from the browser. The Core API is for setup scripts, back-office tools, scheduled jobs and what the Shop API can't do, always on the server and never once per page view.

Step 1: Crystallize tenant, tokens and MCP

Ask me:

  1. Do I have a Crystallize account and a tenant for this store? If not, I sign up for free at https://app.crystallize.com/signup and create an empty tenant. Ask for its tenant identifier.
  2. Do I have access tokens? If not, tell me: in the Crystallize App, go to Settings → Access Tokens → Generate a new token, name it, and keep the ID and the secret (the secret is shown once). A token acts with its user's role, so while we build, that user needs to be Tenant Admin (or have a role that can write shapes, pieces, topics, items and prices and run mass operations). Once the store is built, switch the MCP to a token from a read-only user.
  3. Is the Crystallize MCP connected, with write access? Check that you have its write tools (run-mass-operation, mutate-core), not only the read tools (tenant-overview, fetch-content-model): with only the read tools, it was added without ?exposeWrite=true. If it's missing, have me run this in my terminal with my own token, then restart you:
    npx add-mcp "https://mcp.crystallize.com/mcp?exposeWrite=true" \
      --header "X-Crystallize-Access-Token-Id: <token id>" \
      --header "X-Crystallize-Access-Token-Secret: <token secret>"
    
    If the MCP can't be connected in my tool, say so and fall back to scripts that call the Crystallize APIs with the tokens from .env.local. In Claude Code, also suggest the Crystallize skills: /plugin marketplace add crystallizeapi/ai, then /plugin install use-crystallize@crystallize-ai. The plugin brings its own read-only Crystallize MCP entry with placeholder credentials: keep using the one added above (and add &exposeSkills=false to its URL once the plugin's skills are installed).
  4. Confirm the connection with tenant-overview, and tell me what's already in the tenant. If it isn't empty, ask whether to build next to what's there or in a fresh tenant.

The storefront needs the tenant identifier and its own credentials: an access token pair for the Shop API (server only), and a static auth token if Discovery and the Catalogue API are secured. Don't reuse the admin build token in production. Put them in .env.local (have me fill in the secrets) and make sure .env* is in .gitignore.

Step 2: my business and my brand

Ask me:

  • What I sell, who buys it, and what makes us different. My brand name and a one-line pitch.
  • My markets, currencies and languages, and my VAT/tax setup.
  • Where my product data lives today: a spreadsheet or CSV, an export from Shopify, WooCommerce or another platform, a PIM or ERP, my current website, or nothing yet. Where my product images are.
  • My brand: logo (SVG if I have it), colours, typefaces, tone of voice, and two or three sites whose look I like. If I have no brand guide, propose a direction from my answers and show it before building pages.
  • Where it should run: my own domain, and hosting (suggest Vercel for Next.js).

Then ask what is particular to this kind of store:

  • What do I sell piece by piece, and what makes two pieces different products: shape, size, colour, finish? Do all colours of a shape cost the same?
  • How do my pieces join? The demo's are blocks on a grid of studs; anything that snaps together on a grid (tiles, beads, modular parts) works the same way. What may float, and what must rest on something?
  • Which ground does a build stand on: one plate in a few sizes, or several laid out as a town, some with roads?
  • Do I want ready-made sets to start from, and a public gallery of builds people have shared?
  • Do I want an AI that builds a model from a sentence or a picture? Which provider do I have a key for, and should it be open to everyone or limited per visitor?
  • What should a buyer get besides the pieces: building instructions and a pick list as PDFs, a share link, a picture of the build?
  • My currency, VAT and where I ship. The demo is one market in EUR, and its payment is a mock.
  • May I use the shapes I have in mind? Check that a piece's design isn't protected before it goes in the catalogue, and keep other makers' names and brands out of the store.

Step 3: the content model

Create this in my tenant with the MCP, renamed to fit my trade, after I have approved the plan. Keep the structure: it is what the storefront's features depend on.

Build in dependency order, since mass operations run in sequence with no rollback: pieces and shapes (empty first, then their components), topic maps (at most 30 topics per topic/create), price variants, markets and VAT types, the folder tree (two to four levels, five to twelve per level), and only then items. Use lowercase-hyphen identifiers. Decide now which fields are translated and which are discoverable. Restrict every item relation with acceptedShapeIdentifiers. Never add price or stock components to a shape: variants have them built in.

  • block (product): one product per shape (a 2 × 4 brick, a 1 × 2 slope), in a category folder, with a block-spec piece: its shape (box, tile, slope, curve, arch, round, window, door and so on), width, length and height on the grid, and weight. One variant per colour, with a colors component (label, hex), a Finish attribute for see-through colours, its own SKU, image and price.
  • baseplate (product): the ground, with its size and layout (plain, or a road running through it).
  • set (product): a ready-made build, with a description and its whole design packed into one design rich text. Priced from its blocks, never on its own.
  • Topics for the gallery: a build theme (animals, buildings, vehicles and so on) and a size, set on the build's picture.
  • Pricing: one price variant per currency. An Orders pipeline whose first stage takes new orders.
  • A design is small and plain: { plate, blocks: [{ sku, x, y, z, r }] }, with positions on the grid and r in quarter turns. It is the build, the basket and the bill of materials at once.

Step 4: my data

Import my products and content with mass operations, mapping my data onto the model: validate each file with build-mass-operation, run it with run-mass-operation and follow it with get-mass-operation-status. Read the operation logs, not just the task status: a task can finish as complete with failed operations, and there is no rollback. Give every upsert a resourceIdentifier so a re-run updates instead of duplicating, and chunk large imports. Start with a small batch, check it in the Crystallize App with me, then run the rest.

Publish every imported item in each language: the storefront only sees published versions (in a mass operation, item/publish needs real itemIds). Import images from URLs with copyRemoteAsset, or upload them (presigned upload, then registerImage). Renditions are generated in a queue: after a large import, republish once they exist, and have the storefront fall back to the original image URL while variants is empty. Before building pages, query Discovery once; if the tenant isn't ignited yet, run igniteDiscoApi (with stacks: opensearch if we use vector ranking), wait for the task to complete, and allow a few minutes. If I have no data yet, create a small, clearly labelled placeholder set (ten or so products) so we can build the pages, and remind me to replace it.

  • The demo is 62 shapes in 20 colours (1,056 variants), eleven baseplates (seven plain, four with roads) and eight sets, from a cottage of 294 blocks to a town on nine plates. All of it is generated from one file in the repo into mass operations: model, catalogue, publish, sets, topics.
  • The sets are written as rules in code (walls, roofs, trees) rather than block by block, and the seed packs each result into the set's design.
  • Product images are rendered by the app itself from the same geometry the builder draws, one per variant, then uploaded and attached by key.
  • From me: my pieces with sizes, colours and prices, the sets I want to start with, and the rules for how pieces join.

Step 5: the storefront

  • A single-page app (the demo is Vite, React and three.js) with a small server beside it. The browser only talks to that server; every Crystallize token stays there.
  • One engine, three places: the grid, collisions, what grips what, the bill of materials and the price live in one plain JavaScript file with no imports, run by the browser, the server and the tests. Geometry is generated from a shape's dimensions, so there are no model files.
  • The catalogue (Discovery API): one query builds a snapshot of every shape, colour, baseplate and set, cached on the server. The palette, the prices and the sets all come from it.
  • The build is a cart (Shop API): a moment after each change the server hydrates the same cart with one line per SKU. An order re-validates the design, re-prices it with the engine and refuses if the Shop API total differs; then it completes that cart.
  • Sharing: a shared build is a Shop API cart of type wishlist with the design in its meta, opened at /b/<id>. A gallery build is the same with a name and a theme, and its picture in the media library, tagged with the theme topic and carrying the build's id and numbers in its meta. The gallery lists those pictures; it never reads the wishlists.
  • PDFs: building instructions layer by layer and a pick list, drawn on the server from the design as flat isometric shapes, with a small PDF writer of its own.
  • The AI builder: the model never names a SKU or places a block. It writes a plan of coarse parts (a box, a roof, a cylinder, an outline pushed through a thickness, each with a colour and a size), and a compiler fills the parts with real blocks, staggers the joints and drops what would float. The model is told once what did not hold and writes parts to carry it. A slower mode writes three drafts, picks the best from pictures of them, then looks at the build twice and corrects it. Structured output, streamed, so blocks appear as the plan arrives. Env: ANTHROPIC_API_KEY, server only.
  • Usage and admin (optional): one record per AI build, share and order, kept in a small Redis store, with a password-protected page that lists them.
  • Env: CRYSTALLIZE_TENANT_IDENTIFIER, CRYSTALLIZE_ACCESS_TOKEN_ID, CRYSTALLIZE_ACCESS_TOKEN_SECRET, on the server only.

Build my design, not a demo's: my typefaces, colours and tone, with pages that suit my products. Show me the home page, a category and a product page early, and adjust the design with me before building the rest.

Every page is built for search engines, answer engines and AI agents from the start, not added at the end:

  • SEO: server-rendered HTML, one <h1>, a unique title and description, canonical URLs, hreflang per language, a sitemap and robots.txt, and clean, translated paths.
  • Structured data: JSON-LD on every page that has a subject: Organization and WebSite (with a SearchAction) on the home page, Product with Offer (price, currency, availability) on product pages, BreadcrumbList on categories and products, Article or Recipe on content. Generate it from the same data as the page.
  • GEO, for answer engines and agents: /llms.txt (an H1, a summary, links to every section), /llms-full.txt, and a Markdown twin of every page (its URL plus .md, or Accept: text/markdown), with prices, stock and facts written out in plain sentences.
  • Agents can act, not only read: register the store's actions (search, add to cart, check availability) with WebMCP (navigator.modelContext.registerTool, or annotated forms), and keep the accessibility tree clean: semantic HTML, labelled controls, real buttons and links.
  • Fast and stable: responsive images from Crystallize, no layout shift (reserve space for images and late content), little client JavaScript. Aim for 100 in every Lighthouse category (Performance, Accessibility, Best Practices, SEO; heavy 3D or video pages may score lower on performance) and pass every Agentic Browsing check.

Step 6: run it, then ship it

Run it locally and walk me through each feature above with my own data. Fix what I find. Before you call it done, run Lighthouse on the home page, a category and a product page (npx lighthouse <url> --only-categories=performance,accessibility,best-practices,seo,agentic-browsing), validate the JSON-LD (https://validator.schema.org), open /llms.txt and a page's .md twin, and fix what falls short. Deploy only when I ask: set the same environment variables on the host, point my domain, and give me the live URL.

Watch out for

  • The Catalogue API can come back with no variants for these products: read the catalogue from Discovery, and ignite Discovery again after the content model changes.
  • A cart merges identical SKUs into one line, so the build can't be rebuilt from cart lines: keep the design itself in the meta.
  • Never trust the browser's price or design: validate and price on the server with the same engine, and compare with the Shop API total.
  • Don't let the model place blocks one by one: it loses count and builds things that float. Let it describe parts and let code do the bricks.
  • A long AI build needs a function that may run for minutes and a stream that reports progress; set the limit and show what is happening.
  • Listing a gallery from Core on every visit runs into rate limits: read it on the server every few minutes and cache it.
  • Rendering product pictures and the 3D scene stops in a background tab: run the batch in a visible window.
  • Files can't go through mass operations: upload them, then attach the key.
  • Records of who built what hold IP addresses and prompts: tell visitors, and decide how long to keep them.
  • Don't invent facts about my business (prices, stock, certifications, delivery promises). Ask, or leave a clearly marked placeholder.

And for every Crystallize store, from the skills:

  • Orders: create and change them through the Shop API /order (createFromCart, create, setMeta with merge: true, addToStage, setPayments). Editing an order in Core adds a duplicate to the Shop API's list. Read a customer's orders with the identifier from the session, limit: 100, grouped by coreId (keep the newest). Seed order history through /order create, not Core registerOrder. The order id is the cart id; don't call fulfill after createFromCart.
  • Payments: create the order from the payment provider's verified webhook, never from the browser, once per cart.
  • Cart meta goes in hydrate(input: { meta }); hydrate is the whole cart, so send every line each time.
  • Images: serve them straight from Crystallize (not through an image optimizer such as next/image in its default setup): a WebP srcset from the returned variants with an accurate sizes, falling back to the original URL while renditions are missing. Replace an image by uploading a new one, not with registerImageRevision.
  • Ranking (if the store ranks per shopper): check that __type(name: "RankByInput") exists; pass context as a variable, with userTaste entries of { vocabulary, weights, magnitude } (magnitude = the square root of the sum of squared weights); tieBreaker is required; don't combine sorting with ranking, and page with skip and limit inside the rerank window; introspect TenantRankByField for field names; leave context out when there's no taste; use explain: true only for tuning.
  • Bookings (if the store books): durations are in seconds; the role needs the bookingPolicies permission; put the customer on the cart before bookSkuItem; every hydrate must resend each booked line with its window and unit, or the booking is cancelled; remove a booking by re-hydrating without it.

Done when

  • My tenant has the content model above with my products, prices and images in it.
  • The storefront runs on my domain in my brand, and every feature I chose works with my data: we have clicked through each one together.
  • Lighthouse scores close to 100 in every category and every Agentic Browsing check passes on the home, category and product pages.
  • I know how to add a product, change a price and publish, in the Crystallize App.