Freeframe

Documentation

Keystone

v1.0.0Updated Oct 12, 2026An architectural, high-trust site for a design-build construction firm, with a project estimator and case studies.

Overview#

Keystone is a website for a design-build construction firm, built as a WordPress block theme. The fictional brand is Corbel Design-Build, an architecture studio and general contractor in Milwaukee, Wisconsin. The theme has a blueprint-style home page with a hero drawing that draws itself in, count-up figures, services, selected work, a process timeline, accreditations and client references; a project portfolio with type filters and search; a case study with a facts table, a before/after slider and a drawing gallery with a lightbox; a services page with sectors, contract models and an FAQ; a five-step cost estimator that feeds a quote request; an about page with the story, values, leadership, safety record and open roles; a contact page with live office status, a map and a contact form; 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/keystone.

Headings, copy, cards, lists, buttons and images are core WordPress blocks arranged in block patterns, so you edit them in the block editor without touching code. The interactive parts (the estimator, the project filter bar, the before/after slider, the gallery lightbox, the forms and the office status) work as in the HTML version: they are small Custom HTML blocks driven by assets/js/main.js. 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.

  1. Download keystone.zip from freeframe.dev/templates/keystone (the WordPress tab).
  2. 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 Keystone.
  3. Go to Appearance > Keystone setup and click Create the demo pages. This creates the Home, Projects, Malt House Lofts (the case study), Services, Project estimator, About 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.
  4. 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:

sh
pnpm install
pnpm dev     # builds the CSS, then starts WordPress with the theme at http://127.0.0.1:9400

pnpm 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 > Keystone pages) made of section patterns. Every section is also offered on its own in the block inserter under Patterns > Keystone.

Page Slug Page pattern Sections (pattern files in patterns/)
Home / page-home.php home-hero (line drawing and count-up figures), home-services, selected-work, process, accreditations, client-references, cta
Projects /projects/ page-projects.php projects-hero, project-list (type filter, search and nine project cards), projects-cta
Malt House Lofts /project/ page-project.php case-study-hero, case-study-brief (drawing, brief and project facts), before-after, gallery (with the lightbox), outcome, related-projects, project-cta
Services /services/ page-services.php services-hero, service-commercial, service-residential, service-renovation, service-architecture, sectors, contract-models, faq, cta
Project estimator /estimate/ page-estimate.php estimate-hero, estimator (the five steps, the quote request and the cost summary), estimate-bar (the cost bar on phones)
About /about/ page-about.php about-hero, story (with the timeline), values, leadership, safety-record (with the chart), careers, cta
Contact /contact/ page-contact.php contact-hero, contact-form (form and the two office cards), service-area (map), direct-lines
404 any missing URL templates/404.html 404

The cta band ("Have a site? Let's put numbers on it.") is one pattern shared by Home, Services and About: insert it anywhere from Patterns > Keystone. 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-keystone/
  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), editor styles, the `js`
                            class script, theme colour and favicon, 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 > Keystone 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         estimator, project filter, slider, lightbox, forms, office status...
  assets/icons/             SVG icons for the Icon block
  assets/img/               project drawings, team portraits, logo, favicon, social image
  assets/fonts/             Barlow, Barlow Condensed and IBM Plex Mono, 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-keystone.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.txt

Customising#

Brand and colours#

The colours are in theme.json (settings.color.palette) and in Appearance > Editor > Styles > Colors > Palette:

Colour Default Used for
Charcoal 950 #121314 blueprint sections, the footer, text on orange
Charcoal 900, 800, 700 #1a1b1d, #242629, #34373b outlines, dark buttons, body text
Charcoal 600, 500 #4a4e53, #6b7076 secondary text, labels
Concrete 50 #f6f5f2 the page background
Concrete 100 to 400 #ecebe6 to #a19e95 drawing-paper sections, borders, hairlines
Signal 500 #f15a0f the brand orange: buttons, markers, highlights on charcoal
Signal 300, 400, 600 #ffa366, #ff7a2e, #d24c0a hover states and icons
Signal 700 #a83b06 orange text on light backgrounds (enough contrast)
White, Black for your own blocks

The theme's stylesheet reads these colours from the palette (bg-signal-500, text-char-600...), so changing Signal 500 in Styles recolours every button and marker at once. Keep Signal 700 dark enough for text on Concrete 50 (4.5:1). The SVG drawings (the hero building, the 404 keystone, the project elevations, the map and the safety chart) carry their own colours in their markup.

The drawing-paper and blueprint backgrounds are the classes grid-paper and grid-blueprint (gradients in src/theme.css): add either to a Group's Additional CSS class(es).

Typography#

