Skip to content
Sneferu
by Hekana

Page types

Style every page of a Hekana store with Sneferu templates: product, collection, search, cart, page and 404, alternates and the objects each one has in scope.

On this page

A store has more pages than the home page. A theme can style each page type with its own template. Any type you do not write is filled in by the SDK's default store, so every page of the store goes through your theme (its layout, tokens and CSS) from the first day.

Template filePageData in scope
templates/index.snfHome (required)none
templates/product.snfOne productproduct
templates/collection.snfA category, or all productscollection, paginate
templates/search.snfSearch resultssearch, paginate
templates/cart.snfThe cartnone (the cart is drawn in the browser, see Cart and controllers)
templates/page.snfA merchant's content pagepage
templates/404.snfPage not foundnone

product, collection and page also take alternates: product.codes.snf is a second product template a merchant can assign to some products. Any other template name is SN3035.

Every template can also read request, localization, store, locale and dir.

templates/product.snf
<hk-sections />
<hk-schema>
  {
    "sections": [
      {
        "type": "product-main",
        "blocks": [
          {
            "type": "product-title"
          },
          {
            "type": "product-price"
          },
          {
            "type": "product-excerpt"
          },
          {
            "type": "product-variants"
          },
          {
            "type": "product-buy"
          },
          {
            "type": "product-text"
          },
          {
            "type": "product-description"
          },
          {
            "type": "product-tags"
          }
        ]
      },
      {
        "type": "related-products"
      }
    ]
  }
</hk-schema>
Result
A product page: a large image with thumbnails on the left, title, price, option buttons, quantity and an Add to cart button on the right
The default product page, 1080 px wide.

The product

product.id  product.handle  product.title  product.url
product.price  product.compare_at  product.price_min  product.price_max   (minor units: piastres)
product.available                  false when every variant is sold out
product.image  product.images      image objects { url, srcset?, alt?, width?, height? }
product.description                sanitised HTML: print with <hk-rich-text>
product.excerpt  product.kind  product.digital_kind  product.tags  product.category
product.options                    [{ name, values: [string] }]
product.variants                   [{ id, title, price, compare_at, available, options: [string], image }]
product.selected_variant  product.has_variants
product.min_quantity  product.quantity_step  product.max_quantity

product.price is the price of the variant shown first. Do not compute totals in a template: the server prices the cart.

collection.handle  collection.title  collection.description  collection.url  collection.image
collection.products          the products of this page
collection.products_count    all of them
collection.sort_options      optional: [{ value, label, url, active }]
collection.filters           optional: [{ name, values: [{ label, url, active, count }] }]

search.terms  search.results  search.results_count

paginate.page  paginate.pages  paginate.per_page  paginate.total
paginate.prev_url  paginate.next_url
paginate.parts               at most 7 pages around the current one: [{ page, url, current }]

/category/<handle>?page=999, ?page=-1 and ?page=abc are clamped to a real page. Print the page links with <hk-pagination paginate="{{ paginate }}" />.

Pages and requests

page.title  page.body_html (sanitised: use <hk-rich-text>)  page.handle  page.url
request.path  request.page_type            product, collection, ... (index for the home page)
localization.locale  localization.alternate_locale  localization.alternate_url

localization.alternate_locale is null when the theme ships one language.

<hk-product-gallery product="{{ product }}" layout="thumbs-below" /> prints the first image eager and with high priority, the others lazy, and thumbnails as plain links. layout is thumbs-below, thumbs-side or stacked. Without JavaScript the thumbnails still switch the image.

Pagination and language switch

<hk-pagination paginate="{{ paginate }}" /> prints previous and next links and the page numbers (44 px targets, mirrored arrows on Arabic pages); it prints nothing for a single page.

<hk-locale-switch /> links to the same page in the other language, labelled in that language (العربية or English) with hreflang and lang. It prints nothing when localization.alternate_url is empty.

Choosing a product or collection

A setting of type product stores a handle, like collection does:

html
{{ product(section.settings.pick).title }}

product() takes a handle or a product setting (SN2012 otherwise); a page that uses it has its products preloaded (pageDependencies(...).products).

Try it

sneferu dev serves every page type: /products/<handle>, /products, /category/<handle>?page=2, /search?q=card, /cart, /pages/about, and a 404 for anything else. Add /en or /ar to switch language, or ?template=product.codes to preview an alternate. The 404 page uses your templates/404.snf, or the default store's when you have none; /__template/<name> still renders any template directly.