The theme engine rewrite is live, and this post is about the work we actually planned, discussed, and implemented during this rewrite pass.
WebGrid now has one canonical theme language running through the site, the Obsidian UI layer, and the palette renderer. The old split-brain setup is gone. Theme files mean one thing again. Changing a theme no longer feels like negotiating with three separate systems.
This was a hard cutover on purpose. Legacy token names are out. Canonical roles are in.
What shipped
code/src/lib/theme-tokens.tsnow defines the canonical role system and fallback defaultscode/src/layouts/Base.astroapplies canonical theme data in the site runtime.obsidian/plugins/palette-rendererwas rewritten around canonical grouped rolesscripts/generate-obsidian-theme-css.mjsnow generates the live Obsidian mapping and wrapper package output.obsidian/plugins/webgrid-theme-sync/main.jsnow handles silent regeneration, theme activation, and light/dark togglingthemes/theme-index.mdandcontent/_site.mdnow split metadata from active theme selection cleanly- README, QUICKSTART, INSTRUCTIONS, the rewrite plan, and TODO were updated to match the new flow
- One canonical role map across Astro, Obsidian, and
palette-renderer - Runtime and build-time fallback handling for missing canonical keys
- A first-class
WebGridtheme package for Obsidian - Live generated Obsidian CSS mapped from the same WebGrid theme source
- A silent sync plugin that regenerates the package in the background
- A
theme-indexpicker with activate buttons for every theme file - A built-in light/dark toggle directly inside the theme picker
content/_site.mdrestored as the source-of-truth for the active site theme
Why this matters
Before this rewrite, the theme story had too many edges. Astro had one path, Obsidian had another, and the visual tooling had its own assumptions layered on top. It worked until it didn’t, and every new theme change increased the odds of drift.
Now the system is opinionated in the right places.
Theme authors work with canonical roles like surface-base, fg-primary, action-primary, border-default, and state-focus. WebGrid consumes those roles in the site runtime. Obsidian consumes those same roles through generated variable mapping. The preview tooling reads the same language too. That means fewer special cases, fewer translation bugs, and a much cleaner mental model.
Changelog
This changelog is based on the rewrite plan, the backlog, this conversation, and the files touched during the implementation.
Canonical roles replaced the old token set
The runtime, theme parser, site CSS, persona themes, and public theme copies were all moved to the canonical role schema. This was not a compatibility layer. It was a full cutover.
Missing keys now fail soft instead of falling apart
If a canonical role is missing, the parser and runtime now merge against defaults so the UI stays intact instead of collapsing into partial styling.
Obsidian stopped being a separate styling universe
The live Obsidian theme output is now generated from the same source theme data as the site. The packaged WebGrid theme is a thin wrapper over generated CSS, which keeps the package simple and keeps the real styling source centralized.
Theme switching got much less awkward
The active theme is sourced from content/_site.md again, which puts the decision back where it belongs. The theme index stays around for package metadata and compatibility, but users no longer need to guess file paths by hand. The picker scans available themes, shows the active one clearly, and lets you switch with a button.
Light and dark mode are now one click away
The theme index picker can now trigger Obsidian's built-in light/dark toggle directly, so the note where you manage themes also manages the current mode.
Docs were brought back into alignment
README, QUICKSTART, INSTRUCTIONS, the rewrite plan, and the backlog all now reflect the canonical workflow instead of the half-old, half-new version of reality.
Validation snapshot
npm run checkpassesnpm run buildpasses- No legacy color token keys remain in active runtime theme paths
- Obsidian live UI updates are wired and responding to theme changes
There are still a couple of manual smoke checks worth doing around Astro localStorage theme overrides and palette-renderer live preview parity, but the rewrite itself is shipped.
The short version
WebGrid themes are no longer a collection of polite agreements between separate systems.
They are one system now.
That is the release.