Three fonts are bundled in assets/fonts/ and declared in theme.json (settings.typography.fontFamilies), so no request goes to Google: Barlow Condensed (500 to 700; preset display) for headings, buttons and big numbers, Barlow (400 to 600 and italic; preset sans) for text, and IBM Plex Mono (400 and 500; preset mono) for the technical labels. 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, --mono), so keep those slugs. The SVG drawings name the fonts directly (font-family="IBM Plex Mono, …").

Font sizes are the presets in theme.json (xs 0.75rem to 9xl 8rem, the Tailwind scale). The classes h-display (condensed, bold, uppercase), spec (small mono label), eyebrow (mono label with an orange square) and eyebrow-light (the same on dark) give text the template's styles.

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 > Keystone.

What the script drives 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 building drawing an SVG that draws itself in (.draw)
project-list the type chips and search box, the result count, the empty state see Projects filter and search
before-after the slider see Before/after slider
gallery the gallery buttons and the lightbox see Gallery lightbox
estimator, estimate-bar the steps, the quote form, the cost summary, the cost bar on phones see Project estimator
safety-record the chart and its data table an SVG bar chart; update the bars and the sr-only table together
contact-form the form, its success message, the office status and the opening hours see Forms and Office status
service-area the map an SVG map of southeast Wisconsin
404 the keystone drawing an SVG that draws itself in
header, footer the menu button, the CORBEL wordmark driven by the script; decorative

Some blocks carry classes (Block settings > Advanced > Additional CSS class(es)) that the script reads. Blocks can't store data- attributes, so the script turns classes starting with ffd- into them when the page loads: ffd-project ffd-type--renovation on a project card becomes data-project data-type="renovation".

  • reveal fades a block in as it scrolls into view.
  • link-card on a group makes the whole group clickable: the first link inside it stretches over the group (the logos).
  • crop draws orange crop marks on two corners of a card.

Adding a project

