Themes

A whole storefront look in one step: every page laid out with sections your store owns, colours, typefaces, pictures, menus and starter pages.

A theme is a finished storefront look you give your store in one step: its header, its footer and its pages laid out with their own sections, their words, colours and typefaces, placeholder pictures, menus and sometimes a few starter pages. Every theme is made of sections your store owns, so once it is applied, everything in it is an ordinary part of your draft that you (or your agent) can change.

Picking a theme changes your draft only. Nothing a shopper sees changes until you publish the storefront.

Where to find them

  • Dashboard: Online Store → Storefront settings → Design (also reached from the canvas editor's Choose a theme and from the last step of setting up a store). One list, filtered by kind of shop (fashion, food and drink, beauty, home and gifts, tech, starters). Each card shows a picture of the theme's home page, its name, its kind and one line about it. The theme your draft wears is marked Current.
  • Preview opens a large view: the home page on a computer and on a phone side by side, the pages the theme lays out and what it needs from you.
  • Use this theme asks your store what applying would change, then asks you once in a dialog. If you have unsaved changes on the screen, the dialog offers Save changes and use this theme or Discard changes and use this theme. Afterwards the dashboard says what happened and offers Open editor.
  • Only owners and admins can change the theme; for anyone else the button says Ask an owner or admin. In test mode the theme goes into your test store's draft.
  • Agents: list_themes, get_theme { id }, and the set-theme command in apply_storefront_commands (For agents below). Use the id that list_themes returns.

See a theme before you pick it

Every theme has its own page on formahand.com/themes, linked from the table in The themes below. It shows the home page on a computer and on a phone, the pages the theme lays out and who it suits.

  • Open the demo opens a live demo store wearing the theme, with sample products. Click through it as a shopper would: the catalog, a product, the cart. Checkout is closed in a demo, so nothing can be bought.
  • Use this theme on the theme page, or in the bar along the top of the demo, takes you to your dashboard with the theme chosen (or to sign up first), and you confirm there.

An agent finds the same demo in demoUrl, one per theme in list_themes (null when a theme has none).

The kinds of theme

  • The six original themes (Bold Street, Luma, Corner Pantry, Noir, Gridline, Warm Roast) bring their own header, footer and home page as sections your store owns. Picking one keeps what is yours: your colours, typefaces and copy follow the theme rules, your stylesheet is kept with the theme's spacing and corner tokens in front of it, a menu that has links is kept, and your hero image goes onto the theme's hero section.
  • The design themes (Rounded Edit, Sage Apothecary, Pale Studio, Quiet Wardrobe, Fitting room, Checkerboard Aperitif, Garden Room) are whole looks: their own colours, typefaces, stylesheet and menus, and most lay out the product, catalog and cart pages too.
  • The starters: Clean grid and Editorial promo are simple whole looks; Blank canvas is a blank start, plain sections you fill in yourself.

Your code is never overwritten. If your store already has sections with a theme's ids (you picked it before, and may have changed them), they are used as they are, at their own versions, and the answer says so (sections.reused). To get the originals back, apply it with apply_preset { id, reset: true }: each original is saved as a new version of its section, so your version stays in the section's history. A store that is on one of the original themes today keeps its home page until you pick a theme: nothing changes on its own.

What applying does

Part of your draftWhat happens
Colours, typefacesA design theme or starter brings its own; an original theme keeps yours
Your stylesheetReplaced by a design theme's (its radius and spacing tokens, then its own CSS); an original theme keeps it
Every page's layout and the header and footer slotsReplaced by the theme's, with its sections at the versions it was made with
Header and footer menusReplaced by the theme's (an original theme keeps a menu that has links)
Store modulesOnly the ones the theme names (modules), such as the "Shop by collection" grid a design leaves out: switched on or off as the theme says. The answer lists them (modules); set-module changes them back. Custom HTML and add-on blocks are never touched
Starter pagesAdded only where you have no page with that address; your own pages are never touched
Your own sectionsKept. Each instance moves to the end of the page it was on, hidden, and the answer lists them. Show one again with set-section-visibility. A page body section of your own (product, catalog or cart) is the exception: a page has one body, and the theme's page brings its own, so yours comes off that page and stays in your store (unplaced); put it back in place of the page's body whenever you like
Custom HTML blocksKept the same way, hidden at the end of their page
Store name, heading, intro, logo, tab icon, social links, hero image, page copy, embedsKept
Products, collections, orders, customersNever touched

The theme's sections are added to your store and listed by list_sections, like any section. Some themes bring read-only sections (fork_section makes your own copy); the original themes and Blank canvas bring sections that are your store's own from the moment you apply them, so you (or your agent) change them with save_section and Formahand never updates them. Its pictures and drawings are added to your media library, so every image setting points at your own /media/ path; replace them with your photographs whenever you like. A picture is either a neutral shape in the theme's colours or one that comes with the design. Applying the same theme again keeps one copy of each picture in your library, not two.

Typefaces. A theme either picks one of the store's font pairings (the same list as Brand in Storefront settings) or brings the design's own heading and body typefaces, chosen from the section font list. With its own, your store's typefaces become Your own typefaces: every page loads the two families once, and the headings and text follow them, catalog, product and cart pages included. Choosing another pairing in Brand, or set-fonts with another pairing, puts them aside; set-fonts { pairing: "custom", headingFamily, bodyFamily } changes them, each an exact name from the font list (describe_sections, part fonts). Each family loads 400 to 700; a theme that names other weights (weights: [300, 400]) or italic: true for a family loads those too, at most six weights, and set-fonts takes headingWeights, bodyWeights (any weights the family has, at most six; [] goes back to 400 to 700), headingItalic and bodyItalic.

Undo. Before anything changes, the draft as it was is saved in the version history (the dashboard shows it as "Before theme <name>"; list_storefront_versions names it "Before preset <name>"). Restoring it (restore_storefront_version, or Version history in Storefront settings) brings the draft back exactly, sections, pins and all.

Picking a second theme replaces the first one's look and sections on your pages (the first one's sections stay in your store), and keeps your own sections as above. Picking the same theme again starts its pages over, with the sections your store already has.

