Post
Three Releases Without a Post: Structured Data, Languages and a Security Fix
The last post here covered the API documentation in 1.8.69. Three releases have gone out since without one. Most of what changed came from building real sites on ssg, a multilingual marketing site and a recipe blog, where we had to script around something ssg did not do. This post goes through those gaps and what ssg does about them now.
Recipes without the backfill script
A recipe site migrated from WordPress had 26 posts and a Python script. The
script read each post, found the ingredients list and the method, and copied
both into the post's schema: front matter so the page could carry a Recipe
rich result. It had to run again every time a recipe was added.
In 1.8.72 ssg reads them itself. When a page's structured data is a Recipe and
its schema: has no recipeIngredient or recipeInstructions, ssg takes
them from the post:
- the list under a heading called "Ingredients", "Składniki", "Zutaten", "Ingrédients", "Ingredientes" or "Ingredienti";
- the steps under "Method", "Instructions", "Preparation", "Przygotowanie", "Zubereitung" and the like.
A heading can be ## Ingredients or a bold line. It can go on ("Ingredients
for 16 servings"). The steps can be a numbered list, plain paragraphs, or
paragraphs under <strong>Step 2</strong>. recipe_headings adds a site's own names.
recipeCategory now comes from the post's categories. Anything you do write
in schema: still wins, field by field.
{{ duration "PT1H25M" }} prints "1 hr 25 min", in six languages. Structured
data keeps times as ISO 8601, so a theme no longer needs a second,
hand-written copy to show them. check_schema_recommended: true lists what a
recipe card would show if it were there, such as yield, time and nutrition,
as advice that never fails a build.
More structured data, no extra front matter
- FAQ. A
faq:list in front matter becomes an FAQPage block. - Listings. With
seo: true, every listing and archive page is an ItemList of the posts it shows, in order. - Authors. An author's archive is that author's ProfilePage.
- The site. The front page names the Organization behind it, using the
name, logo and social profiles already set in
marketing:.
A theme that writes its own JSON-LD keeps full control and gets these blocks as
.StructuredData to include if it wants.
A CV page from Schema Resume
Schema Resume is a JSON format for a CV. Point ssg at one:
1resume:
2 file: cv.json
ssg builds a page at /cv/ that renders in any theme, with ProfilePage
structured data that lists your roles, education, credentials, skills and
languages in schema.org terms. It also publishes the source document next to
the page as resume.json. Your e-mail, phone and street address stay out of
the page, the structured data and that file unless you set contact: true.
A front page per language
On a site in Hindi, English and Polish, each language needed its own home
page. A page with link: "/en/" worked, but ssg did not know it was the
English front page. It wrote the English post listing to the same file, and
whichever was rendered last won. Since 1.8.70, a page at a language's root is
that language's front page, and its listing moves to /en/blog/. The listing
pages also gained what a theme needs for its <head>: the language, the
canonical address of each paginated page, and hreflang for every language.
Workers
- Newsletter.
ssg new worker newsletteris a sign-up form backed by Cloudflare D1. It stores the consent text with each address, checks Turnstile, and supports one-click unsubscribe and double opt-in. The admin view exports CSV. - Turnstile secrets. Workers in one Cloudflare Pages project share one
environment. Setting
TURNSTILE_SECRETfor the comments Worker used to turn on a check in the cookie-consent log that the banner never passed, so every consent record was dropped without an error. Each Worker now reads its own secret first. - Cookie dialog focus. The consent dialog now keeps keyboard focus inside it and hands it back to the element that opened it when it closes.
Smaller fixes worth knowing
- Render hooks (1.8.70) are now looked up in the theme first, so a theme can ship them.
- The snap's private
/tmp. The snap build now warns when you point it at/tmp, which is the snap's own private copy. Before 1.8.70 it reported success, and the files were nowhere you could find them. - Docker preview. In the Docker image, which has no Node, the preview now
says once that Functions are not served, instead of failing every time it
starts.
watch_runner: nonesilences it.
1.8.71: update now
1.8.71 is a security release. Dependabot did not report this: it watches
dependencies, and these vulnerabilities were in Go itself. govulncheck found
13 advisories in Go 1.27.1's standard library and in golang.org/x/net that
ssg's own code calls, in HTTP/2, net/http, crypto/tls, html/template and
os. That covers the preview server, every remote fetch and every page ssg
renders. ssg 1.8.71 is built with Go 1.27.2. Nothing in a site changes; replace
the binary, package or image. Building ssg from source now needs Go 1.27.2.
The changelog has everything, and UPGRADING has the one thing in 1.8.72 to check: recipe pages may now publish ingredients, steps and a category they did not publish before.