Overview#
Roast is a shop for a specialty coffee roaster, built as a WordPress block theme. The fictional
brand is First Crack, a roaster in an old tram depot in Baltimore, Maryland. The theme has a home
page with this week's roasts, a roast finder, a subscription teaser, brew guides and reviews; a shop
with roast, origin and process filters; product pages with bag sizes, grinds, a tasting profile and
a brew recipe; a subscription builder that shows the price per cup and the next delivery dates; a
cart drawer; a three-step demo checkout; brew guides with a recipe scaler; a wholesale page with a
volume estimator and an enquiry form; a sourcing page; a contact page with an FAQ; and a 404 page.
It is version 1.0.0 (see template.json and style.css), works with WordPress 7.1 and PHP 7.4 or
newer, and is the WordPress version of the HTML template of the same name. See it live at
freeframe.dev/templates/roast.
The pages around the shop (headings, copy, roast cards, reviews, the sourcing and contact pages,
buttons) are core WordPress blocks arranged in block patterns, so you edit them in the block editor
without touching code. The shop itself works as in the HTML version: the coffees are one JavaScript
list in assets/js/main.js, and the script draws the coffee cards, the product page, the cart,
the subscription prices and the checkout from it. It is a storefront for a demo or a prototype; to
take real orders, see Checkout. Colours and fonts are design tokens in theme.json:
change them in Appearance > Editor > Styles and the whole site follows.
Quick start#
Requirements: WordPress 7.1 or newer and PHP 7.4 or newer. No plugins are needed.
- Download
roast.zipfrom freeframe.dev/templates/roast (the WordPress tab). - In your WordPress admin go to Appearance > Themes > Add New Theme > Upload Theme, choose the zip and click Install Now, then Activate. The theme is listed as Freeframe Roast.
- Go to Appearance > Roast setup and click Create the demo pages. This creates the Home, Shop coffee, Product, Subscribe, Checkout, Brew guides, Wholesale, Our sourcing and Contact pages from the theme's page patterns, sets Home as the front page (Settings > Reading) and creates the header menu. Pages that already exist with the same slug are left alone, so it is safe to click it again.
- Visit your site. Edit any page in Pages, and the header, footer and templates in Appearance > Editor.
You can also try the theme without installing anything: the Try it in WordPress button on freeframe.dev opens it in WordPress Playground (WordPress running in your browser) with the demo pages already set up.
To work on the theme's files locally you need Node.js 24 and pnpm; WordPress itself runs in WordPress Playground, so there is no PHP, web server or database to install:
pnpm install
pnpm dev # builds the CSS, then starts WordPress with the theme at http://127.0.0.1:9400pnpm dev signs you in as admin (password password) and creates the demo pages. The site is
rebuilt from scratch every time you start it; your edits to theme files are live, edits made in the
WordPress admin are not kept.
Pages#
Each page is a page pattern (in Patterns > Roast pages) made of section patterns. Every section is also offered on its own in the block inserter under Patterns > Roast.
| Page | Slug | Page pattern | Sections (pattern files in patterns/) |
|---|---|---|---|
| Home | / |
page-home.php |
home-hero (with bag art), ticker, featured-roasts (coffee cards), find-your-roast, subscription-teaser, brew-teaser, sourcing-stats, reviews |
| Shop coffee | /shop/ |
page-shop.php |
shop-hero, shop-catalogue (filters, sort and coffee grid), shop-promises |
| Product | /product/?id=kochere |
page-product.php |
product-breadcrumb, product-details (gallery, size, grind, add to cart), product-info (tasting profile, origin, brew recipe), related |
| Subscribe | /subscribe/ |
page-subscribe.php |
subscribe-hero, plan-builder (the five steps and the plan summary), subscribe-start (sign-up form) |
| Checkout | /checkout/ |
page-checkout.php |
checkout-header, checkout-done (confirmation), checkout-empty, checkout-main (steps and order summary) |
| Brew guides | /brew/ |
page-brew.php |
brew-hero, brew-guides (method tabs and recipe scaler), brew-cta |
| Wholesale | /wholesale/ |
page-wholesale.php |
wholesale-hero, wholesale-benefits, wholesale-pricing (price table and estimator), wholesale-enquiry |
| Our sourcing | /about/ |
page-about.php |
about-hero, how-we-buy, prices-paid, producers, visit-cta |
| Contact | /contact/ |
page-contact.php |
contact-hero, contact-form (form, roastery hours, other contacts), faq |
| 404 | any missing URL | templates/404.html |
404 |
The script finds the shop, product, subscription, checkout and brew guide pages by their slugs
(shop, product, subscribe, checkout, brew): if you rename one, change its URL in
freeframe_roast_page_urls() in inc/setup.php too. Posts use templates/single.html; the blog,
archives and search results use templates/index.html, templates/archive.html and
templates/search.html.
Project structure#
freeframe-roast/
style.css theme header (name, version, requirements, license); no styles
theme.json design tokens: palette, fonts, font sizes, spacing, layout widths, button
functions.php loads the files in inc/
inc/setup.php stylesheet and script (with its strings and page URLs), editor styles,
the `js` class script, pattern categories
inc/icons.php registers assets/icons/*.svg for the Icon block
inc/icon-labels.php the icons' names shown in the editor
inc/block-styles.php button block styles
inc/site-setup.php Appearance > Roast setup: creates the demo pages and the menu
templates/ page.html (pages), page-with-title.html, single.html, index.html,
archive.html, search.html, 404.html
parts/ header.html and footer.html (they show the header and footer patterns)
patterns/ every section and page (PHP files with block markup)
assets/css/theme.css the compiled stylesheet (do not edit: built from src/)
assets/css/editor.css the same for the block editor (generated by src/editor-css.mjs)
assets/js/main.js the shop: coffees, bag art, cart, subscription, checkout, brew guides, forms
assets/icons/ SVG icons for the Icon block
assets/img/ logo, favicon, social image
assets/fonts/ Unbounded and Onest, with their licenses
src/theme.css the Tailwind CSS source of assets/css/theme.css
src/icons.css icons drawn before or after text with CSS (generated)
src/editor-css.mjs writes assets/css/editor.css after each build
languages/ freeframe-roast.pot, the template for translations
blueprint.json WordPress Playground setup used by `pnpm dev`
screenshot.png the picture shown in Appearance > Themes
package.json the CSS build and the local WordPress (Node.js tooling)
readme.txt, README.md, DOCS.md, CHANGELOG.md, LICENSE.txtCustomising#
Brand and colours#
The colours are in theme.json (settings.color.palette) and in Appearance > Editor > Styles >
Colors > Palette:
| Colour | Default | Used for |
|---|---|---|
| Butter | #fff6df |
the page background, text on dark |
| Cream | #fffcf4 |
cards and fields |
| Oat | #f6e9c8 |
soft panels, page headers |
| Line | #e3d5b3 |
hairlines |
| Sun | #ffcd4a |
stickers, highlight bands, the second button style |
| Cobalt, Cobalt dark | #2338b5, #18268a |
the brand: hero bands, primary buttons, links |
| Sky | #d9e0ff |
selected options, info panels |
| Navy | #141a3c |
text, outlines and the offset "sticker" shadows, the footer |
| Muted | #4b4f6e |
secondary text |
| Tomato, Tomato dark | #e0522f, #b03417 |
decoration; the dark shade for text (stars, errors, the cart badge) |
| Leaf | #23714a |
success messages and savings |
| White, Black | for your own blocks |
The theme's stylesheet reads these colours from the palette (bg-cobalt, text-muted...), so
changing Cobalt in Styles recolours every brand surface at once. The bag artwork draws its own
colours: each coffee's bag colour is in the coffee list (assets/js/main.js).
Typography#
Two fonts are bundled in assets/fonts/ and declared in theme.json
(settings.typography.fontFamilies), so no request goes to Google: Unbounded (variable, 500 to
800; preset display) for headings, prices and labels, and Onest (variable, 400 to 700; preset
sans) for text. To use other fonts, install them in Styles > Typography > Fonts (the Font
Library) and select them, or replace the fontFace entries in theme.json. The utility classes
read the presets (--wp--preset--font-family--display, --sans), so keep those slugs. The bag
labels in the SVG art name the fonts directly (font-family="Unbounded, …" in art()).
Font sizes are the presets in theme.json (xs 0.75rem to 9xl 8rem, the Tailwind scale).
Content#
Edit pages in Pages: click any text to change it, select a button to change its link. Sections are groups; open List View (the stacked lines icon at the top left) to select a section, move it, duplicate it or delete it. To add a section from another page, use the block inserter (+) > Patterns > Roast.
What the shop script draws or fills is in Custom HTML blocks: edit those in the block's HTML
view, and keep their ids and data- attributes.
| Pattern | Custom HTML | What it is |
|---|---|---|
home-hero |
the two linked bags (<a data-art="kochere">) |
bag illustrations, see Images and artwork |
ticker |
the scrolling tasting notes | the second copy is aria-hidden so screen readers read it once |
featured-roasts, related |
the coffee grid | coffee cards from the coffee list |
shop-catalogue |
the filters, the result bar, the grid, the empty state | see Shop filters |
product-breadcrumb, product-details, product-info |
the breadcrumb, the gallery and buy box, the three info cards | filled from the coffee in the URL |
plan-builder |
the five steps and the plan summary | see Subscription builder |
checkout-done, checkout-main |
the confirmation details, the checkout steps, the order lines and totals | see Checkout |
brew-guides |
the method tabs, their panels and the recipe scaler | see Brew guides |
wholesale-pricing |
the price table and the estimator | see Wholesale estimator |
about-hero |
the globe illustration | decorative SVG |
subscribe-start, wholesale-enquiry, contact-form |
the forms | see Forms |
header, footer |
the menu and cart buttons, the footer newsletter form, the cart drawer and the toast | driven by the script |
A few blocks carry a class (Block settings > Advanced > Additional CSS class(es)) that the script or stylesheet reads:
ff-hiddenhides a section until the script decides to show it (the checkout confirmation and empty-cart states, the mobile menu). In the editor these sections are shown with a dashed outline.revealfades a block in as it scrolls into view.link-cardon a group makes the whole group clickable: the first link inside it stretches over the group (the roast cards on the home page, the logo).carddraws the template's outlined card with its offset shadow;stickerthe yellow label;eyebrowthe small blue heading above titles.
The coffee list
Coffees are the COFFEES list at the top of assets/js/main.js. Each coffee looks like this:
{
id: 'kochere', name: 'Kochere Lot 7', origin: 'ethiopia', region: 'Yirgacheffe, Gedeo zone',
process: 'washed', roast: 'light', price: 21, rating: 4.9, reviews: 312, badge: 'New harvest', featured: 1,
notes: ['Jasmine', 'Bergamot', 'White peach'], profile: { acidity: 5, sweetness: 4, body: 2 },
producer: 'Worka Sakaro washing station', altitude: '1,950–2,150 m', variety: 'Ethiopian landraces', harvest: 'December 2025',
bag: '#f4a6c4', brew: 'v60',
blurb: 'Tea-like and floral, with a long peach finish…'
}| Field | Notes |
|---|---|
id |
Unique, used in /product/?id=… (any letter case) and in saved carts. Changing an id drops it from visitors' carts |
origin, roast, process |
Keys of ORIGINS, ROASTS and PROCESSES; to add an origin, add it there and a checkbox to the shop filters' Custom HTML |
price |
The 250 g price in dollars. The other bag sizes are price × factor from SIZES (500 g × 1.85, 1 kg × 3.4), rounded to whole dollars |
profile |
Acidity, sweetness and body from 1 to 5 (the tasting profile bars) |
bag |
The bag colour in the artwork |
brew |
A key of METHODS (v60, aeropress, french, moka, cold, espresso): the recipe shown on the product page |
badge |
Optional label such as Bestseller or Limited |
featured |
Optional; coffees with it appear in "This week's roasts", sorted by the number |
Shop settings sit just below the list: SIZES, GRINDS, FREE_SHIPPING (45), SHIPPING
(standard $6, express $12, pick-up free), MAX_QTY (20), the subscription settings (STYLES,
SUB_DISCOUNT 10%, DOSE 15 g a cup, FREQUENCIES, MAX_BAGS, ROAST_DAY, DELIVERY_LAG) and
the brew METHODS. Prices are formatted with Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }). The "Free shipping over $45" announcement bar (header pattern), the shop and
FAQ copy and the delivery options' descriptions are plain text, so update them when you change the
settings; the prices themselves are always worked out by the script.
Edit assets/js/main.js in a child theme (copy it there and load it instead), or your coffees are
overwritten when you update the theme. Coffee names, notes and descriptions are data, not
translatable strings.
Images and artwork#
Every coffee picture is drawn by art(coffee, view) in assets/js/main.js: view 0 is the bag
(its colour, a label with the origin, process and a roast mark: a sun, waves or a moon) and view 1
the roasted beans. Place art anywhere with a Custom HTML block:
<div class="art aspect-[4/5] overflow-hidden rounded-3xl border-2 border-navy" data-art="gatomboya" data-view="1"></div>Add data-decorative to hide it from screen readers. To use photos instead, add an image field
to each coffee and return an <img> from art(). The logo is assets/img/logo.svg in an Image
block next to the Site Title block in the header and footer patterns; the name comes from
Settings > General > Site Title. Icons are Icon blocks: select one and pick another from the
Roast collection or WordPress's own. The social image is assets/img/og-image.png
(1200 × 630, source og-image.svg); the favicon assets/img/favicon.svg is used until you set a
Site Icon in Settings > General.
Navigation, header and footer#
The header and footer are template parts (parts/header.html, parts/footer.html) showing the
header and footer patterns. Edit them in Appearance > Editor > Patterns > Header / Footer.
The header pattern starts with the announcement bar.
The header has two Navigation blocks showing the same menu: the desktop one and the one in the
mobile menu. Edit the menu once in Appearance > Editor > Navigation (the setup creates "Main
menu"). Its last link (Contact) is hidden in the desktop header, which has its own Contact
link; keep Contact last, or remove the .site-nav … :last-child rule in src/theme.css. A
Navigation block that doesn't point at a menu shows the most recently created one; to pin a menu,
select the Navigation block and choose it in the block settings, for both blocks.
The footer's Coffee and Help menus and social links are List blocks: click a link to change it,
press Enter to add one. The social links point to #; replace them with your profiles.
Features#
Cart drawer#
The cart is saved in localStorage and synced across tabs. Every element with data-cart-open
(the cart button in the header, "View cart" in the toast) opens the cart drawer; coffee cards add a
250 g whole-bean bag with their "Add 250 g" button. The drawer lists each line with its size, grind
and unit price, a quantity stepper (1 to MAX_QTY) and Remove, shows the free-shipping progress
and the subtotal, traps focus, closes with Escape, the close button or the backdrop, and returns
focus to where it was. Without JavaScript the cart button goes to the checkout page.
Shop filters#
The shop filters by roast, origin and process (checkboxes with counts; any within a group, all
groups together) and sorts by featured, price, roast or name. The count is announced, active
filters show as removable chips, and the state is kept in the URL (/shop/?roast=light,medium&origin=ethiopia&sort=price-asc)
so filtered views can be linked, as the footer does. Parameter names and values are read in any
letter case and anything that isn't one of the shop's own values is ignored. On small screens the
filters fold behind a Filters button.
Product page#
/product/?id=gatomboya shows that coffee (an unknown or missing id shows the first one). The page
title, breadcrumb, tasting notes, profile bars, origin details and brew recipe fill from the coffee.
Bag sizes show their prices, the grind is a select, the quantity stepper is limited to 1–20, and
the add button shows the line total. Two thumbnails switch between the bag and the beans. "Build a
plan" links to the subscription builder with the matching style. Related coffees prefer the same
roast.
Subscription builder#
The builder has five steps: style (STYLES), bag size, bags per delivery (1 to MAX_BAGS), how
often (FREQUENCIES, in weeks) and grind. The summary shows each choice with a Change button
(which scrolls to and focuses that step), the price per delivery and per cup (DOSE grams a cup),
a monthly estimate, the saving against shop prices (SUB_DISCOUNT) and the next three delivery
dates: the first is DELIVERY_LAG days after the next ROAST_DAY (Monday) after today, the rest
follow every few weeks. Dates are written in plain text, so they read the same on any day. The plan
is saved and restored on the next visit; /subscribe/?style=decaf preselects a style. The
"Start subscription" form is a demo (see Forms).
Checkout#
The checkout has three steps (details, delivery, payment) with a step indicator. Each step is
validated before the next; the delivery step offers standard (free over FREE_SHIPPING), express
and roastery pick-up with prices from SHIPPING; the payment step shows a review with Edit links
and formats the card number and expiry as you type. On success it shows a confirmation with a
random FC- order number and clears the cart. No payment is processed. The submit handler in
initCheckout() marks the spot for your payment provider. For real payments, use a hosted checkout
such as Stripe Checkout, or a shop plugin such as WooCommerce, and don't collect card numbers in
your own form.
Brew guides#
The brew page has one tab per method (role="tablist"; arrow keys, Home and End move between
tabs). /brew/#aeropress opens a tab directly (any letter case). The recipe scaler reads the open
method's ratio and cup size from METHODS: choose the number of cups and the strength (one point
more or less water per gram) and it shows the coffee, water and ratio. To add a method, add it to
METHODS, a tab and a panel in the Custom HTML of brew-guides.
Wholesale estimator#
On the wholesale page, drinks a day and days open each week give the kilos of coffee a week
(WHOLESALE_DOSE, 18 g a drink), the matching price tier from TIERS (highlighted in the table)
and an estimated weekly spend. The table itself is text in the wholesale-pricing pattern: keep it
in step with TIERS.
Back to top#
A button appears after scrolling about one screen down; it scrolls to the top (instantly with
reduced motion), moves keyboard focus to the main content and lifts above the toast. It is created
by assets/js/main.js; to remove it, delete the "Back to top" part of that file and the
.back-to-top styles in src/theme.css, then run pnpm build.
Block styles#
In the block settings' Styles panel:
| Block | Styles |
|---|---|
| Button | Fill (default, the cobalt button), Outline, Sun, Light (on dark) |
The classes is-px-7, is-py-3-5, is-text-base and is-bg-cream on a Button block make it
wider, taller, larger or give an outline button a cream fill (the hero buttons use them).
FAQ answers on the contact page are Details blocks: add one by duplicating an answer in List
View; its summary layout comes from classes starting with [&>summary]: and its plus sign is drawn
by CSS (ff-plus).
Forms#
All forms are validated by setupValidation() in assets/js/main.js: errors appear on blur and
submit, the first invalid field is focused, and each error is linked with aria-describedby. Rules
come from attributes in the forms' Custom HTML: required, type="email", type="tel",
minlength, data-label (the name used in the message), data-validate (zip, order, card,
expiry or cvc) and, for a group of checkboxes, data-group with data-msg.
| Form | Where | Behaviour |
|---|---|---|
Newsletter (data-form="newsletter") |
every footer | replaced with a thank-you message |
Subscription (data-form="subscribe") |
Subscribe | replaced with a summary of the plan and the first delivery date |
Wholesale (data-form="wholesale") |
Wholesale | needs at least one interest; replaced with a thank-you message |
Contact (data-form="contact") |
Contact | the order number is optional (FC-12345); replaced with a thank-you message |
Checkout (#checkout-form) |
Checkout | shows the order confirmation |
Nothing is sent. To collect messages, use a form plugin (replace the form's Custom HTML block
with the plugin's block; add the classes field, field-label and btn-primary to its fields,
labels and button), or post the form in its callback in assets/js/main.js (in a child theme), for
example to Formspree:
$$('[data-form="contact"]').forEach((form) => setupValidation(form, () => {
fetch('https://formspree.io/f/your-id', {
method: 'POST', body: new FormData(form), headers: { Accept: 'application/json' }
}).then((res) => {
successSwap(form, res.ok ? '<p>Thanks for writing.</p>' : '<p>Something went wrong. Please email us.</p>');
});
}));Every field has a name, so the request carries all the values; keep a name on any field you add.
Saved data (localStorage)#
| Key | Value | Used for |
|---|---|---|
firstcrack-cart |
JSON list of { id, size, grind, qty } |
the cart |
firstcrack-plan |
JSON { style, size, bags, freq, grind } |
the subscription builder |
These are the HTML version's keys. Both are validated every time they are read: unknown coffees,
sizes, grinds and styles are dropped or replaced with defaults (ids in any letter case are
accepted), quantities are clamped to whole numbers from 1 to MAX_QTY, duplicate cart lines are
merged, and tampered data is overwritten with the cleaned version. Prices are never stored; totals
are always calculated from COFFEES and STYLES. If storage is blocked (some private windows),
the shop still works, but the cart and plan are empty after a reload.
SEO and sharing#
Page titles come from WordPress: the page title, an em dash and the site name (for example
"Wholesale — First Crack"); the home page shows the site name and tagline (Settings > General).
The product page sets its title from the coffee ("Kochere Lot 7 — Ethiopia coffee | First Crack
Coffee") once the script runs. The theme doesn't output meta descriptions or Open Graph tags; use an
SEO plugin such as Yoast SEO, Rank Math or The SEO Framework, and give it assets/img/og-image.png
(or your own 1200 × 630 image) as the default social image. WordPress already generates a sitemap
at /wp-sitemap.xml.
Accessibility#
Built in: a skip link to the main content (added by WordPress, styled by the theme), landmarks
(header, labelled navigation, main, footer), one h1 per page, visible focus rings, the menu button
with aria-expanded and a label that changes with its state, a cart drawer that traps focus and
returns it, a labelled cart button with the item count, live result counts and plan prices,
radio-card options with visible focus, ARIA tabs on the brew page, form errors announced through
aria-describedby and aria-invalid, labelled bag art, and reduced-motion support for every
animation (the ticker stops). The demo passes axe (WCAG 2.1 A and AA).
When you edit: keep one Heading 1 per page, give images alt text (or mark them decorative), keep
link text meaningful, and label any field you add to a form (<label for="...">).
Building and deploying#
You only need this if you change the theme's files. The stylesheet assets/css/theme.css is
compiled with Tailwind CSS from src/theme.css and the classes used in patterns/, parts/,
templates/, inc/ and assets/js/:
pnpm install
pnpm build # compile assets/css/theme.css and assets/css/editor.css
pnpm watch # recompile assets/css/theme.css on every change (run pnpm build before you commit)Run pnpm build after adding a utility class to a pattern, template or the script's markup,
otherwise the class has no style. Classes you type in the editor's Additional CSS class(es)
field are only styled if the stylesheet already contains them.
To deploy, zip the theme folder (named freeframe-roast, without node_modules/) and upload it
in Appearance > Themes, or copy the folder to wp-content/themes/ on your server.
Translations#
The theme is translation-ready with the text domain freeframe-roast. All text in patterns,
templates and PHP goes through WordPress's translation functions; the script's strings (cart,
filters, subscription summary, checkout messages, form errors) are translated in PHP
(freeframe_roast_script_strings() in inc/setup.php). Coffee names and descriptions are data in
assets/js/main.js. Create a translation with Loco Translate, or with WP-CLI and Poedit:
wp i18n make-pot wp-content/themes/freeframe-roast wp-content/themes/freeframe-roast/languages/freeframe-roast.potSave freeframe-roast-de_DE.mo (for example) in wp-content/languages/themes/ or in the theme's
languages/ folder. Page content created by Roast setup is copied into your pages in the site's
language at that moment; translate it in the editor like any other content.
Child themes#
Use a child theme for changes you want to keep when Roast is updated (your coffees in particular).
Create wp-content/themes/roast-child/style.css:
/*
Theme Name: Roast Child
Template: freeframe-roast
*/Templates, parts, patterns and theme.json in the child theme override the parent's files of the
same name. To use your own copy of assets/js/main.js, dequeue the parent's script
(freeframe-roast) and enqueue yours with the same dependencies in the child's functions.php.
The parent's stylesheet only contains the classes the parent uses: if your child theme uses new
utility classes, compile a stylesheet for the child (copy package.json and src/theme.css, point
the @source lines at the child's folders) and enqueue it.
Troubleshooting#
- The pages look unstyled or new classes do nothing. The stylesheet only contains classes it
found when it was built. Run
pnpm buildafter editing patterns, then reload. - "This block contains unexpected or invalid content". A pattern or page was edited by hand with markup that doesn't match the block. Click Attempt recovery, or re-insert the section from Patterns > Roast.
- Coffee links go to a page that doesn't exist. The script links to
/product/,/shop/,/subscribe/,/checkout/and/brew/. If you renamed those pages, updatefreeframe_roast_page_urls()ininc/setup.php. - The cart or plan doesn't keep its contents. The browser blocks storage (some private windows), or the coffee ids changed. See Saved data.
- Contact is missing from the desktop menu, or another link is. The desktop header hides the menu's last link. See Navigation, header and footer.
- Roast setup says the pages exist, but they are empty. It never overwrites existing pages. Delete (and empty the trash of) the pages with those slugs, or open each page and insert its page pattern from Patterns > Roast pages.
- The forms don't send anything. They are demo forms; see Forms.
- A page shows the title twice or no title. Pages use a template without a title, because the page patterns start with their own heading. For a plain text page (privacy policy, terms), choose the Page with title template in the page's settings.
License#
MIT, which is compatible with the GPL that WordPress requires (see LICENSE.txt in the theme
folder). Free for personal and commercial use. The coffee artwork and logo are included under the
same license. Unbounded and Onest are licensed under the SIL Open Font License 1.1 (OFL.txt in
each folder of assets/fonts/).