Fairpage

Setting up a shop

A cart and an order form on Plus+: the collections a shop needs, products with variants, and the pages that add to the cart and send it.

On this page
  1. What a shop is made of
  2. Variants
  3. The cart's list
  4. Pages
  5. Trying it
  6. The confirmation mail

What a shop is made of

A shop is three or four collections in the site's schema (_content/schema.yaml), written with the AI bar or pushed from the command line:

  • productshave a name, a slug and photos, and a price unless they have variants.
  • variantshold a product's sizes or colours: each its product, its option values, its price and its picture.
  • ordersis a form collection with form: {cart: lines, confirm: email}: the buyer's fields, the list the cart fills, and its total.

A schema with cart: is refused below Plus+. fairpage docs has the full reference under A cart and orders: every option, the cart page and the confirmation mail.

Variants

Variants are a collection of their own, edited on the product's form as a table, as Shopify edits them. On variants:

  • product: {type: relation, to: products, required: true, inline: true} puts the table on the product. in_nav: false on the collection leaves variants out of Content's sidebar.
  • value_1: {type: text, in_list: true, label_from: option_name} is the first option's value. Its column is named by the product's option_name, a text field, and the owners add values there as chips. A value_2 with label_from: option_2_name is a second option.
  • price: {type: number, format: money, currency: EUR, required: true, in_list: true} is the variant's price. It is the only price: the product has none of its own.
  • image: {type: image, in_list: true, pick: gallery} is picked from the product's gallery list, whose items have one image.
  • old_price: {type: number, format: money, currency: EUR, in_list: true, when: on_sale} shows only while the product's on_sale checkbox is ticked.

Every field the table shows is marked in_list: true. A slug, slug: {type: slug, from: value_1}, is made from the value, or from the product's slug for a product without options.

The cart's list

On orders, the list cart: names holds one relation, to the variants (or the products when there are none), a whole quantity with a min and a max, a text name and a money price:

  • variant: {type: relation, to: variants, required: true}
  • quantity: {type: number, format: integer, min: 1, max: 99, required: true}
  • name: {type: text, set: variant.product.name}
  • option_1: {type: text, set: variant.value_1}
  • price: {type: number, format: money, currency: EUR, set: variant.price}

set: is filled from the live rows when an order arrives, so no price comes from the browser. The order's total is {type: number, format: money, currency: EUR, set: sum(lines.price * lines.quantity)}. A line's other copied text, such as option_1, follows its name in mail and on the cart as line.options.

A field with owners: true, such as stage: {type: select, options: [Pending, Shipped, Done], default: Pending, owners: true, in_list: true}, is set by the owners on each order and never by a visitor.

Pages

  • Moneyis kept in cents, 1250 for €12.50, and a page writes it with formatMoney: {v.price.formatMoney('EUR')}.
  • A product listreads the lowest price with content.products.with("min(.variants.price) as from_price"), and sorts by it with .order("min(.variants.price)").
  • A product's pagelists its variants with content.variants.where("product", item). Its add-to-cart form, <form data-fp-cart="orders">, has a <select name="variant"> of their ids and a quantity.
  • Every pagereads the cart as forms.orders.cart: count, lines (each with quantity, name, options, total and the row it points to) and total.
  • The cart pageholds the order form, <form data-fp-form="orders">, with the buyer's fields. It lands back on the page with forms.orders.sent, and the cart empties.

Trying it

The editor's canvas shows an empty cart: it cannot keep the cart's cookie. Open the draft, in the menu beside Publish, opens it in a tab of its own, where adding to the cart works and the cart fills. Sending an order works only on the live site.

The confirmation mail

Without a mail of its own, each buyer gets Fairpage's: the site's icon, the lines and the total. _fp/email/orders.x.html is the site's own, written like a page with no layout: it reads entry (the order's fields, its lines and total) and site (name, url), and its <title> is the subject. It takes no <style> (write style= on each element), no {@html} and no written address: links are built from site.url. A mail that links anywhere else, or that Fairpage's check flags, goes in Fairpage's design instead.

Not answered here?

A person at Fairpage replies on the request’s page, and by email: within one business day on Plus, two on Lite.

Write to support