A dry run (apply_preset { id, dryRun: true }, or the first step of Use this theme in the dashboard) answers with everything above for your store (what would be replaced, which of your sections would be kept and where, which starter pages would be added or skipped) and writes nothing. It needs only the read scope.

For agents

One word: a look is a theme, and there is one way to pick one. A theme's id is an identifier to pass back, not a name to show: tell the merchant the theme's name.

  1. list_themes: every theme, { id, name, category, line, pages, preview, phone, licence, current?, demoUrl }, with current naming the one the draft wears. preview and phone are pictures of its home page. demoUrl: a hosted demo store of the theme, open to visitors, or null. licence: the machine licence fields, for your records; credits are shown to people on formahand.com/credits only.
  2. get_theme { id }: one theme whole: its line, pages and pictures, then its sections (summarised), every page's instances with their settings, the pictures, menus, starter pages and licence.
  3. apply_storefront_commands { revision, commands: [{ type: "set-theme", presetId: "<id>" }] }, with the id that list_themes returns: picks it, in one write with the rest of the batch. The answer's theme is { id, name, preset, sections, summary }, and theme.summary is also the first of notes. For a design theme or a starter the rest of the batch is applied right after, on the new revision; if one of those commands is refused, the theme is already in the draft and the refusal says so (themeApplied, revision).
  4. Adjust: update-section for words and pictures, set-colors, set-fonts, set-section-visibility; replace the placeholder pictures with the merchant's own (upload_image, then update-section).
  5. get_preview_link, then publish_storefront { revision }.

get_store answers theme: { id, name }, the theme the draft wears as list_themes names it (themePresetId is the older field and names the original theme a design builds on).

Older names. list_presets, get_preset { id } and apply_preset { id, dryRun?, revision?, reset? } still work and read the same catalogue; apply_preset is how to ask for a dry run or a reset. Every id works in all of them: the id from list_themes or the one list_presets returns. apply_preset answers { applied, revision, summary?, replaced, kept, replacedInstances, notKept, unplaced?, modules?, contentPages: { added, skipped }, stylesheetReplaced, sections: { ids, reused, restored }, imagesUploaded, notes, next }. A read-only theme section is named <theme>--<name>, which your own sections cannot be, so it never takes one of your ids. A section in the way that came from an add-on is refused (preset_conflict) and nothing changes: make a copy of it under another id first.

Starting a design from nothing. set-theme { presetId: "blank-canvas" } is where an agent starts when it rebuilds a storefront. It takes the home sections off the page and places plain starter sections instead: a hero (heading, text, button and picture in a group the merchant can reorder), a product grid (choose its collection with update-section { instanceId: "shop", settings: { collection: "<handle>" } }; until then it shows its heading and a link to every product), a text and picture band, questions and answers, a newsletter sign-up, and a header and footer. Every heading, text, button and picture in them is marked, so the merchant can select and change it in the builder. They are ordinary sections of your store (canvas-hero, canvas-products and so on): change them with save_section, or replace them with your own.

