Skip to main content

max / makenotwork

server: take themes from published makeover instead of shared/themes theming embedded shared/themes via include_dir!, which needs a literal path at compile time and so could not survive the move to a registry crate. makeover 0.9.0 embeds the set itself and exposes it as (id, source) pairs, so the server drops its own include_dir dependency and reads the shared set directly. Note: palenight was dropped upstream over unresolvable provenance. A creator who had selected it falls back to the platform default, which theme_css and normalize_theme_id already handle for unknown ids.
Author: Max Johnson <me@maxj.phd> · 2026-07-19 19:47 UTC
Commit: ac22ade753a92dc309464dc36344c6420573d3db
Parent: a5fdabf
4 files changed, +20 insertions, -34 deletions
M server/Cargo.lock +12 -10
@@ -4358,11 +4358,11 @@ dependencies = [
4358 4358 "hex",
4359 4359 "hmac 0.12.1",
4360 4360 "http-body-util",
4361 - "include_dir",
4362 4361 "infer",
4363 4362 "jsonwebtoken",
4364 4363 "lightningcss",
4365 4364 "log",
4365 + "makeover",
4366 4366 "memmap2",
4367 4367 "metrics",
4368 4368 "metrics-exporter-prometheus",
@@ -4384,7 +4384,6 @@ dependencies = [
4384 4384 "syntect",
4385 4385 "tagtree",
4386 4386 "tempfile",
4387 - "theme-common",
4388 4387 "thiserror 2.0.18",
4389 4388 "tokio",
4390 4389 "tokio-stream",
@@ -4416,6 +4415,17 @@ dependencies = [
4416 4415 ]
4417 4416
4418 4417 [[package]]
4418 + name = "makeover"
4419 + version = "0.9.0"
4420 + source = "registry+https://github.com/rust-lang/crates.io-index"
4421 + checksum = "8901217cbffb659a961ac7b63fbfb72bacd4eda13b1d5a7329a9ffed54616165"
4422 + dependencies = [
4423 + "include_dir",
4424 + "serde",
4425 + "toml",
4426 + ]
4427 +
4428 + [[package]]
4419 4429 name = "maplit"
4420 4430 version = "1.0.2"
4421 4431 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7244,14 +7254,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
7244 7254 checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
7245 7255
7246 7256 [[package]]
7247 - name = "theme-common"
7248 - version = "0.7.0"
7249 - dependencies = [
7250 - "serde",
7251 - "toml",
7252 - ]
7253 -
7254 - [[package]]
7255 7257 name = "thiserror"
7256 7258 version = "1.0.69"
7257 7259 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,10 +123,8 @@ docengine = { path = "../shared/docengine", features = ["doc-loader", "directive
123 123 # Tag standard
124 124 tagtree = { path = "../shared/tagtree" }
125 125
126 - # Shared theme palette (Tier 0 creator theming). Themes are embedded at compile
127 - # time from shared/themes/ via include_dir, so production needs no themes path.
128 - theme-common = { path = "../shared/theme-common" }
129 - include_dir = "0.7"
126 + # Shared theme palette + the bundled theme set (Tier 0 creator theming).
127 + makeover = "0.9.0"
130 128
131 129 # Git source browser
132 130 git2 = { version = "0.20", features = ["vendored-libgit2"] }
@@ -7,7 +7,7 @@
7 7 # remote we did not sanction.
8 8 #
9 9 # The `licenses` check is intentionally NOT part of the gate command yet: three
10 - # first-party path crates (docengine, s3-storage, theme-common) ship without a
10 + # first-party path crates (docengine, s3-storage) ship without a
11 11 # `license` field, which `cargo deny check licenses` rejects. Giving those
12 12 # crates an explicit license (MIT for reusable infra, per the licensing
13 13 # strategy) is a separate cleanup; the allow-list below is kept current so the
@@ -1,14 +1,14 @@
1 1 //! Tier 0 creator theming.
2 2 //!
3 - //! The platform ships a set of built-in palettes (`shared/themes/*.toml`, the
4 - //! same theme-common format the desktop apps emit and consume). A creator may
3 + //! The platform ships a set of built-in palettes (the themes `makeover`
4 + //! embeds, the same set the desktop apps consume). A creator may
5 5 //! pick one for their public profile and for each project; items inherit their
6 6 //! parent project's choice. `None` everywhere means the platform default,
7 7 //! [`DEFAULT_THEME_ID`].
8 8 //!
9 9 //! Themes are embedded at compile time so production needs no themes directory
10 10 //! on disk. Each theme is resolved to its intent tokens and rendered once via
11 - //! [`theme_common::intent_css_vars`] and cached; page handlers inject the
11 + //! [`makeover::intent_css_vars`] and cached; page handlers inject the
12 12 //! rendered string into the page `<head>`, where it overrides the default
13 13 //! intent `:root` from `static/style.css` (the brand aliases derive from there,
14 14 //! so the whole page re-themes). This is the single TOML -> CSS mapping shared
@@ -17,11 +17,7 @@
17 17 use std::collections::BTreeMap;
18 18 use std::sync::LazyLock;
19 19
20 - use include_dir::{Dir, include_dir};
21 - use theme_common::{ThemeMeta, intent_css_vars, parse_theme_str, resolve};
22 -
23 - /// The bundled themes, embedded from the shared crate at compile time.
24 - static THEMES_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/../shared/themes");
20 + use makeover::{ThemeMeta, embedded_themes, intent_css_vars, parse_theme_str, resolve};
25 21
26 22 /// The platform default theme id — the stock parchment look. Reproduces the
27 23 /// historical `:root` exactly, so an unset (`None`) choice renders unchanged.
@@ -38,17 +34,7 @@ pub struct ThemeEntry {
38 34 /// Registry of built-in themes keyed by id, sorted by id for a stable picker.
39 35 static REGISTRY: LazyLock<BTreeMap<String, ThemeEntry>> = LazyLock::new(|| {
40 36 let mut map = BTreeMap::new();
41 - for file in THEMES_DIR.files() {
42 - let path = file.path();
43 - if path.extension().and_then(|e| e.to_str()) != Some("toml") {
44 - continue;
45 - }
46 - let Some(id) = path.file_stem().and_then(|s| s.to_str()) else {
47 - continue;
48 - };
49 - let Some(content) = file.contents_utf8() else {
50 - continue;
51 - };
37 + for (id, content) in embedded_themes() {
52 38 match parse_theme_str(id, content, false) {
53 39 Ok(theme) => {
54 40 let tokens = resolve(&theme);