# @tsuki/firefox-theme tsuki for Firefox 157+ (Nova). One adaptive theme: kami (paper) when your system is light, sumi (ink) when it's dark, with shu marking the active tab, loading state, and focused address bar. Two layers: - **Theme** (`tsuki-.xpi`) — colors only. Signed by Mozilla, self-hosted on Gitea, updates automatically. - **userChrome.css** (optional) — what the theme API can't reach: IBM Plex Sans, tsuki corner radii (4/6/8px instead of Nova's 12–24px), and shu in place of Nova's violet for focus rings, links, and primary buttons. Both are generated from [`@tsuki/tokens`](https://git.d-v.cc/tsuki/tokens). No hex values are written by hand. ## Install ### Theme Download `tsuki-.xpi` from the [latest release](https://git.d-v.cc/tsuki/firefox-theme/releases) and open it in Firefox. Firefox checks `updates.json` in this repo for new versions. ### userChrome.css 1. Open `about:config` and set `toolkit.legacyUserProfileCustomizations.stylesheets` to `true`. 2. Open `about:support` and click **Open Folder** next to *Profile Folder*. 3. Unzip `tsuki-userchrome-.zip` from the release and copy the contents of its `userChrome/` folder into a `chrome/` folder in your profile, giving you `chrome/userChrome.css` and `chrome/tsuki-fonts/`. 4. Restart Firefox. If you already have a `userChrome.css`, paste tsuki's at the top of yours and keep the `tsuki-fonts/` folder next to it. The overrides target Nova's design tokens (`--border-radius-*`, `--color-accent-primary`, `--focus-outline-color`), not element selectors, so they should survive most Firefox updates. Mozilla doesn't support userChrome.css, though, and a future release may rename these tokens. ## Design notes - **No gradients.** Nova encourages gradient themes. tsuki doesn't use them, and the tests fail on any `gradient` or `images` in the output. - **Selected tab = toolbar.** Both are `kami-0` / `sumi-100`, so the active tab reads as one sheet with the toolbar. Separation comes from color, not shadow. - **Dead Nova keys are omitted:** `ntp_text`, `sidebar_highlight`, `sidebar_highlight_text`. - **Contrast is tested:** text pairs ≥ 4.5:1, icons and accent marks ≥ 3:1, in both modes. To change a color, edit [`src/mapping.ts`](src/mapping.ts). ## Develop ```bash pnpm install pnpm build # dist/theme, dist/userChrome, updates.json pnpm test pnpm lint # web-ext lint (self-hosted rules) pnpm start # Firefox with the theme + userChrome, light pnpm start:dark # same, forced dark ``` `pnpm start` uses a throwaway profile in `.preview-profile/`, not your own. ### Test checklist (Mozilla's for Nova) Horizontal and vertical tabs · sidebar closed / open / expand-on-hover · compact density · private window · light and dark · hover states on tabs and toolbar buttons. ## Releasing Release Firefox only installs Mozilla-signed add-ons, so "self-hosted" means signed through AMO's **unlisted** channel (not published on addons.mozilla.org), then distributed from Gitea. One-time setup: 1. Create AMO API credentials at . 2. Add repo secrets: `AMO_JWT_ISSUER`, `AMO_JWT_SECRET`, `NPM_TOKEN` (registry read), `RELEASE_TOKEN` (Gitea token with repo write). 3. The repo must be public: Firefox fetches `updates.json` and the XPI without auth. Cut a release: ```bash npm version --no-git-tag-version pnpm build # regenerates updates.json for the new version git commit -am "release: vX.Y.Z" git tag vX.Y.Z git push --follow-tags ``` CI verifies `updates.json` is committed for the tag, signs the XPI, and attaches it and the userChrome zip to a Gitea release.