The apply-preset editor command exists so the draft's history is honest, but it only runs through apply_preset and set-theme, which add the sections and pictures first. Sent on its own to apply_storefront_commands it is refused with that sentence.

The themes

Sixteen themes, by name. Each name links to its page, with pictures and the live demo.

ThemeKindLook, pages and typefaces
Bold StreetFashionBold black type, a big hero with your newest product and grey product tiles. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: the theme's own.
LumaHome and giftsCalm and minimal: a thin header, a tall hero and roomy product rows. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: the theme's own.
Corner PantryFood and drinkA playful pantry look in orange and cream with a big serif hero. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: the theme's own.
NoirFashionSleek and dark, with a three-tile product grid and a scrolling row. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: the theme's own.
GridlineTechPrecise and product-first: a full-width hero and tidy product cards. Lays out: product page, catalog, cart, home page, header, footer and checkout. Typefaces: the theme's own.
Warm RoastFood and drinkA warm coffee-roaster look with a story band and an olive footer. Lays out: product page, catalog, cart, home page, header, footer and checkout. Typefaces: the theme's own.
Rounded EditFashionClean and white, with big rounded picture cards and black pill buttons. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: Inter.
Sage ApothecaryBeautySage and cream for beauty and wellness, with a light serif headline. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: Fraunces and Red Hat Text.
Pale StudioFashionPale and sharp: heavy capitals, round black buttons and a picture band. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: Schibsted Grotesk.
Quiet WardrobeFashionBlack and white, with full-width pictures and small light type. Lays out: home page, product page, catalog, cart, stores page, faq page, blog, post, header, footer and checkout. Typefaces: Sora.
Fitting roomFashionWarm stone colours, tall condensed capitals and one product shown large. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: Bebas Neue and Manrope.
Checkerboard AperitifFood and drinkA bold drinks look: a huge wordmark, a checker border and caramel blocks. Lays out: home page, product page, catalog, cart, about page, find us page, header, footer and checkout. Typefaces: Staatliches and Geist.
Garden RoomHome and giftsA bright florist look with a huge rounded name and yellow buttons. Lays out: home page, product page, catalog, cart, gallery page, about page, header, footer and checkout. Typefaces: Outfit.
Clean gridStartersWhite space, one split hero and a tidy product grid. Lays out: home page, catalog, product page, about page, faq page, cart, header and checkout. Typefaces: Modern.
Editorial promoStartersWarm and magazine-like, with a picture-led opening and an offer band. Lays out: home page, catalog, product page, our story page, shipping page, cart, footer and checkout. Typefaces: Editorial.
Blank canvasStartersA blank start: plain sections you fill in with your own words and pictures. Lays out: home page, product page, catalog, cart, header, footer and checkout. Typefaces: Modern.

Brand identity

Your brand is yours on every theme. It is part of the draft, so a new logo reaches shoppers when you publish, not before. Every part is optional: a store that never sets one looks exactly as its theme does.

WhatCommandWhat it does
Logoset-logoThe header shows your logo instead of the store name as text, 40 to 320 px wide and never taller than the header. The same logo appears in your store's emails and on packing slips.
Tab iconset-faviconThe icon in the browser tab: a square PNG. Every store already has one, the first letter of the store name on your accent colour.
Typefacesset-fontsOne of the store's font pairings, the theme's own (the default), system fonts only, or your own two families from the font list.
Coloursset-colorsBackground, accent, text, muted text and border. The text colour has to be readable on the background (4.5 to 1 or better); the refusal says the ratio and which way to move.
Social linksset-socialInstagram, Facebook, TikTok, X, YouTube, Pinterest and LinkedIn profile addresses, shown as small marks in the footer.
"New" badgeset-badgesHow many days a new product wears a "New" badge. 0, the default, turns it off.

In the dashboard this is the Brand card in Online Store → Storefront settings; its Save & publish ships it. Agents upload a logo or an icon with set_logo and set_favicon, which upload the file to your media library and set it in the draft; the other parts go through apply_storefront_commands.

What a theme change keeps. A colour you chose yourself is yours and stays on every theme. A colour you never changed belongs to the old theme and goes with it, so the store simply looks like the new theme. The one exception is readability: a text colour of yours that cannot be read on the new theme's background is dropped, and the answer says so in notes.

Page layout

