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.
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: falseon 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'soption_name, a text field, and the owners add values there as chips. Avalue_2withlabel_from: option_2_nameis 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'sgallerylist, whose items have one image.old_price: {type: number, format: money, currency: EUR, in_list: true, when: on_sale}shows only while the product'son_salecheckbox 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 aquantity. - Every pagereads the cart as
forms.orders.cart:count,lines(each withquantity,name,options,totaland the row it points to) andtotal. - The cart pageholds the order form,
<form data-fp-form="orders">, with the buyer's fields. It lands back on the page withforms.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.
Fairpage