vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Derive theme metadata from the stylesheet file name
d222b0cf5d23444ea5df9429ec7d3690407dd00c · Keenan Nemetz · 1d ago · parent f7a34d87
Derive theme metadata from the stylesheet file name profile/themes/index.json is gone. Each profile/themes/<id>.css is self-describing: the file name is the id and the label (acme-ocean.css becomes Acme Ocean), and the rules are scoped to that id. The loader discovers the files, validates the names, and sorts them by label. Remove the manifest from the starter repository, its README, the Admin Configuration path table, and the configuration docs. An old index.json in an existing repository is ignored.
forge/instancerepo/seed.go +13−21
| @@ -84,8 +84,7 @@ notes can live here too. | |||
| 84 | 84 | profile/README.md the landing page introduction (markdown) | |
| 85 | 85 | profile/private/README.md replaces it for signed-in viewers | |
| 86 | 86 | profile/custom.css instance-wide styles, loaded after the theme | |
| 87 | profile/themes/index.json lists the themes offered in Account -> Appearance | ||
| 88 | profile/themes/<id>.css one stylesheet per theme | ||
| 87 | profile/themes/<id>.css one stylesheet per theme in Account -> Appearance | ||
| 89 | 88 | profile/favicon.svg replaces the built-in favicon | |
| 90 | 89 | assets/ served at /static/custom/assets/ | |
| 91 | 90 | ||
| @@ -100,16 +99,9 @@ viewers), even when the repository itself is private. | |||
| 100 | 99 | ## Themes | |
| 101 | 100 | ||
| 102 | 101 | The Account page's Appearance picker lists the built-in Everforest variants and | |
| 103 | every theme in profile/themes/index.json. Add one by creating its stylesheet and | ||
| 104 | listing it: | ||
| 105 | |||
| 106 | profile/themes/index.json | ||
| 107 | { | ||
| 108 | "themes": [ | ||
| 109 | { "id": "acme-ocean", "name": "Acme Ocean" }, | ||
| 110 | { "id": "acme-paper", "name": "Acme Paper" } | ||
| 111 | ] | ||
| 112 | } | ||
| 102 | every CSS file in profile/themes/. A theme is self-describing: its file name is | ||
| 103 | the id and the label, and its rules are scoped to that id. Add one by creating | ||
| 104 | the stylesheet: | ||
| 113 | 105 | ||
| 114 | 106 | profile/themes/acme-ocean.css | |
| 115 | 107 | :root[data-theme="acme-ocean"] { | |
| @@ -139,8 +131,9 @@ listing it: | |||
| 139 | 131 | --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent); | |
| 140 | 132 | } | |
| 141 | 133 | ||
| 142 | The id must be lowercase letters, digits, and dashes. It cannot be "system" or | ||
| 143 | start with "everforest-", which are the built-in values. Each stylesheet is | ||
| 134 | The file name becomes the id and the label: acme-ocean.css is the "Acme Ocean" | ||
| 135 | theme. It must use lowercase letters, digits, and dashes, and cannot be "system" | ||
| 136 | or start with "everforest-", which are the built-in values. Each stylesheet is | ||
| 144 | 137 | loaded after the built-in sheets and before profile/custom.css, and its rules | |
| 145 | 138 | apply only while that theme is selected. Set color-scheme and the tokens the | |
| 146 | 139 | theme changes: a light theme needs color-scheme: light and light surface and | |
| @@ -148,19 +141,18 @@ text tokens. | |||
| 148 | 141 | ||
| 149 | 142 | profile/custom.css applies to every theme, so keep instance-wide overrides | |
| 150 | 143 | there and put a selectable palette in profile/themes/<id>.css. Keep each theme | |
| 151 | file small: every listed theme is linked on every page. | ||
| 144 | file small: every theme is linked on every page. | ||
| 152 | 145 | ||
| 153 | The picker stores the choice in the browser, not on the account. A theme removed | ||
| 154 | from index.json falls back to System the next time the page loads. | ||
| 146 | The picker stores the choice in the browser, not on the account. A theme whose | ||
| 147 | file is deleted falls back to System the next time the page loads. | ||
| 155 | 148 | `), | |
| 156 | "profile/README.md": []byte("# " + name + "\n\nTell people what this forge is for. This file is the landing page introduction.\n"), | ||
| 157 | "profile/themes/index.json": []byte("{\n \"themes\": []\n}\n"), | ||
| 149 | "profile/README.md": []byte("# " + name + "\n\nTell people what this forge is for. This file is the landing page introduction.\n"), | ||
| 158 | 150 | "profile/custom.css": []byte(`/* Custom styles. This file is loaded last: after vole.css, everforest.css, and | |
| 159 | 151 | * any profile/themes/<id>.css, so it can override every theme. | |
| 160 | 152 | * | |
| 161 | 153 | * For a palette that appears in Account -> Appearance, add | |
| 162 | * profile/themes/<id>.css and list it in profile/themes/index.json. This file | ||
| 163 | * is for overrides that apply no matter which theme is selected. | ||
| 154 | * profile/themes/<id>.css; its file name is the id and label. This file is for | ||
| 155 | * overrides that apply no matter which theme is selected. | ||
| 164 | 156 | * | |
| 165 | 157 | * Prefer tokens over rules: a token keeps the layout, contrast, and responsive | |
| 166 | 158 | * behaviour that the built-in sheets already got right. | |