Every page is an ordered list of sections and custom blocks. The home page holds the theme's home sections; the catalog, product and content pages each have one body section, the page itself, with blocks before or after it. The header and footer slots hold custom blocks shown on every page except the payment page.

  • set-layout { page, order } or set-layout { slot, order } puts a page or a slot in the order you give.
  • move-section moves one section; the block commands take a position.
  • In the builder, drag sections and blocks up and down the page. A theme section can be hidden or removed; a page must keep at least one visible section or block.

Agents and API has every command with its fields.

Element editing

Sections are what you move; elements are what you edit: one heading, text, button, link or picture inside a section. Click one in the builder and a small toolbar offers its words, link or picture, and how it looks: alignment, size, spacing and whether it shows. Escape deselects; the arrow keys change the spacing.

Agents do the same with two commands:

  • set-element { areaId, key, value } changes an element's words, link or picture.
  • set-element-style { areaId, key, align, size, visible, spacing } changes how it looks: align is left, center or right, size is s, m, l or xl on the theme's own type scale, spacing is 0 to 4 steps of the theme's spacing.

A theme offers only the knobs its design can honour, so a control that is missing is one the theme does not have. Sections your store owns mark their own elements, and can also let the merchant move an element (set-element-order) or nudge it on a phone: sections has the rules and a complete example, and add-custom-block puts your own HTML at a section boundary (custom code).

Content pages and menus

You write pages (refund, shipping and privacy policies, terms, contact, about) in the dashboard under Content, in Markdown: headings, paragraphs, bold and italic, lists, quotes, rules and links. Every theme shows them in its own type at /pages/<address>. A draft page shows nobody; published pages are listed in your sitemap. Some addresses are kept for the store itself (home, products, cart, checkout, collections, pages, api, sitemap.xml, robots.txt) and are refused.

Menus hold up to 12 header links and 20 footer links, each a path on your store or an https: address. A theme brings its own menus until you set yours.

Who owns a page. The Content screen is the record. The builder shows the same pages and menus, and what it changes on a page that is already live is saved to that page at once. A page you add in the builder waits for publish. Publishing adds the new pages and links and removes the menu links you took out; it never rewrites or deletes a live page (you delete pages on the Content screen). An open builder tab that is out of date is refused rather than allowed to overwrite a newer page: reload it and try again. A store holds up to 60 pages (120 KB of text in all).

Every store's Contact page carries a form. With a public support address set, a message goes to that address with the shopper's address to reply to; without one, it comes to the account holder with a reminder to set one.

Shopping pages

Every theme lays out the same shopping journey:

AddressPage
/Home: its sections, in your order
/collections/allEvery product
/products/<address>One product: quantity, Add to cart, Buy now and related products
/cartThe cart and its checkout
/pages/<address>One of your content pages
/orders/trackTrack your order, by order number and email

Old addresses such as /products, /shop and /catalog lead to /collections/all, and a redirect of your own (content and SEO) wins over them. An address that does not exist shows the theme's own "not found" page.

  • Filters, order and paging. Catalog, collection and search pages filter by tag, option, brand, product type, availability and price, 24 products a page. A filtered page is one link a shopper can share. A collection keeps the order you arranged unless you set another.
  • Related products. Under a product: your own picks for it (up to 8), else products from the same collection, then with the same tags, then the newest. Under the cart, "Add to your order". A sold-out product is never suggested.
  • Prices on a card. "From" shows only when a variant really costs less; a sale shows the old price struck through.
  • For every shopper. Every theme shows a clear focus ring for the keyboard, a link to skip to the content, and no movement for shoppers who asked their device for less.

The theme format

Themes are data, never code: every part is checked with the same rules your own sections and drafts are. The format is the one the catalogue is written in.

