fetchPageFile now rejects text/html responses so servers with SPA routing (e.g. Cloudflare Pages with /* /index.html 200) no longer trick the renderer into treating a fallback index.html as a found markdown file. Category-variant pages (page.current.md with no plain page.md) now fall through correctly to their variant URL. mdcms build now writes a self-unregistering service-worker.js when pwa: no, evicting any stale caching worker left over from a previous pwa: yes build. manifest.json is also removed when pwa: no. https://claude.ai/code/session_01Xs5GyREFhjWxhS1UhW2wA8
4.1 KiB
Unreleased changes
Changes merged into development that have not yet been released to main.
mdcms build patches <title> with sitename
mdcms build now rewrites the <title> tag in index.html with the value of sitename from config.yml. Previously the tag was hardcoded (MD-CMS) in older templates, or blank in the starter template, so link previews in WhatsApp, Slack, and other crawlers that read static HTML showed the wrong name.
Untranslated posts now visible in all categories
Status: On development, pending release.
What was broken
When the category system is enabled, a post file without a category suffix (e.g. posts/my-post.md) was silently assigned to the default category only. Switching to any other category caused those posts to disappear from the nav and from posts-* tag listings — even though no translated version existed. If you wrote posts without a language suffix, they simply vanished the moment a visitor switched category.
Pages without a category suffix are unaffected: they continue to be assigned to the default category, which is the correct behaviour for pages.
What it does now
Posts without a category suffix are treated as uncategorised — meaning they appear in every category. A post called my-post.md now shows up regardless of which category is active. A post called my-post.en.md still appears only in the en category as before.
Mixed situations work as expected: if you have both my-post.md and my-post.nb.md, the Norwegian variant is shown when the nb category is active, and the bare my-post.md is shown for every other category.
What changes in the build output
After rebuilding a site with mdcms build, affected post entries in nav.yml gain an uncategorized: true field:
- file: posts/my-post.md
title: My Post
sort: 100
uncategorized: true
In search.json, these entries carry "category": null instead of the default category code. This is what tells the renderer to include them universally.
A rebuild is required for existing sites to pick up the change.
Fix: category-variant pages fail to load on servers with SPA routing (e.g. Cloudflare Pages)
When a site uses category-suffixed page files (e.g. page.current.md) and is hosted on a server configured with SPA fallback routing (serving index.html with HTTP 200 for any unknown path), the renderer's fetchPageFile mistook the HTML fallback for a found markdown file. It returned index.html content instead of falling through to try the .current.md variant. The page rendered the raw HTML of index.html as markdown, showing the <title> text (sitename) in the content area.
fetchPageFile now checks the Content-Type response header and rejects any response with text/html, continuing to the next candidate URL instead.
Fix: stale service worker not removed when pwa: no
index.html unconditionally registers service-worker.js on every page load. When a site switched from pwa: yes to pwa: no, mdcms build stopped generating a new service worker, but the old one remained active in browsers that had visited the site before. The stale worker continued to serve cached responses from the old build.
mdcms build now writes a self-unregistering service-worker.js when pwa: no. On the visitor's next page load, the browser installs this stub worker, which immediately unregisters itself and evicts any previously cached content. manifest.json is also removed if present.
Fix: config.yml YAML parse errors now abort the build with a clear message
A malformed config.yml (e.g. a stray tab character, which YAML forbids as a token starter) previously caused read_config to silently return an empty dict. The build would proceed with no config — categories disabled, no default category code — producing a broken nav.yml with wrong filenames and missing variants fields, so category-variant pages would not appear in the sidebar.
read_config now raises ClickException on both OSError and yaml.YAMLError, aborting the build with a descriptive error message instead of continuing silently with an empty config.