Appearance
Build Process
The web frontend build is handled by web/build.ts using Bun's built-in bundler.
Build Script
The build script (web/build.ts) compiles the TypeScript source into a single JavaScript bundle with the following steps:
- Read configuration: In dev mode, reads
config/main.config.json(legacy fallback:main.config.json) for endpoint URLs. In release mode, uses fixed production values. - Define constants: Injects build-time constants via
Bun.builddefines:CERT_ISSUER— JWT issuer for token validationCERT_AUDIENCE— JWT audienceSERVER_ENDPOINT— HTTP API base URLSERVER_WS_ENDPOINT— WebSocket endpoint URLVERSION— Build version stringBUILD_DATE— Build timestamp
- Bundle: Compiles
src/web.tsand all imports intobuild/js/web.jswith external sourcemaps
Build Modes
Development
bash
cd web
bun run devReads endpoints from config/main.config.json (legacy fallback: project-root main.config.json). Uses concurrently to run:
nodemonwatchingsrc/for changes → rebuilds on savelive-serveron port 8090 servingbuild/
Production
bash
cd web
bun run build
# or from root:
bun build:server # includes web buildIn release mode (triggered by --release flag), the build script uses production values from the active brand instead of config file endpoint values. The HTTP and WebSocket endpoints are set to relative paths ("./" and "./ws") so the frontend works at any mount point — whether served at the domain root (/) or behind a reverse proxy subpath (e.g. /safecall/app/). The browser resolves these relative to the page URL at runtime.
Output Structure
web/build/
├── index.html # Main HTML page
├── css/
│ ├── styles.css # Custom styles
│ ├── bulma.min.css # Bulma CSS framework
│ └── fontawesome.min.css # Font Awesome icons
└── js/
└── web.js # Bundled applicationServer Embedding
The built web files are embedded into the server binary during the server build process:
scripts/build/generators/embeds.tsreads all files fromweb/build/- Generates
server/src/static_embeds.tswith Base64-encoded file contents - The server serves these embedded files for static asset routes (
/,/css/*,/js/*, etc.)
This means the production server is a single self-contained binary with the web UI built in.
Security Note
The config file is never included in the web build. Only specific, non-sensitive values (endpoint URLs, JWT issuer/audience) are injected as build-time constants. Sensitive credentials (passwords, MQTT credentials, KISS credentials) remain server-side only.