The PurgeCSS content path for module templates was relative to the theme directory. Since the shipped themes moved to src/themes/default/* that path resolves to src/themes/modules, which does not exist, so production builds strip every class used only in module templates: client tab panes lose display:none and stack down the page, admin modal sections lose their layout, and form helpers such as col-form-label and input-group-text disappear. Development builds are unaffected because PurgeCSS only runs in production. Resolve the modules directory from the helper's own location instead, and add a test that a class referenced only by module templates survives purging. Co-authored-by: Kai Randles <kai.randles@streetkidsdirect.org.uk> Co-authored-by: Adam Daley <admdly@users.noreply.github.com>
Frontend and Theme Builds
FOSSBilling builds shared browser assets from frontend/ and theme assets from each theme workspace.
Build Commands
npm run buildchecks frontend source, builds core assets, and builds all themes.npm run build:productionruns the same build withNODE_ENV=production.npm run checkruns lightweight JavaScript syntax checks and validates theme icon manifests.npm run build-admin_defaultandnpm run build-huragabuild a single theme.
Generated assets are written to src/public/assets and src/themes/**/assets/build. These paths are ignored by Git and are copied into release artifacts by the Docker build.
Theme Dependencies
Themes own the UI packages they consume. Shared tooling in frontend/tools can help compile assets, generate sprites, and post-process CSS, but it should not make a theme depend on a specific UI package.
Examples (the shipped default theme package bundles both — src/themes/default/admin and src/themes/default/client; their npm workspace package names, admin_default and huraga, are unrelated to their directory paths):
admin_default(src/themes/default/admin) owns Tabler, Coloris, Chart.js, Litepicker, Tom Select, Flag Icons, and its Tabler icon package.huraga(src/themes/default/client) owns Bootstrap, Tom Select, Flag Icons, and its Tabler icon package.svg-spriteis a root development dependency because the shared sprite helper imports it.
Icons
Theme icon sprites are generated from each theme's icon-manifest.json.
- Add static SVG icon usage to the relevant theme manifest.
- Mark icons as
"dynamic": truewhen the icon name is resolved at runtime, such as admin navigation icons from module metadata. - Put theme-specific SVG files in the theme's
custom-iconsdirectory. - Reference generated symbols with inline sprite IDs, for example
<use href="#home" />.
Run npm run check-icons before changing icon usage.
CSS
Theme vendor CSS belongs in src/themes/**/assets/css/vendor.css. Theme-specific styles belong in the theme Sass entrypoint. Rules that are genuinely identical across the default admin and client themes belong in frontend/styles/_shared-theme.scss instead of being duplicated.
PurgeCSS runs only for production builds. A PurgeCSS failure fails production builds so release CSS problems are caught early.