Replace the GitHub Contents API tree-walk with a flat manifest approach.
template-manifest.json lists every file and empty directory in the starter
template; download_template() fetches the manifest then pulls each file
directly as a raw URL, sidestepping git API rate limits and making the
template hostable from any HTTP source.
- GITHUB_CONTENTS_API / _github_get / _download_tree removed
- TEMPLATE_BASE_URL + TEMPLATE_MANIFEST constants added
- _http_get() replaces _github_get() (generic, no GitHub headers)
- download_template() accepts optional base_url for custom sources
- app/template-manifest.json added (v0.4, 35 files, 2 empty dirs)
- Generated files (manifest.json, service-worker.js, search.json)
excluded from manifest — they belong to mdcms build output, not
the starter template
https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
Pages whose filename matches a nav section-id now get a clean pathname
URL (e.g. /timesheet) instead of the hash-based /#pages/timesheet.md.
- _initialPathname captured at IIFE start; handles ?_route= from 404.html
- basePath determined by initBasePath() after nav data loads; subpath
deployments (e.g. /mysite/) handled automatically
- navigateTo() uses replaceState to /slug for section-id pages and falls
back to #hash for everything else
- popstate listener handles browser history if a clean URL was the entry
- resolveSlugToFile() validates that slug is both a section code and has
a pages/{slug}.md entry in navData
- app/404.html added for GitHub Pages SPA routing
https://claude.ai/code/session_01Ai8xRvmrzdhuTKiRQ2fnn9
Implements four new mdcms fenced-block types:
tab-underline / tab, tab-filled,
accordion-underline / accordion, accordion-filled
Each block reads items: from a YAML body. Tab state and accordion
open/close are managed with aria-selected / aria-expanded and
data-open attributes. Markdown content inside each item is rendered
with the same pipeline as the surrounding page.
Adds computeDerivedTokens() — called on every applyTheme() — which
computes --mdcms-bar, --mdcms-filled-bg/border/fg, --mdcms-strip-border
from the active palette. Uses HSL chroma (S × (1-|2L-1|)) instead of raw
HSL S for the bold-nav heuristic, avoiding a false-positive on near-white
nav colours like the default #F8FAFC.
Adds app/pages/tabs-accordions.md as a visual test page and
docs/unreleased.md to track this change ahead of the next release.
https://claude.ai/code/session_01SFMh7PDxJjvvo5dYbCCFFs
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
A YAML parse error in config.yml (e.g. a stray tab character) caused
read_config to swallow the exception and return {}, disabling categories
and producing a broken nav.yml with no variants fields and wrong filenames.
read_config now raises ClickException on both OSError and YAMLError.
Documented in docs/knownbugs.md and docs/unreleased.md.
https://claude.ai/code/session_01Xs5GyREFhjWxhS1UhW2wA8
mdcms build now writes the sitename from config.yml into the <title> tag
of index.html. WhatsApp, Slack, and other link-preview crawlers read the
static HTML without executing JavaScript, so the title must be correct in
the raw file. Previously it was blank (or "MD-CMS" in older templates).
Pages without a category suffix still map to the default category.
Only posts/ files without a suffix get uncategorized: true in nav.yml
and category: null in search.json.
https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e