luci-theme-footstrap (the package)
A LuCI theme for OpenWrt 23.05 and newer (ucode templates). Installing and using it:
the repository README. Developer documentation: ../docs/.
Internal name: footstrap. Media path: /luci-static/footstrap.
One theme, one entry
luci.themes carries exactly one entry, Footstrap → /luci-static/footstrap. Layout (top bar
by default, or the side menu), mode, palette, density, wallpaper, rounding and every colour — accent,
the three status colours, the four surfaces — are client axes on the Footstrap tab of
System → System: localStorage plus attributes and inline properties on :root, and nothing is
written to the router until "Save as default" is pressed.
There are no per-layout or per-mode themes; every legacy name (FootstrapSidebar, FootstrapOnTop,
…-dark/…-light) is deleted by root/etc/uci-defaults/30_luci-theme-footstrap.
There is one menu renderer too, menu-footstrap.js. The top bar is its own markup, morphed by CSS
through :root[data-layout]. No second template, no second renderer, no footstrap-top symlink.
The theme's boundary: it supplies the chrome and the design language; page content is drawn by
the view JS of luci-mod-*. The one exception is fs-overview.js, which draws no content of its own
and only re-arranges the stock overview sections.
Layout
Makefile luci.mk; LUCI_MINIFY_CSS:=0; Build/Prepare (CSS, mangle, strip,
version, po2lmo)
styles/ CSS SOURCE: layers tokens / base / theme / pages
build-css.sh styles/ → htdocs/luci-static/footstrap/cascade.css
mangle-tokens.sh shorten the private --fs-* names in a built sheet
strip-templates.sh strip-shell.sh drop comments from .ut and from root/**.sh
po/ translation catalogue (Weblate translates this)
ucode/template/themes/footstrap/ header.ut, footer.ut, sysauth.ut, partials/
htdocs/luci-static/footstrap/ cascade.css (generated), logo.svg — no webfonts, and no
wallpaper: the Pattern is one the admin uploads, and a font
is one the admin installs (repo: fonts/set-font.sh)
htdocs/luci-static/resources/ menu-footstrap.js (renderer), menu-footstrap-common.js,
fs-{fit,menutree,prefs,widgets,chrome,router,sheets,search,
select,appearance,version,overview}.js
root/etc/uci-defaults/ registration and legacy-name migration
root/usr/share/rpcd/acl.d/ ACL: uci footstrap (Save as default) + login-background upload
There is no update checker: the theme is installed from the package feed (install.sh adds it), so
apk upgrade / opkg upgrade carries it forward like everything else on the router. The Footstrap
tab shows the version it is running and makes no network call to do it.
Do not edit cascade.css — it is generated by build-css.sh from styles/ and is gitignored.
Colours go in styles/03-palettes.css, scales and tokens in styles/02-tokens.css.
Working on a router
The normal dev stand is four containers driven by owlab from ../owlab.yaml — see
../docs/development.md. dev-sync.sh targets a hardware router over
ssh:
./dev-sync.sh # push to `ssh router` (registers the theme but does NOT activate it)
ssh router 'uci set luci.main.mediaurlbase=/luci-static/footstrap; uci commit luci; rm -f /tmp/luci-indexcache*'
ssh router 'uci set luci.main.mediaurlbase=/luci-static/bootstrap; uci commit luci' # roll back
Before pushing, run npm run check from the repository root. The rules and the traps are in
../docs/conventions.md; packaging is in
../docs/package.md.