On the Projects page, select a project card (a List item group with the class ffd-project ffd-type--commercial, for example) in List View and duplicate it. Change the drawing, the badge, the "P-1xx / place" line, the name and its link, the description and the floor area and year. The type class must be one of the chip filters (ffd-type--commercial, --residential, --renovation, --architecture); the search matches the name, the place, the badge, the year and the description, read from the card itself. Then update the counts on the chips (the chip-count numbers in the filter bar's Custom HTML) and the "Showing 9 projects" text.

Images and artwork#

The project elevations, the case study drawings and the team portraits are SVG files in assets/img/, used by Image blocks: select one and Replace it with a photo. Keep the aspect ratios: project cards are 4:3 (800 × 600), the before/after pair 800 × 520 (both images the same size), team portraits 5:6 (400 × 480). The logo is assets/img/logo.svg in an Image block next to the CORBEL wordmark in the header and footer patterns. Icons are Icon blocks: select one and pick another from the Keystone 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.

The hero drawing, the 404 keystone, the safety chart and the map are inline SVG in Custom HTML blocks (inline so their lines can animate and their labels use the theme's fonts). Replace any of them with an Image block if you prefer a photo.

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 licence and phone 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": Home, Projects, Services, About, Contact, Get an estimate). Its first link (Home) and last link (Get an estimate) are hidden in the desktop header, which has the logo and its own estimate button; keep them first and last, or remove the .site-nav … :first-child and :last-child rules 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 Work and Company menus are List blocks: click a link to change it, press Enter to add one. The phone number, email and licence number appear in the header bar, the footer, the contact page and the call-to-action bands; search for them when you change them.

Features#

Project estimator#

The Project estimator page walks through five steps (project type, size, finish, timeline, your details) and shows a live estimate in the summary panel (aria-live="polite"), with a cost bar at the bottom of the screen on phones.

  • Where the code is: the "Estimator price model" block at the top of the second part of assets/js/main.js (data and estimate()), and the "Estimator: 4 steps + request form" block further down (the interface). The markup is the estimator pattern's Custom HTML.

  • The data:

    js
    var TYPES = {
      commercial: { label: __('Commercial build'), desc: __('…'), rate: [215, 340], min: 2000, max: 80000, step: 500, size: 12000, weeks: [26, 1], help: __('…') },
      …
    };
    var FINISH = { standard: { …, mult: [1, 1] }, premium: { …, mult: [1.18, 1.28] }, signature: { …, mult: [1.45, 1.65] } };
    var TIMELINE = { flexible: { …, mult: [0.96, 0.97], pace: 1.15 }, standard: { … }, fast: { …, mult: [1.08, 1.14], pace: 0.82 } };
    var DESIGN = { label: __('Architecture & permits'), mult: [1.07, 1.1], weeks: [12, 20] };
    var DEFAULT_ESTIMATE = { type: 'commercial', size: 12000, finish: 'standard', timeline: 'standard', design: true };
  • The calculation (estimate(s)): floor area × the type's rate per ft², times the finish and timeline multipliers, times DESIGN.mult when architecture is included. The low end is rounded down and the high end up to the nearest $5,000. Build time in weeks is (weeks[0] + weeks[1] × size / 1000) × pace, shown as a range of −8% to +10%.

  • Changing prices: edit rate and mult (in a child theme, see Child themes). Also update the price text on the option cards in the estimator pattern ($215–$340 / ft², +18–28%) and the default numbers in the summary panel, which show before the script runs.

  • Adding a project type: add a key to TYPES and copy an option card in step 1 with <input type="radio" name="type" value="your-key">.

  • Links in: /estimate/?type=renovation preselects a type (the services and case study pages use it), and /estimate/#request opens the details step.

  • Accessibility: each step is a <fieldset> with a <legend>; choices are real radio buttons and a checkbox. The step buttons use aria-current="step", and moving between steps puts focus on the new step's heading. Without JavaScript all steps are shown at once.

On the Projects page the chips filter the cards by type and the search box matches every typed word against the card's name, place, type, year and description. The count (role="status") announces "Showing 2 of 9 projects", an empty state with a Clear filters button appears when nothing matches, and the URL updates to ?type=…&q=…, so filtered views can be shared (the services page links to /projects/?type=commercial and so on). Chips are buttons with aria-pressed. The code is the "Projects: type filter + search" block in main.js; the search text is built from each card by the WordPress adapter at the top of the file.

Before/after slider#

On the case study, the after image sits underneath and the before image is clipped on top with clip-path driven by the --pos custom property (.before-after-clip in src/theme.css). An invisible range input covers the images, so dragging, clicking, touch and arrow keys all work, and screen readers hear "52% before, 48% after". To use other pictures, edit the two <img> paths in the before-after pattern's Custom HTML and keep both images the same size.

The gallery buttons open their drawing in a native <dialog> with previous and next buttons, arrow keys, Esc or a click on the backdrop to close, and focus returned to the button that opened it. The lightbox reads its pictures, titles and captions from the gallery buttons themselves, in order: to change a drawing, edit the <img src> and the two text lines of its button in the gallery pattern's Custom HTML; to add one, copy a button and give it the next data-lightbox-open number.

FAQ accordion#

The FAQ on the Services page is an Accordion block (WordPress's own, with its keyboard support and ARIA): add a question by duplicating an item in List View. The first answer is open when the page loads (Open by default in the item's settings). The square plus/minus marker is drawn by CSS (.wp-block-accordion-heading__toggle::after in src/theme.css).

Office status#

Each office card on the Contact page (ffd-office--milwaukee, ffd-office--madison) shows "Open now · until 5:30 pm" or "Closed · opens tomorrow 7:00 am", worked out in the office's own time zone:

js
var OFFICE_HOURS = {
  milwaukee: { tz: 'America/Chicago', days: [null, [7, 17.5], [7, 17.5], [7, 17.5], [7, 17.5], [7, 16], null] },
  madison: { tz: 'America/Chicago', days: [null, [8, 17], [8, 17], [8, 17], [8, 17], [8, 17], null] }
};

Day 0 is Sunday; null means closed; hours are decimals (17.5 is 5:30 pm). Keep these in step with the opening-hours tables in the contact-form pattern. Without JavaScript the badge reads "Office hours".

Count-up stats, scroll reveals and line drawings#

Blocks with reveal fade and rise into view, and .draw SVGs draw their lines, when they scroll into view. Numbers inside <span data-count="620" data-decimals="0">620</span> count up once when they appear (edit the number and its data-count together in the paragraph's HTML view). All three are skipped when the visitor prefers reduced motion, and nothing is hidden without JavaScript.

Header, mobile menu and back to top#

The header is sticky and gains a shadow after scrolling. Below 1024 px the menu button opens the mobile menu, updating aria-expanded and its label; Esc closes it and returns focus to the button. A back-to-top button appears after about one screen of scrolling and steps aside while the footer's "Back to top" link is visible; on the estimator it lifts above the cost bar (data-back-to-top-avoid). To remove it, delete the "Back to top" part at the end of assets/js/main.js 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 orange button), Dark, Ghost, Ghost (on dark)

The class is-large on a Button block makes it the larger hero size. Arrow and pencil icons on buttons are classes too (icon-after-arrow-right, icon-before-ruler, with icon-size-20); see src/icons.css for the available icons.

Forms#

There are two forms. Both validate in the browser and neither sends anything until you connect it; their success messages say so.

Form Where Validation
Quote request (data-quote-form) Project estimator, step 5 name, email, phone (10+ digits), site, ideal start, project notes (20+ characters), consent box
Contact (data-contact-form) Contact name, email, optional phone (10+ digits if filled), topic, nearest office, message (10+ characters)

Validation is in wireForm() and check() in assets/js/main.js. It reads required, type="email", minlength, required checkboxes and data-validate (phone, phone-optional) from the forms' Custom HTML; a <fieldset data-group="office"> of radio buttons requires a choice. Errors appear under each field, linked with aria-describedby, and the first invalid field gets focus.

To collect messages, use a form plugin (replace the form's Custom HTML block with the plugin's block; add the classes label, input and btn btn-signal to its labels, fields and button), or post the form in its callback in assets/js/main.js (in a child theme), for example to Formspree:

js
wireForm(form, function () {
  fetch('https://formspree.io/f/your-form-id', { method: 'POST', body: new FormData(form), headers: { Accept: 'application/json' } })
    .then(function (res) {
      if (!res.ok) throw new Error('Send failed');
      form.reset();
      form.classList.add('hidden');
      ok.classList.remove('hidden');
      ok.focus();
    })
    .catch(function () { alert('Sorry, your message could not be sent. Please call us.'); });
});

For the quote request, do the same inside wireForm(quoteForm, …), and append the estimator's choices (they are in a separate form): data.append('type', state.type), size_ft2, finish, timeline, design and compact(r.low) + ' – ' + compact(r.high). Then change the "This is a demo, so nothing was sent" text in the patterns. The reference number (CDB-26-1234) is random; replace it with the ID your system returns, or remove it.

Saved data (localStorage)#

Key Shape Written
keystone-estimate-v1 {"type": "commercial", "size": 12000, "finish": "standard", "timeline": "standard", "design": true} on every estimator change

This is the HTML version's key. readEstimate() validates it on every read: type, finish and timeline must be keys of TYPES, FINISH and TIMELINE; size must be within the type's limits (otherwise the type's default size is used); design must be a boolean. Anything else falls back to DEFAULT_ESTIMATE, and storage errors are ignored. A ?type= in the URL overrides the saved type. To reset it, delete the key in your browser's developer tools (Application > Local Storage). If you change the shape, rename ESTIMATE_KEY so old values are ignored.

SEO and sharing#

Page titles come from WordPress: the page title, an em dash and the site name (for example "Services — Corbel Design-Build"); the home page shows the site name and tagline (Settings > General). 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. A construction firm benefits from LocalBusiness (or GeneralContractor) structured data with the office addresses and hours; most SEO plugins can add it.

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, labelled sections, visible focus rings in signal orange, the menu button with aria-expanded and a label that changes with its state, filter chips with aria-pressed and a live result count, a range input behind the before/after slider with a spoken value, a native dialog for the lightbox, the Accordion block for the FAQ, estimator steps as fieldsets with aria-current="step", form errors announced through aria-describedby and aria-invalid, a data table behind the safety chart, labelled drawings and reduced-motion support for every animation. Orange text on light backgrounds uses Signal 700 for contrast. 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/:

sh
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-keystone, 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-keystone. All text in patterns, templates and PHP goes through WordPress's translation functions; the script's strings (estimator labels and breakdown lines, result counts, office status, form errors and messages) are translated in PHP (freeframe_keystone_script_strings() in inc/setup.php). Create a translation with Loco Translate, or with WP-CLI and Poedit:

sh
wp i18n make-pot wp-content/themes/freeframe-keystone wp-content/themes/freeframe-keystone/languages/freeframe-keystone.pot

Save freeframe-keystone-de_DE.mo (for example) in wp-content/languages/themes/ or in the theme's languages/ folder. Page content created by Keystone setup is copied into your pages in the site's language at that moment; translate it in the editor like any other content. Prices are formatted in US dollars and square feet by the script (money(), compact()).

Child themes#

Use a child theme for changes you want to keep when Keystone is updated (your prices and office hours in particular). Create wp-content/themes/keystone-child/style.css:

css
/*
Theme Name: Keystone Child
Template: freeframe-keystone
*/

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-keystone) and enqueue yours in the child's functions.php, keeping the inline window.freeframeKeystone strings (or copy them). 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 build after 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 > Keystone.
  • A new project card doesn't show up under a filter. Its group needs the classes ffd-project and ffd-type--<type> with one of the chip types. See Adding a project.
  • The estimate doesn't change after editing prices. The option cards show text from the pattern, but the numbers come from TYPES, FINISH, TIMELINE and DESIGN in assets/js/main.js. Change both. A saved estimate in the browser can also hold an old type: see Saved data.
  • Home or Get an estimate is missing from the desktop menu. The desktop header hides the menu's first and last links. See Navigation, header and footer.
  • Keystone 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 > Keystone 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 project drawings, portraits, map, chart and logo are included under the same license. Barlow, Barlow Condensed and IBM Plex Mono are licensed under the SIL Open Font License 1.1 (OFL.txt in each folder of assets/fonts/).

Search documentation

Search the guides and every template's documentation