Overview#
Ledger is an editorial magazine for long-form writing, built as a WordPress block theme. The demo
is The Ledger, a fictional independent magazine of essays about software, design, craft and
attention. It has a front page with a featured essay, topic chips, the latest essays, a quote,
short notes and most read lists and a newsletter sign-up; a long-form article layout with an "In
this essay" outline, reading progress, footnotes, a chart, sharing, tags, the writer's biography
and "Keep reading"; an archive page with live search and topic filters; a topics page; topic, tag
and writer archives; an about page with the writers, masthead and values; a contact page with a
pitch form; and a 404 page. Typography (Newsreader and Inter) is tuned for comfortable reading in
light and dark mode. It is version 1.0.1 (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/ledger.
How the WordPress version is organised#
The HTML version has one example article and lists the other essays by hand (and in a JSON list for the archive). The WordPress version is a real blog:
- Essays are posts. An essay's topic is its category, its writer is the post author (a WordPress user, with their biographical info and picture), its dek (the line under the title) is the post's excerpt, its cover is the featured image. Three post fields add the reading time, the cover's credit and the "Keep reading" choices (see Essay fields).
- What lists essays is built from the posts: the front page's featured essay and "Latest"
grid (Query Loop blocks), the archive page's search and filters (
inc/content.phpprints the essays' data), the article page (templates/single.html), and the topic, tag, writer and search archives (templates/archive.html,templates/search.html). Publish an essay and it appears everywhere at once. - Editorial choices stay content: the front page's "Short notes" and "Most read" lists, the quote, the topic chips and the Topics page's cards are blocks in the pages, which you edit like any text (WordPress doesn't know which essays are read most).
- The pages (Home, Archive, Topics, About, Contact) are WordPress pages made of patterns, and the header and footer are template parts.
Colours (a light and a dark value for each), the three fonts and font sizes 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
ledger.zipfrom freeframe.dev/templates/ledger (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 Ledger.
-
Go to Appearance > Ledger setup and click Create the demo content. This creates:
- four writers (users with the Author role,
jonah-reyes,ana-ferreira,priya-nairandtomas-lindgren, with an@example.comaddress and a random password), with their biographical info and pictures; - five topics (categories: Design, Craft, Writing, Culture, Engineering, with descriptions) and two tags;
- twelve sample essays (posts) with their topic, writer, date, excerpt, cover (put in the media
library, in
uploads/freeframe-ledger/), reading time and cover credit; the newest, "The case for slower software", has the full article text, the others a short placeholder; - the Home, Archive, Topics, About and Contact pages from the theme's page patterns, Home as the front page (Settings > Reading) and the two header menus.
Anything that already exists (same login or slug) is left alone, so it is safe to click it again.
- four writers (users with the Author role,
-
In Settings > General set the Site Title (the demo uses "The Ledger"; it is in every browser tab title) and the Tagline. Use pretty permalinks (Settings > Permalinks, any option except Plain).
-
Write your own essays (see Writing essays), then delete the sample essays (Posts) and, if you like, the sample writers (Users; give their posts to someone else first).
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
content already set up. The demo gives the featured essay the address /article/ (so its
address is the same as in the other versions' demos); Ledger setup gives it
/the-case-for-slower-software/.
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), sets the site title to "The Ledger" and
the tagline to "Essays on tools, craft and attention", switches on pretty permalinks and creates
the demo content (blueprint.json). 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 and templates#
| Page | Slug | Made of (patterns in patterns/) |
|---|---|---|
| Home (front page) | / |
page-home.php: home-featured (the newest essay, a Query Loop), home-topics (topic chips), home-latest (the next six essays, a Query Loop), home-quote, home-notes (short notes and most read), newsletter (anchor #newsletter) |
| Archive | /archive/ |
archive (search box, topic filter and the list, Custom HTML) |
| Topics | /topics/ |
topics (a card per topic and "Have an idea?") |
| About | /about/ |
about-intro, writers, masthead (masthead and values), write-for-us |
| Contact | /contact/ |
contact (contact form, pitch guidelines, email addresses, newsletter) |
| Template | Used for |
|---|---|
single.html |
an essay (post): the essay pattern, see The article page |
archive.html |
a topic, tag or writer's archive: its name and description, then the list of its essays |
search.html |
search results (WordPress's search, /?s=) with a search box |
index.html |
the blog page, if you choose one in Settings > Reading |
page.html |
pages (their patterns are full-width sections) |
page-with-title.html ("Page with title") |
plain text pages (privacy policy...): the title, then the text in the article style |
404.html |
missing pages (404 pattern, with a search box that searches the archive page) |
Template parts: Header (parts/header.html: the top bar with the tagline, RSS and newsletter
links, and the sticky header) and Footer (parts/footer.html). The essay lists of the
archives use the posts pattern; their headings are archive-heading and search-heading.
Project structure#
freeframe-ledger/
style.css theme header (name, version, requirements, license); no styles
theme.json design tokens: palette (light and dark), fonts, font sizes, spacing,
layout widths, button; the custom template and the template parts
functions.php loads the files in inc/
inc/setup.php stylesheet and script, the script's translations, the dark mode script,
editor styles, head meta (theme colours, favicon), title separator,
pattern categories
inc/content.php the essay fields, the "freeframe-ledger/essay" block bindings source,
the writers' pictures, "Keep reading", the archive page's data
inc/block-styles.php the Outline, Light (on dark) and Text link button styles
inc/icons.php registers assets/icons/*.svg for the Icon block
inc/icon-labels.php the icons' names shown in the editor
inc/site-setup.php Appearance > Ledger setup: writers, topics, essays, pages and menus
templates/ single.html, archive.html, search.html, index.html, page.html,
page-with-title.html, 404.html
parts/ header.html and footer.html
patterns/ the header, footer, front page, article layout, essay card and list,
every page's sections, and the featured essay's text
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 site's JavaScript (see below)
assets/icons/ SVG icons for the Icon block (arrow-right, check)
assets/img/ cover art, writers' portraits, favicon, social image
assets/fonts/ Newsreader, Inter and JetBrains Mono files and their licenses (OFL.txt)
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
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.txtassets/js/main.js starts with a "WordPress:" adapter (it turns the classes blocks keep back into
attributes), then the HTML template's script: theme toggle, mobile menu, scroll reveal, toast, the
article's reading time, progress bar, outline and sharing, the archive's search and filter, form
validation; and finally the back-to-top button.
Writing essays#
Write an essay in Posts > Add New:
| Where | What it is | Shown |
|---|---|---|
| Title | the essay's title | everywhere |
| Text | paragraphs, headings (Heading 2), lists, quotes, Code blocks, pictures... | the article page |
| Excerpt (post settings) | the dek, one or two sentences | under the title on the article page, on the cards and in the archive |
| Categories | the essay's topic (choose one) | the topic line ("Design"), the topic chips, the archive filter |
| Tags | keywords | chips at the end of the essay, tag archives |
| Featured image | the cover (3:2 pictures fit best) | the article page (wide), the cards |
| Author | the writer | name, picture and biography on the article page, writer archive |
| Publish date | the cards, the article page, the archive (grouped by year) |
Every essay belongs to one topic. Posts left in the default category (Uncategorized, like WordPress's sample "Hello world!" post) are not essays: they don't appear on the front page or the archive page (they still have their own address and appear in search results). Give every essay a topic, or rename the default category to a topic in Posts > Categories.
The article page's text is styled for reading (prose-ledger): a paragraph with the class
lede gets the large first letter; a Quote block with the class pull is a centred pull quote
with its citation; a Group with the tag aside and the class callout is a coloured note; a
Code block can contain the theme's highlighting spans (tok-c, tok-k, tok-s, tok-f, in its
HTML view). Look at the featured essay to see them all. The featured essay's notes are a Group
with the class not-prose (it keeps its own small type) holding a heading with the class
ffd-toc-skip (left out of the outline) and a list whose items have HTML anchors (fn1, fn2);
the references in the text are links to them in <sup> (<sup><a href="#fn1" id="ref1">1</a></sup>,
written in the paragraph's HTML view).
Essay fields#
Three post fields (Custom Fields; switch the panel on in the editor's Preferences > General > Advanced) complete an essay:
| Field | Value | Used for |
|---|---|---|
reading_time |
5 min read |
the cards and the archive. Empty: counted from the text (230 words a minute). The article page always counts it from the text. |
cover_credit |
Illustration by Hana Sato for The Ledger. |
the caption under the cover on the article page |
related |
slugs of up to three essays, separated by commas | "Keep reading" on the article page. Empty: the latest essays on the same topic. |
Writers#
Writers are WordPress users (Users > Add New, role Author or Editor). On the article page the
theme shows their Display name, their Biographical Info (Users > Profile) and their picture,
and "More from <first name>" links to their archive (their First Name). Pictures come from
Gravatar, except for users with the freeframe_ledger_avatar user field (a file name in the
theme's assets/img, set by Ledger setup for the sample writers); a plugin such as Simple Local
Avatars lets you upload pictures instead.
Customising#
Brand and colours#
Every colour has a light and a dark value in the palette (theme.json, settings.color.palette,
and Appearance > Editor > Styles > Colors > Palette). The stylesheet maps them to the HTML
template's variables, which switch with the dark class, and Tailwind tokens read those (in
src/theme.css):
| Colour (light slug / dark slug) | Token | Used for |
|---|---|---|
Paper base / base-dark |
paper |
the page background, text on dark bands |
Ink contrast / contrast-dark |
ink |
text, rules, dark bands, buttons |
Surface surface / surface-dark |
surface |
cards, form fields, chips |
Muted muted / muted-dark |
muted |
secondary text |
Line line / line-dark |
line |
borders and dividers |
Accent accent / accent-dark |
accent |
topic lines, links in essays, the progress bar, the drop cap, focus rings |
Accent soft accent-soft / accent-soft-dark |
accent-soft |
callouts, inline code, form messages |
For a blue accent, change Accent and Accent soft in Styles (both themes), or in theme.json. The
code block colours (#191814 and the tok-* colours), the error red and the accent of the
"From the archive" kicker on the dark band (.kicker.on-ink) are written in src/theme.css;
the browser UI colours (#faf7f2, #14130f) in freeframe_ledger_head_meta() (inc/setup.php).
Typography#
Three fonts are bundled in assets/fonts/ (variable files, one per character subset) and
declared in theme.json, so no request goes to Google:
| Font | Slug | Used for |
|---|---|---|
| Inter (400 to 700) | inter |
interface text, labels (the site's Text font) |
| Newsreader (400 to 700, italic 400 to 600) | newsreader |
headlines, deks and the essays' text (the font-serif class) |
| JetBrains Mono (400 to 500) | jetbrains-mono |
code |
To use another font, install it in Appearance > Editor > Styles > Typography > Fonts and
select it, or replace the fontFace entries in theme.json. The utilities read the fonts
through their slugs (--font-serif is --wp--preset--font-family--newsreader in
src/theme.css), so rename a slug only together with src/theme.css. The chart in the featured
essay names Inter in its SVG.
Dark mode#
A small script printed first in <head> (freeframe_ledger_theme_script() in inc/setup.php)
adds the dark class to <html> before the page paints: from the reader's saved choice
("dark" or "light", key ledger-theme in localStorage), or, when there is none or the stored
value is anything else, from the system setting. The theme switch in the header
(data-theme-toggle, with aria-pressed) toggles it and saves the choice. To switch dark mode
off, delete the theme switch's Custom HTML block from the header and add to a child theme's
functions.php:
add_filter( 'freeframe_ledger_dark_mode', '__return_false' );Navigation, header and footer#
Edit the header and footer in Appearance > Editor > Patterns > Header / Footer. The header has
a top bar (from 640 px wide: the tagline and RSS and Newsletter links) and the sticky header: the
masthead ("The Ledger." with an accent full stop), the menu (from 1024 px), a search link to the
archive, the theme switch, Subscribe (to /#newsletter) and, below 1024 px, the menu button
that opens the mobile menu (#mobile-menu). The menus are two Navigation blocks showing the
Main menu and the Mobile menu (Home, Archive, Topics, About, Contact), created by Ledger
setup; edit them in Appearance > Editor > Navigation. WordPress marks the current page's link
(an accent underline on desktop, accent text in the mobile menu).
The footer has the masthead and its line, the Topics, Publication and Follow link lists (List
blocks; the topic links go to the archive page's filter, /archive/?topic=Design) and the
copyright line, which prints the current year when the footer comes from the theme's files. The
RSS, Mastodon and Bluesky links point at # in the demo: set your addresses (your feed is at
/feed/). The toast used by "Copy link" is a Custom HTML block at the end of the footer.
Content in pages#
Edit the pages in Pages. Some content is in Custom HTML blocks, because blocks can't express it: edit those in the block's HTML view.
| Pattern | Custom HTML |
|---|---|
header |
the search link, the theme switch, the menu button |
archive |
the search and filter bar, the list (filled by the script), the empty state |
newsletter, contact |
the forms and their thank-you messages |
essay (article page) |
the outline and share box, the share buttons |
essay-slower-software (the featured essay's text) |
the chart |
footer |
the toast |
404 |
the search form |
"Short notes" and "Most read" on the front page are hand-picked: each item is a Group (class
link-card) whose title links to the essay. The topic chips and the Topics page show essay counts
and each topic's latest essay as text: update them when you publish. WordPress turns straight
apostrophes and quotes typed in text blocks into curly ones (wptexturize).
Classes the script reads#
Blocks keep classes, not data-* or ARIA attributes, so the theme writes the HTML template's
attributes as classes: data-x="y" is the class ffd-x--y, hidden is ff-hidden, and role,
aria-* and tabindex on blocks are ffa-<name>--<value>. The adapter at the top of
assets/js/main.js turns them back into attributes. Keep them when you edit:
| Class | Where | What it does |
|---|---|---|
ffd-article |
the essay's Post Content block (essay pattern) |
the text whose reading time, progress and headings the script reads |
ffd-reading-time |
the reading time in the article header | written by the script ("5 min read") |
ffd-progress |
the bar in the reading progress Group | grows as you read |
ffd-toc-skip |
a heading in an essay's text (the notes' heading) | left out of the outline |
ffa-aria-labelledby--…, ffa-role--region, ffa-aria-hidden--true |
sections and decorative bands | the accessible names and roles of the HTML template |
ffa-tabindex--0 |
the Code block in the featured essay | keyboard scrolling |
Theme classes: link-card (a card whose title link covers it), cover (a picture box),
kicker, prose-ledger, not-prose, lede, pull, callout, chip, ff-chips, ff-inline
(blocks laid out as one line of text), ff-plain-list, ff-cover-link, ff-kicker-links,
ff-text-link, ff-rss, site-nav, site-nav-mobile, reveal.
Features#
The front page#
The featured essay is a Query Loop of one post, the newest essay; "Latest" is a Query Loop of six posts that skips the newest. Both leave out posts in the default category. Change the number of essays or add a topic filter in the Query Loop block's settings.
The article page#
templates/single.html shows the essay pattern for every post: the topic and "· Essay" (Post
Terms), the title, the excerpt, the writer's picture and name, the date and the reading time; the
cover (Featured Image) and its credit; the outline and share box; the text (Post Content); the
topic and tags as chips and the share buttons; the writer's box ("Written by", name, Biographical
Info, "More from Jonah"); "Keep reading" (a Query Loop of three essays: the post's related field,
or the latest on the same topic); and "Liked this essay?". The reading time, the cover credit and
"More from …" are paragraphs and a button bound to the theme's block bindings source
freeframe-ledger/essay (inc/content.php: keys reading-time, cover-credit, url,
author-more, author-url).
Reading progress and outline#
The bar at the top of the article page grows as you read through the text. The outline ("In this essay": a box on wide screens, a collapsible box on narrow ones that closes after you pick a heading) lists the text's Heading 2 blocks (they get an id from their text) and highlights the section you are reading. The reading time is counted from the text (230 words a minute): the words a reader reads, without SVG text (a chart's title, description and labels), hidden elements or the notes (the Notes group or the Footnotes block); captions and code count.
Sharing#
Links with data-share="x", "linkedin" or "email" get share URLs for the page and title.
Copy link copies the page's address and shows a "Link copied to clipboard" toast.
Archive search and filters#
On the Archive page, typing in the search box matches titles, excerpts, writers and topics; the
topic chips narrow by topic; essays are grouped by year with a count and an empty state with a
reset button. The URL keeps the state (/archive/?topic=Design&q=notes), so it can be shared.
Press / to jump to the search box. The essays come from your published posts (every post with
a topic, newest first), printed as JSON by freeframe_ledger_archive_data() in inc/content.php
(filter freeframe_ledger_archive_data); the topics are the essays' categories. The 404 page's
search box searches the archive.
Scroll reveals, mobile menu, back to top#
Elements with the class reveal fade up when they scroll into view (only while JavaScript runs;
at once with reduced motion). The menu button opens the mobile menu, swaps its icon and label, and
closes with Esc, a link or on wide screens. A back-to-top button appears after about one screen
of scrolling (delete its part of assets/js/main.js and the .back-to-top styles to remove it).
Buttons#
The Button block's default style is the dark pill. In the block settings' Styles panel there
are also (inc/block-styles.php) Outline (the template's btn-ghost), Light (on dark)
(for dark bands: "Pitch us", "Subscribe to the letter") and Text link ("More from Jonah").
Forms#
| Form | Pattern | Fields |
|---|---|---|
| Newsletter | newsletter (front page), contact (sidebar) |
|
| Contact | contact |
name (2+ characters), email, subject, message (30+ characters), consent |
Forms with data-validate are checked in the browser: errors appear in the element whose id is the
field's id plus -error (field labels for the messages are in data-label), fields get
aria-invalid, and the first invalid field is focused. When everything is valid, the form's
[data-form-success] panel is shown and focused, and the form is reset.
Nothing is sent anywhere: they are demo forms until you connect them, with a form plugin
(replace the form's Custom HTML block with the plugin's block; add the classes input, label
and btn to its fields and button) or a form service such as Formspree: add the endpoint as the
form's action and method="post", and in assets/js/main.js, at the comment "Send the data to
your form endpoint here", send it with fetch(form.action, { method: 'POST', body: new FormData(form), headers: { Accept: 'application/json' } }) before showing the panel (in a child theme's copy of
the script). Also rewrite the thank-you texts, which say that nothing was sent.
Saved data (localStorage)#
| Key | Value | Purpose |
|---|---|---|
ledger-theme |
"dark" or "light" |
The reader's theme choice; any other value is ignored and the system setting is used |
SEO and sharing#
Page titles come from WordPress: the page or essay title, an em dash and the site name; the front
page shows the site name and tagline. 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 (they use the excerpt and the
featured image of each essay), and give it assets/img/og-image.png as the default social image.
WordPress generates a sitemap at /wp-sitemap.xml and an RSS feed at /feed/.
Accessibility#
Built in: a skip link to the main content (added by WordPress, styled by the theme), landmarks
(a labelled top bar, header, navigation with labels, main, labelled sections, the article's outline
as a labelled aside, footer), one h1 per page, visible focus rings, the theme switch with
aria-pressed, the mobile menu button with aria-expanded and Esc to close, the archive's topic
chips with aria-pressed in a labelled group and the count announced politely, footnotes linked
both ways, an accessible chart (title and description), form errors linked with
aria-describedby, aria-invalid on wrong fields, thank-you panels that receive focus, a
keyboard-scrollable code block, and reduced-motion support for reveals, smooth scrolling and the
back-to-top button.
When you edit: keep one Heading 1 per page and use Heading 2 for an essay's sections (they make the outline), give covers and pictures alt text in the media library (or leave it empty for decorative art), and check the contrast of any colour you change, in both themes (WCAG AA).
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, a template or assets/js/main.js.
Classes you type in the editor's Additional CSS class(es) field are only styled if the
stylesheet already contains them. pnpm start starts WordPress without rebuilding the CSS;
pnpm dev does both.
To deploy, zip the theme folder (named freeframe-ledger, 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-ledger. All text in patterns
(including the Custom HTML blocks), templates and PHP goes through WordPress's translation
functions; languages/freeframe-ledger.pot is the template. The script's strings (theme switch and
menu labels, "N min read", the archive's count, months, "All", "By …", form errors, "Link copied to
clipboard", "Back to top") are translated in PHP (freeframe_ledger_script_strings() in
inc/setup.php, printed as window.freeframeLedgerL10n). Create a translation with Loco Translate,
or with WP-CLI and Poedit:
wp i18n make-pot wp-content/themes/freeframe-ledger wp-content/themes/freeframe-ledger/languages/freeframe-ledger.potContent created by Ledger setup (essays, topics, writers' biographies, pages) is copied in the site's language at that moment; translate it in the editor like any other content. Dates follow the site's language (Settings > General); the archive page's month names are translated strings.
Child themes#
Use a child theme for changes you want to keep when Ledger is updated. Create
wp-content/themes/ledger-child/style.css:
/*
Theme Name: Ledger Child
Template: freeframe-ledger
*/Templates, parts, patterns and theme.json in the child theme override the parent's files of the
same name. 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. Changes to the
script (sending the forms) belong in a copy of assets/js/main.js in the child theme, loaded in
place of the parent's (keeping the handle keeps its translations):
add_action( 'wp_enqueue_scripts', function () {
wp_scripts()->registered['freeframe-ledger']->src = get_stylesheet_directory_uri() . '/assets/js/main.js';
}, 30 );Troubleshooting#
- An essay doesn't appear on the front page or the archive page. It must be published and have a topic other than the default category (Uncategorized).
- The featured essay is not the one I want. It is the newest essay: change the date, or select the featured Query Loop on the front page and filter it (for example by a tag).
- "Keep reading" shows other essays. Fill the essay's
relatedfield with up to three slugs. - The reading time on the cards is wrong. Set the
reading_timefield, or leave it empty to count it from the text. - No outline on an essay. The outline lists Heading 2 blocks in the text.
- The pages look unstyled or new classes do nothing. Run
pnpm buildafter editing patterns. - "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 > Ledger.
- Ledger setup says the pages exist, but they are empty. It never overwrites existing content. Delete (and empty the trash of) the pages with those slugs, or insert the page pattern into each.
- A form or the chart is gone after someone saved the page. Custom HTML needs the
unfiltered_htmlcapability, which administrators have on a single site; edit those pages as an administrator, or use a form plugin. - The forms "send" but nothing arrives. They are demo forms; see Forms.
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 cover art, portraits and icons are included
under the same license. Newsreader (assets/fonts/newsreader/OFL.txt), Inter
(assets/fonts/inter/OFL.txt) and JetBrains Mono (assets/fonts/jetbrains-mono/OFL.txt) are
licensed under the SIL Open Font License 1.1.