FieldWhat it holds
schemaVersionAlways 1: the version of the preset format.
id2 to 32 lower-case letters, digits and single hyphens, starting with a letter.
nameWhat the gallery shows, at most 60 characters.
descriptionOne or two sentences on the look, at most 400 characters.
categoryminimal, editorial, bold, playful, luxury or general.
versionLike 1.4.0. A store records the version it applied.
authorWho made the preset: { name, url? }.
origincatalogue for the presets Formahand offers every store.
licence{ name, url, attribution }. attribution is the credit the licence asks for, in the licence's own words (at most 200 characters). It is listed on formahand.com/credits, never on a theme card, a theme page or in these docs.
baseThemeThe theme whose own catalog, product and cart pages, header and footer the preset builds on.
brandThe look: typefaces { pairing, heading?, body? } (pairing is one of the store's font pairings, or custom: the design's own heading and body { family, weights, italic? } from the font list, which the storefront loads, in those weights on top of 400 to 700 and at most six, and the theme's type follows), colours { background, accent, text, muted, hairline }, radius { s, m, l } and spacing { s, m, l } in pixels. The text colour has to be readable on the background.
customCssTheme-level CSS under the custom CSS rules. The radius and spacing scales go first as --fh-radius-s
sectionsThe sections the preset brings, at most 16: whole section packages, each either origin catalogue with the id <preset>--<name> (read-only in the store, updated with the preset) or origin store with an ordinary id (the store's own code from the moment it is applied, never updated by Formahand). Every section in the catalogue marks its elements, so each one is editable in the builder.
layoutEvery page (home, catalog, product, cart, page:<slug>) and slot as an ordered list of instances with their settings, the pins of the bundled sections at their bundled versions, and any sections switched off. The same layout a draft has.
mediaImages, at most 64: { key, alt, width, height, role (hero, product, lifestyle, logo, icon), placeholder }. placeholder: true is a neutral image drawn in the preset's colours. placeholder: false is a picture or a drawing that comes with the design under a licence that lets it be passed on, and then needs licence { name, url?, attribution } and source (theme-artifacts/<path> or the preset's media/<file>: a .png, .jpg or .webp copied as it is, at most 1024 KB, or an .svg drawing, at most 256 KB, checked and written out again by the drawing rules; its width and height the file's own). A setting names either as /media/preset/<key>.png, whatever the file's type.
navigationThe header and footer menus: { header: [{ label, href }], footer: [...] }.
modulesStore modules the design switches on or off, by module id (list_modules), each a part of that module's settings: { "collection-grid": { "enabled": false } }. Custom HTML and add-on blocks are the store's own and cannot be set.
contentPagesStarter pages, at most 12: { slug, title, bodyMarkdown, status }.
previewSketches of each page kind, drawn from the layout. The Themes gallery and list_themes show real pictures of the home page instead.

A theme is refused unless every bundled section passes the section checks, every instance names a section the theme brings (or a built-in one) on a page that section may sit on, every instance's settings fit its section, the pins name exactly the bundled sections at their bundled versions, every placeholder a setting names is in media, and the text colour is readable on the background.

Limits

LimitValue
Sections one preset brings16
Images64
One placeholder image256 KB
One licensed image (placeholder: false)1,024 KB
One drawing (.svg)256 KB
Every image of one preset together16,384 KB
An image's width or height4 to 2,400 px
Starter pages12
Stylesheet, tokens included64 KB
Preview pictures besides the thumbnail6
What get_theme answers24 KB

Refusals

One sentence per problem, starting with the theme, then the section, page, instance and setting it is about: Preset clean-grid, Section clean-grid--products, instance related on page product, setting count: use a number of at most 12.

CodeMeaning
preset_invalidThe preset does not match the preset format.
preset_section_invalidA bundled section fails the section checks.
preset_section_idA bundled section's id does not start with the preset's id, or is used twice.
preset_layout_invalidThe layout breaks a page rule, or names a section the preset does not bundle.
preset_setting_invalidAn instance's settings do not fit its section.
preset_pin_invalidA pin does not name a bundled section at its bundled version.
preset_media_missingA setting names a placeholder image the preset does not carry.
preset_contrastThe text colour cannot be read on the background.
preset_limitThe preset is over one of its limits.
preset_not_foundNo preset with that id is in the catalogue.
preset_conflictYour store has a section of its own with a bundled section's id.

Credits and licences

Every theme carries a licence. Credits for the designs the themes are based on, and for every picture that comes with them, are on one page: formahand.com/credits, linked from the footer of every page. Theme cards, theme pages and these docs carry none. Themes Formahand makes say so. Placeholder pictures are ours and free to use; replace them with your own photographs before you open the store.

A picture that comes with a design is a media entry with placeholder: false, its licence and its source; get_theme shows each one's licence, and formahand.com/credits lists it. It is still yours to replace with your own photograph.

A drawing (an icon, an illustration) is an .svg file and is shown like any picture. Drawings are checked strictly, in the catalogue and again by your store when one is uploaded: a drawing may hold shapes, gradients, clipping, masks and filters, and nothing else. No script, no styles block, no event attributes, no embedded pictures or pages, no text elements (convert text to outlines), and no address of any kind except a reference to a part of the same drawing. One that is not clean is refused with what to remove, never repaired silently, and your store serves every drawing locked so that opening one on its own can run nothing.