Skip to main content
Build

Storefront

Ember & Oak

Ember & Oak is a demo, not a real shop — it’s here to show one kind of thing you could build on Headless. The idea: a storefront where the product grid does no client-side filtering, because every category chip, price range, in-stock toggle, sort order, and page turn is a query the server answers — and a single “Store Settings” entry drives the brand color, name, hero headline, and announcement bar, so changing it re-skins the whole site. Here’s how you’d build your own like it, by prompting a coding agent.

Server-side filter · sort · paginate
headless.build/demos/demo-shop
The Ember & Oak demo storefront — an announcement bar, hero, and a product grid with category, price, and stock filters.

Step 0

The content model

Here’s the shape you’re aiming for. You don’t have to build it by hand — the next steps have an agent create it for you — but it helps to see the target first. Expand a type to see its fields.

storesettingsSingleton5 fields

One-of-a-kind settings that theme the whole storefront at runtime.

  • brandcolorTexthex, sets the accent
  • storenameText
  • taglineTextrendered as the hero headline
  • announcementTexttop bar; hidden if empty
  • freeshippingthresholdNumber
productCollection10 fields

The catalog — queried with filters, sort, and pagination.

  • nameText
  • descriptionText
  • priceNumber
  • compareatpriceNumberstrikethrough price
  • imageurlText
  • categoryEnumcookware · knives · utensils · serveware
  • badgeEnumsale · new · limited
  • instockBoolean
  • ratingNumber
  • materialsMulti-selectstainless-steel, walnut, cast-iron, …

The recipe

Build your own with an agent

Use this as a blueprint, not a script — adapt the fields and copy to whatever you’re making. Each step is a real prompt you can hand to a coding agent like Claude Code with the Headless MCP server connected; the terminals show the tool calls the agent makes, and the code is what it produces.

  1. Create the project

    Start by asking your agent to create a project. With the Headless MCP server connected, it can do this directly — no dashboard round-trip. Every project ships with REST, GraphQL, and MCP the moment it exists.

    MCP · Headless
    # Spin up a fresh project
    claude "Create a Headless project called Ember & Oak for a kitchenware store"
    create_project { name: "Ember & Oak", slug: "demo-shop" }
    → demo-shop ready · REST · GraphQL · MCP live
  2. Model the content

    Describe the data in plain language and let the agent translate it into content types and fields. Ember & Oak needs two: a one-off “Store Settings” singleton that themes the site, and a “Product” collection for the catalog. New fields are queryable the same second they exist — no migration, no deploy.

    MCP · Headless
    # A singleton for store-wide settings
    claude "Add a singleton Store Settings with brand color, store name, tagline, announcement, and a free-shipping threshold"
    create_content_type { name: "Store Settings", isSingle: true }
    create_field × 5
    # Then the product catalog
    claude "Add a Product type: name, description, price, compare-at price, image URL, a category enum, a badge enum, in-stock, rating, and a materials multi-select"
    create_content_type { name: "Product" }
    create_field × 10 (category & materials as enums)
    → 2 types, 15 fields — live over the API
  3. Seed some content

    Have the agent fill the store: set the singleton’s brand color and copy, then batch-create a realistic spread of products across every category so the filters have something to bite on. `create_entries` takes up to 100 at a time.

    MCP · Headless
    # Fill the shelves
    claude "Set the store settings, then seed a dozen products across cookware, knives, utensils, and serveware — then publish them"
    update_entry storesettings { brandcolor: "#c2410c", … }
    create_entries product × 12
    publish_entries { count: 12 }
    → the storefront has content to render
  4. Mint a read-only API key

    The storefront reads content in the browser, so it needs a public, read-only key — never a write key. Create one in the dashboard under Project Settings → API Keys with Read scope, then smoke-test it from the terminal before wiring up any UI.

    Terminal
    # Confirm the key works and see the response shape
    curl -s "https://headless.build/api/v1/demo-shop/product?limit=1" \
      -H "X-API-Key: hls_live_your_read_only_key" | jq
    
    # → { "data": [ { "id": "...", "attributes": { "name": ... } } ],
    #     "meta": { "total": 12 } }
  5. Build the storefront

    Now hand the whole frontend to the agent as one task. The key move: filtering, sorting, and pagination are not done in JavaScript — they’re encoded in the query string and answered by the server. Filters use the plural `filters[field][$op]` syntax; sort uses a leading `-` for descending.

    Claude Code
    # The storefront itself
    claude "Write a single self-contained index.html storefront: read Store Settings to theme the page, then list Products with a category filter, price range, in-stock toggle, sort, and pagination — all server-side via the REST API"
    Write public/demos/demo-shop/index.html
    → 1 file · vanilla JS · no build step
    index.html
    // The server does the work — the client just builds the query string.
    function buildQuery() {
      const p = new URLSearchParams();
      p.set("limit", 6);
      p.set("page", page + 1);                     // 1-indexed
      p.set("sort", state.sort);                   // "-createdAt" | "price" | "-price" | "-rating"
      if (state.category) p.set("filters[category][$eq]", state.category);
      if (state.min)      p.set("filters[price][$gte]", state.min);
      if (state.max)      p.set("filters[price][$lte]", state.max);
      if (state.inStock)  p.set("filters[instock][$eq]", "true");
      return `/product?${p}`;
    }
    
    async function api(path) {
      const res = await fetch(`https://headless.build/api/v1/demo-shop${path}`, {
        headers: { "X-API-Key": API_KEY },
      });
      return res.json();                           // { data: [...], meta: { total } }
    }
  6. Ship it

    At this point your storefront is just static files plus a CMS — deploy the frontend to any static host and you’re live. Because the catalog and the theme both live in Headless, the site keeps itself current: publish a new product or change the brand color and it shows up on the next load, no redeploy. The Ember & Oak demo you can open above is exactly this, running on our own API — proof the pattern works end to end.

Build your own in an afternoon.

Model your content once, point an agent at it, and ship. Every project speaks REST, GraphQL, and MCP from the first entry.