nodebb-plugin-dark-skin
v1.0.1
Published
Admin-configurable dark skin for NodeBB with OS theme detection and a toggle
Readme
nodebb-plugin-dark-skin
Admin-configurable dark skin for NodeBB, with OS theme detection and a toggle.
Built for NodeBB 4.14+ and nodebb-theme-harmony.
What it does
- Adds a dark skin whose colours you set in the ACP. The palette is compiled through NodeBB's own custom-skin pipeline, so every colour Bootstrap derives from your variables — button hovers, borders, table stripes — is computed correctly rather than patched afterwards.
- Adds a toggle to the Harmony sidebar next to Harmony's own skin switcher, and
to the mobile bar below the
lgbreakpoint. The switcher is left in place. - Follows the visitor's OS theme until they choose for themselves.
- Works for guests: an explicit choice is stored in a cookie and applied during server-side rendering, so there is no flash of the wrong theme on reload.
Install
npm install nodebb-plugin-dark-skinThen activate it in ACP → Extend → Plugins and rebuild:
./nodebb build && ./nodebb restartConfigure
ACP → Plugins → Dark Skin (the plugin's own entry in the admin sidebar). Seven fields:
| Field | Default | Drives |
|---|---|---|
| Skin name | Dark Skin | the name shown in the skin switcher |
| Background | #1c1e22 | $body-bg, the dark end of the grey ramp |
| Text colour | #e6e6e6 | $body-color, the light end of the grey ramp |
| Primary / brand | #0d6efd | $primary |
| Secondary surface | #2a2e33 | $body-secondary-bg, $light, $body-tertiary-bg |
| Border | #3a3f44 | $border-color |
| Link | blank | $link-color; blank uses the primary colour |
Colours are hex, three or six digits. An invalid value falls back to that field's default rather than to a light colour.
Saving rebuilds the skin on the next page load; no ./nodebb build is needed.
What gets derived
Six fields are not enough to darken Bootstrap 5.3 — its grey ramp,
$light/$dark and the secondary/tertiary backgrounds all stay light unless
they are set explicitly, which is why themes like Bootswatch's darkly declare
several dozen variables. This plugin derives that set from the two anchors you
already give it, and emits 23 variables in total:
$gray-100…$gray-900— interpolated from the text colour (light end) to the background colour (dark end), keeping Bootstrap's usual ramp direction.$body-bg,$body-color,$body-emphasis-color— the last one is$blackin stock Bootstrap and also drives table striping and hover overlays.$body-secondary-bg,$body-tertiary-bg.$lightand$dark, inverted. Harmony's left sidebar is literallyclass="text-dark bg-light …", so without this it renders near-white against a dark body. The same inversion fixes.btn-lightand.text-bg-light, which core and Harmony use in well over a hundred places.$primary,$link-color,$link-hover-color— Bootstrap shades the hover colour towards black, which is the wrong direction over a dark background.$border-color,$border-color-translucent.$form-select-indicator-colorand$form-switch-color— both are interpolated into inline SVG data URIs, and Bootstrap's defaults disappear against a dark control.
Everything else Bootstrap 5.3 derives from these, mostly through
--bs-body-bg, --bs-secondary-bg and --bs-border-color.
How the light side works
This plugin owns the dark side only. The light side is whatever skin you have selected in ACP → Appearance → Skins, so your existing look is untouched.
Notes
- The toggle appears in two places. On desktop it sits in Harmony's left
sidebar, beside the skin switcher. Below the
lgbreakpoint that sidebar is hidden (d-none d-lg-flex), so the toggle is injected into the mobile bar instead, alongside search and notifications. Guests get it in both. - The OS preference is never persisted. It is applied client-side only, and it is never written to the visitor's account or to a cookie, so a member whose laptop is dark and whose phone is light gets the right skin on each. Once someone picks a skin — with this toggle or with Harmony's switcher — that choice wins from then on.
- Honours the ACP "Disable custom user skins" setting: with it on, the plugin stays out of the way entirely.
- The skin is registered in NodeBB's custom-skins list and tagged as belonging to this plugin. Skins you created by hand are never modified.
- Deactivating the plugin does not remove its skin from NodeBB's custom-skins list — NodeBB has no reliable server-side deactivation hook. Remove it by hand in ACP → Appearance → Skins if you no longer want it listed.
Development
npm testThe modules under lib/ are pure: they never require NodeBB, so the unit tests
run without a forum.
Licence
MIT — see LICENSE.
