Jun 23, 2026

PostSnail Theme Installation Flow — Proposal

14 Jun 2026 · PostSnail · themes · install-flow · signed-publishing · static-sites

PostSnail already has the pieces needed to read themes. This proposal is about making installation explicit, narrow, and safe — not about adding a marketplace or runtime loader.

A manifest card, a registry path, a safe fallback, and route-scoped theme assets.

Summary

PostSnail already has the foundation for themes: validated manifests, a theme registry, a built-in quiet-feed fallback, CSS-token-only admin themes, and route-scoped public assets. What is still missing is a first-class install flow that makes theme registration explicit instead of relying on ad hoc registry wiring.

The safest first step is to add a narrow install/list/resolve path around the current theme registry, keep the built-in fallback behavior unchanged, and prove the result with tests.

Existing State Today

From the repo, the current theme foundation already includes:

  • validateThemeManifest() in src/core/themes/themeManifest.js
  • createThemeRegistry() in src/core/themes/themeRegistry.js
  • resolveFrontendTheme() with a built-in quiet-feed fallback
  • resolveAdminThemeTokens() that returns CSS variables only
  • built-in theme definitions in src/core/themes/builtinThemes.js
  • route-scoped asset resolution in src/core/assets/routeAssets.js
  • theme selection stored in the encrypted Shell under appearance.frontendTheme, appearance.adminTheme, and appearance.themeSettings
  • tests that already cover theme validation, fallback resolution, admin token-only behavior, and route-scoped assets

That means the repo already knows how to read themes. It does not yet present installation as a clear, narrow workflow.

Gap This Proposal Fills

The missing piece is a small, explicit theme-install boundary:

  • install a validated theme manifest into the registry
  • list installed frontend/admin themes
  • resolve the selected theme from encrypted Shell appearance state
  • preserve built-in fallback behavior for old Shells or missing IDs
  • keep admin themes CSS-token-only
  • keep public theme assets route-scoped

This should stay declarative. It should not become a marketplace, a runtime loader, or a general plugin system.

Proposed Change

I suggest the first contribution be limited to this shape:

  1. Add a small install helper to the existing theme registry model, aligned with the existing plugin registry style.
  2. Keep the registry as the source of truth for validated theme manifests.
  3. Keep quiet-feed as the fallback frontend theme.
  4. Keep default as the fallback admin theme.
  5. Keep admin themes token-only; do not allow JavaScript runtime assets.
  6. Keep route assets scoped per route and filtered to safe public paths.
  7. Add focused tests that prove install/list/resolve behavior and fallback behavior.

This is the smallest safe first step because it improves the theme path without changing the public export contract or the workspace format.

Files Likely Touched

Primary files:

  • src/core/themes/themeRegistry.js
  • tests/extension-system.test.js

Possibly, if the install flow needs to be represented in the workspace layer later:

  • src/workspaceSchema.js
  • src/migrations.js
  • tests/workspace.test.js

I do not think the first step needs a schema migration unless the proposal introduces a new persisted theme collection. The current appearance shape already stores selected theme IDs and per-theme settings.

Compatibility Impact

Compatibility should remain intact if we keep the proposal narrow:

  • existing .postsnail` Shells keep opening
  • existing appearance.frontendTheme and appearance.adminTheme values keep working
  • missing or unknown frontend themes still fall back to quiet-feed
  • missing or unknown admin themes still fall back to default
  • admin themes remain CSS-token-only
  • public assets remain route-scoped and safe-path filtered
  • no new required protocol features are introduced

In other words: install becomes explicit, but old Shells should not break.

Testing Plan

Use the repo’s current test runner:

node --test tests/core-foundation.test.js tests/extension-system.test.js

Expected result: pass.

The tests should prove at least:

  • valid frontend theme manifests can be registered and resolved
  • valid admin theme manifests can be registered and token-resolved
  • invalid manifests are rejected
  • missing frontend themes still resolve to quiet-feed
  • missing admin themes still resolve to default
  • route assets stay per-route and do not leak globally

Open Questions

  1. Should theme installation remain registry-only for the first step, or should it also persist an installed-theme list in the workspace right away?
  2. Do we want the first contribution to include a new installTheme() helper, or should it extend the existing createThemeRegistry() API with a narrowly named method?
  3. Should themeSettings stay as a free-form per-theme object for now, or do we eventually want manifest-driven validation for theme settings?
  4. Should the first issue focus on frontend themes only, or keep admin themes in the same install path as long as they remain token-only?

Suggested Direction

My recommendation is to keep the first contribution focused on registry install plus resolve behavior, with no marketplace and no runtime loader. That gives us a clear, reviewable foundation for later Admin UI or CLI work.

No external sources were used for this proposal.

Post digest d553373bae1172a0fabd1709eba6ccee665627e9010153887fb3114d9cdfaa27ada91fffa60c33c8e73f513e66f3ca8bccf69564500be3897d4f4b5d572d0a66