Store and landing pages

Single pages (about, offers, product landing pages) built from the live template's components.

A store page is one page at /pages/<slug>. It has no code of its own: its content places components of the store's live template and core blocks in the template's store-page frame (app/pages/[slug]/page.tsx, or a plain main area). A product landing page is a store page with a productId; its product is in scope for the order form.

json
{
  "path": "/pages/summer-shoe",
  "title": "Summer shoe",
  "productId": "<product id>",
  "content": {
    "layout": "blank",
    "slots": {
      "main": [
        { "id": "hero", "use": "hero", "props": { "title": "Walk lighter" } },
        { "id": "buy", "use": "core/product", "slots": { "main": [
          { "id": "gallery", "use": "core/product-gallery" },
          { "id": "form", "use": "core/order-form" },
          { "id": "button", "use": "core/order-button" }
        ] } }
      ]
    }
  }
}

Layouts

content.layout picks what surrounds the page:

ValueThe page renders
absentIn the template's default layout (app/layout.tsx): the store header and footer
blankIn the default layout with its slots left empty: the template's styles and theme, no header or footer
<name>In the template's app/layouts/<name>.tsx (for example a logo-only landing layout)

GET /stores/:id/template lists the choices in layouts ([{id, title, description}]). New product landing pages start with blank. A name the live template does not have is refused on save (422, LAYOUT_UNKNOWN) and, after a template switch, renders in the default layout.

API

RequestDoes
GET /stores/:id/pages?kind=page|landing&productId=List pages
POST /stores/:id/pagesCreate a draft page
PATCH /stores/:id/pages/:pageIdChange path, title, content, seo or productId with expectedVersion
POST /stores/:id/pages/:pageId/preview{token, path}: open <storefront><path>?pagePreview=<token>
POST /stores/:id/pages/:pageId/publishMake the saved version public
POST …/unpublish, …/duplicate, DELETE …Hide, copy, delete
GET /stores/:id/pages/resolve?path=Public: the published page at a path

Every save is version-checked: a stale expectedVersion returns 409 with the current version. The content is validated against the live template's components, store-page slots and layouts; problems return 422 PAGE_INVALID with diagnostics.

In the app: Pages for store pages, and the Landing pages tab of a product.