Summary
Today the WP plugin lets users choose a bundle variant (optimal / optimal-components / optimal-utilities / full, × a flat flag), but the framework version is fixed at compile time via the single SLASHED_CSS_REF constant (slashed.php:32). This issue proposes letting users pin/select the framework version while staying fully within WordPress.org plugin guidelines on asset loading.
Filed for future consideration — no work started.
Key context: this re-opens a seam that already exists
The plugin previously had a per-version CDN loading mode that was collapsed to local-only for WordPress.org review. The fossils are still in the tree:
includes/class-token-page.php:220 ships 'css_source' => 'local' to the SPA — hardcoded, not computed.
admin-app/src/vite-env.d.ts:13 still types css_source?: string as a variable — the UI was built to branch on it.
scripts/update-framework.js comments reference "the plugin's runtime pinned-version CDN mode" and treat release bundles as the same artifacts that mode used.
- Everything funnels through one constant (
SLASHED_CSS_REF) and one resolver (Slashed_CSS_Loader::get_url() in includes/class-css-loader.php).
So this is not a new axis to invent — it's restoring the version axis while keeping css_source permanently local.
The one hard constraint (WordPress.org)
Anything that renders the site must be a file inside the plugin, served from the plugin folder. Frontend CSS is exactly that. Therefore:
- ✅ Choose among versions bundled locally → compliant.
- ❌ Fetch the selected version from a CDN / GitHub / jsDelivr at runtime (the old mode) → non-compliant.
- ❌ "Download version X into the plugin" button → remote code installation → non-compliant.
Every viable design is a variation of pre-place the versions locally, select among files.
Design principles
-
Version the DATA, not the UI. The expensive artifact (the vendored Svelte configurator) stays on one ref. Only the cheap JSON the SPA consumes — inventory.json, classes-hints.json, variables-hints.json (already localized at class-token-page.php:214-216) — plus the CSS bundles get versioned. Keep one SPA build; swap only the data it reads based on the selected version, so token pickers / hints / autocomplete become version-accurate with no SPA rebuild. This removes the biggest objection (configurator UI mismatch across versions).
-
Curate, don't enumerate. Offer a small deliberate set — Latest + one LTS/stable line — not "every release." ZIP math: CSS gzips ~85%, so each extra version is ≈300 KB in the delivered download plus ~30 KB of data. Two or three lines is negligible; "all versions" is the only untenable option and it isn't needed.
-
Companion "legacy pack" as the overflow valve. If deep history is ever needed, ship older bundles as a separate WordPress.org plugin (e.g. "SLASHED Legacy CSS") that registers them through the existing slashed/css_bundle_url filter (class-css-loader.php:68). Main plugin auto-detects and lists them. Still 100% compliant (official install channel, local files), main ZIP stays lean.
-
Reframe intent as stability/pinning. Most "I want an old version" really means "an update must not restyle my live site." Position the feature primarily as "Pin framework version" with default "Latest." SLASHED's named cascade layers + top-layer token overrides already resist most drift, so this matches real intent.
-
Pin version lines, not exact patches. Setting is 0.7.x / 0.6.x rather than v0.7.5. Minors are additive, majors break — pinning a line gives stability without chasing patch numbers, and lets a patch refresh within a line on plugin update without breaking the pin.
Proposed architecture (low blast radius — reuses existing seams)
| Layer |
Change |
| Layout |
dist/<version>/slashed.<bundle>[.flat].css and data/<version>/{inventory,classes-hints,variables-hints}.json instead of flat dirs |
| Registry |
New dist/versions.json — single source of truth: available versions, labels, default, min_wp, per-version compat notes. Keep SLASHED_CSS_REF as the default |
| Settings |
Add css_version beside css_bundle in Slashed_Settings, validated against the registry allowlist exactly like ALLOWED_BUNDLES (class-settings.php:33, :63-77) |
| Loader |
Slashed_CSS_Loader::get_url() inserts the version segment; get_version() mtime logic unchanged (class-css-loader.php:52-93). Missing file → '' → existing admin notice fires |
| SPA data |
class-token-page.php localizes the selected version's inventory/hints and flips __SLASHED_FW_VERSION__ (:191) to match — UI becomes version-accurate, no SPA rebuild |
| Build |
update-framework.js becomes additive: vendor into dist/<v>/ + data/<v>/ and append to versions.json, instead of overwriting the flat dir |
| Guard rail |
On save, diff the user's token overrides against the selected version's inventory and warn about overrides referencing tokens that version lacks |
css_source stays 'local' forever — but now it tells the truth about a real choice instead of masking a removed one.
Explicit non-goals
- Runtime CDN / on-demand download — the old mode; fails review.
- Reverse-diff/patch reconstruction of old CSS at runtime — runtime asset generation, fragile, buys nothing over bundling ~300 KB.
- Shipping N vendored SPA copies — unnecessary once data is versioned instead of UI.
Suggested phasing
versions.json registry + css_version setting + get_url() version segment (CSS selection working).
- Per-version data localization to the SPA (version-accurate pickers/hints).
- Additive
update-framework + settings-page UI ("Pin framework version").
- (Optional/later) companion legacy-pack plugin + override compat guard rail.
Filed from a design discussion; captured here for future consideration.
Summary
Today the WP plugin lets users choose a bundle variant (
optimal/optimal-components/optimal-utilities/full, × aflatflag), but the framework version is fixed at compile time via the singleSLASHED_CSS_REFconstant (slashed.php:32). This issue proposes letting users pin/select the framework version while staying fully within WordPress.org plugin guidelines on asset loading.Filed for future consideration — no work started.
Key context: this re-opens a seam that already exists
The plugin previously had a per-version CDN loading mode that was collapsed to local-only for WordPress.org review. The fossils are still in the tree:
includes/class-token-page.php:220ships'css_source' => 'local'to the SPA — hardcoded, not computed.admin-app/src/vite-env.d.ts:13still typescss_source?: stringas a variable — the UI was built to branch on it.scripts/update-framework.jscomments reference "the plugin's runtime pinned-version CDN mode" and treat release bundles as the same artifacts that mode used.SLASHED_CSS_REF) and one resolver (Slashed_CSS_Loader::get_url()inincludes/class-css-loader.php).So this is not a new axis to invent — it's restoring the version axis while keeping
css_sourcepermanentlylocal.The one hard constraint (WordPress.org)
Anything that renders the site must be a file inside the plugin, served from the plugin folder. Frontend CSS is exactly that. Therefore:
Every viable design is a variation of pre-place the versions locally, select among files.
Design principles
Version the DATA, not the UI. The expensive artifact (the vendored Svelte configurator) stays on one ref. Only the cheap JSON the SPA consumes —
inventory.json,classes-hints.json,variables-hints.json(already localized atclass-token-page.php:214-216) — plus the CSS bundles get versioned. Keep one SPA build; swap only the data it reads based on the selected version, so token pickers / hints / autocomplete become version-accurate with no SPA rebuild. This removes the biggest objection (configurator UI mismatch across versions).Curate, don't enumerate. Offer a small deliberate set — Latest + one LTS/stable line — not "every release." ZIP math: CSS gzips ~85%, so each extra version is ≈300 KB in the delivered download plus ~30 KB of data. Two or three lines is negligible; "all versions" is the only untenable option and it isn't needed.
Companion "legacy pack" as the overflow valve. If deep history is ever needed, ship older bundles as a separate WordPress.org plugin (e.g. "SLASHED Legacy CSS") that registers them through the existing
slashed/css_bundle_urlfilter (class-css-loader.php:68). Main plugin auto-detects and lists them. Still 100% compliant (official install channel, local files), main ZIP stays lean.Reframe intent as stability/pinning. Most "I want an old version" really means "an update must not restyle my live site." Position the feature primarily as "Pin framework version" with default "Latest." SLASHED's named cascade layers + top-layer token overrides already resist most drift, so this matches real intent.
Pin version lines, not exact patches. Setting is
0.7.x/0.6.xrather thanv0.7.5. Minors are additive, majors break — pinning a line gives stability without chasing patch numbers, and lets a patch refresh within a line on plugin update without breaking the pin.Proposed architecture (low blast radius — reuses existing seams)
dist/<version>/slashed.<bundle>[.flat].cssanddata/<version>/{inventory,classes-hints,variables-hints}.jsoninstead of flat dirsdist/versions.json— single source of truth: available versions, labels, default,min_wp, per-version compat notes. KeepSLASHED_CSS_REFas the defaultcss_versionbesidecss_bundleinSlashed_Settings, validated against the registry allowlist exactly likeALLOWED_BUNDLES(class-settings.php:33,:63-77)Slashed_CSS_Loader::get_url()inserts the version segment;get_version()mtime logic unchanged (class-css-loader.php:52-93). Missing file →''→ existing admin notice firesclass-token-page.phplocalizes the selected version's inventory/hints and flips__SLASHED_FW_VERSION__(:191) to match — UI becomes version-accurate, no SPA rebuildupdate-framework.jsbecomes additive: vendor intodist/<v>/+data/<v>/and append toversions.json, instead of overwriting the flat dircss_sourcestays'local'forever — but now it tells the truth about a real choice instead of masking a removed one.Explicit non-goals
Suggested phasing
versions.jsonregistry +css_versionsetting +get_url()version segment (CSS selection working).update-framework+ settings-page UI ("Pin framework version").Filed from a design discussion; captured here for future consideration.