Copyright Since 2005 ColdBox Platform by Luis Majano and Ortus Solutions, Corp
www.coldbox.org |
www.ortussolutions.com
Production-ready desktop application template built with ColdBox, BoxLang MiniServer, Electron, Vite, Alpine.js, and Bootstrap.
This template gives you a full desktop shell around a local BoxLang web application. Electron owns the native desktop lifecycle, while BoxLang MiniServer serves the app locally and the BrowserWindow loads it like a native desktop experience.
- ColdBox application structure inside a desktop runtime
- Electron shell with window lifecycle, menu, tray, and shortcuts
- Local BoxLang MiniServer process managed by Electron
- Vite build pipeline for JS and SCSS assets
- Electron Forge packaging for macOS, Windows, and Linux
- Packaged MiniServer runtime under
runtime/binandruntime/lib - Development and production runtime config split via
.boxlang-dev.jsonand.boxlang.json
app/
config/
electron/
handlers/
interceptors/
layouts/
models/ (includes ViteHelper.bx)
modules/
views/
public/
Application.bx
index.bxm
includes/
resources/
assets/
fonts/
js/
scss/
runtime/
Package.bx
VERSION
bin/
lib/
modules/
miniserver.json
forge.config.cjs
vite.config.mjs
- Electron starts from
app/electron/Main.js Main.jswires the desktop modulesapp/electron/BoxLang.jsstarts BoxLang MiniServer usingminiserver.json- MiniServer loads the ColdBox app from
public/ - Electron waits for the local URL to become ready, then loads it in a
BrowserWindow
app/electron/Main.js: Electron bootstrap and module wiringapp/electron/BoxLang.js: MiniServer process management, readiness checks, restart strategyapp/electron/AppMenu.js: app menuapp/electron/TrayMenu.js: tray integrationapp/electron/Shortcuts.js: global keyboard shortcutsapp/config/Coldbox.bx: ColdBox configurationapp/config/Router.bx: routespublic/Application.bx: web-facing bootstrappublic/index.bxm: default entry pointminiserver.json: MiniServer host, port, web root, and dev runtime configruntime/Package.bx: MiniServer runtime packagervite.config.mjs: frontend asset build configforge.config.cjs: Electron Forge packaging config
- BoxLang OS runtime
- CommandBox
- Node.js
- Java 21+
Important: This template packages the BoxLang MiniServer runtime, but it does not package a JRE/JDK. Java 21+ must already be available on the host machine.
box install
npm installnpm run devThis starts Vite and then launches Electron once the dev server is available.
Builds frontend assets and outputs them to public/includes/resources/:
npm run buildRuns the built application without development mode:
npm run prodGenerates platform-specific icon files from the PNG source iconset:
npm run generate:iconsThis creates:
public/includes/icon.icns- macOSpublic/includes/icon.ico- Windowspublic/includes/icon.png- Generic fallback
Packages the application as a distributable for your platform:
# Current platform
npm run package
# Specific platform
npm run package:mac
npm run package:win
npm run package:linux
# Full packaging (downloads MiniServer runtime first)
npm run package:fullDownloads and extracts the BoxLang MiniServer runtime into runtime/bin/ and runtime/lib/:
npm run package:miniserverThe version is controlled by .bvmrc.
This template uses Electron Forge for building and packaging desktop applications.
macOS (npm run package:mac)
- Output:
dist/Electron/directory - Files:
ColdBox-BoxLang-Desktop-x.x.x-arm64.dmg,.zip - Code signing: Requires
CSC_*orAPPLE_*environment variables
Windows (npm run package:win)
- Output:
dist/Electron/directory - Files: NSIS installer
.exe,.msi,.zip(Squirrel.Windows) - Icon: Reads from
public/includes/icon.ico(generated bynpm run generate:icons) - Requires: Node.js 20 LTS (cross-zip dependency compatibility)
Linux (npm run package:linux)
- Output:
dist/Electron/directory - Files:
.deb,.rpm,.flatpak,.zip - Icon: Uses
public/includes/icon.png
forge.config.cjs controls all packaging behavior:
asar: Always false (MiniServer must be spawned as a real filesystem executable)icon: Resolves topublic/includes/icon(Forge appends platform-specific extensions)makers: Array of active makers (dmg, zip for macOS; squirrel, zip for Windows; deb, rpm, flatpak for Linux)postMake: Hook that copies unsigned-build helper scripts into ZIP artifacts
Forge resolves icon filenames by appending platform-specific extensions:
| Platform | Icon File | Required | Generated by |
|---|---|---|---|
| macOS | public/includes/icon.icns | Yes | npm run generate:icons |
| Windows | public/includes/icon.ico | Yes | npm run generate:icons |
| Linux | public/includes/icon.png | No | Included in repo |
Missing icons will cause build failures on the target platform.
Icons are stored in public/includes/icon.iconset/:
public/includes/
└── icon.iconset/
├── icon_16x16.png
├── icon_32x32.png
├── icon_64x64.png
├── icon_128x128.png
├── icon_256x256.png
├── icon_512x512.png
└── icon_1024x1024.png
Run npm run generate:icons to create:
public/includes/icon.icns(macOS)public/includes/icon.ico(Windows)
These generated files should be committed to your repository to ensure faster CI builds and consistent packaging.
miniserver.json
Controls the local development server:
{
"app": {
"name": "ColdBox BoxLang Desktop",
"logdir": "./logs"
},
"server": {
"port": 59700,
"host": "127.0.0.1",
"webroot": "./public"
},
"warmupUrl": "http://127.0.0.1:59700/",
"healthCheckUrl": "http://127.0.0.1:59700/health"
}.boxlang-dev.json
Development-only overrides (loaded by miniserver.json):
{
"boxlang": {
"compiler": {
"nullChecking": true
},
"runtime": {
"allowImplicitStructKeyAccess": true
}
}
}.boxlang.json
Production configuration (used in packaged builds):
{
"boxlang": {
"compiler": {
"nullChecking": false
}
}
}The Vite pipeline compiles assets to public/includes/resources/:
resources/
└── assets/
├── fonts/ → public/includes/resources/fonts/
├── js/
│ └── app.js → public/includes/resources/app-[hash].js
└── scss/
└── app.scss → public/includes/resources/app-[hash].css
Use the ViteHelper to load assets automatically:
<!-- app/layouts/Main.bxm -->
<head>
#viteHelper.asset( "resources/assets/js/app.js" )#
#viteHelper.asset( "resources/assets/scss/app.scss" )#
</head>The helper automatically:
- Development: Loads from Vite dev server (HMR enabled)
- Production: Loads compiled & hashed assets from
public/includes/resources/
npm run dev # Start Vite dev server + Electron (development)
npm run build # Build Vite assets for production
npm run start # Start Electron only (assumes Vite already running)
npm run prod # Production build + production runtime config
npm run package # Package current platform (create installers/DMG)
npm run package:mac # Package macOS DMG + ZIP
npm run package:win # Package Windows installer + ZIP
npm run package:linux # Package Linux deb/rpm/flatpak + ZIP
npm run package:full # Download MiniServer runtime + package current platform
npm run generate:icons # Generate platform-specific icon files# Terminal 1: Start development
npm run dev
# This starts:
# 1. Vite dev server at http://127.0.0.1:3000
# 2. BoxLang MiniServer at http://127.0.0.1:59700
# 3. Electron window loading http://127.0.0.1:59700
# Edit your .bxm templates or .bx handlers → immediate reload
# Edit your JS/SCSS in resources/assets/ → HMR updates in window# Build Vite assets
npm run build
# Test production build locally
npm run prod
# Package for distribution
npm run package:full # If MiniServer runtime needs re-downloading
npm run package # If MiniServer runtime already packagedSymptom: Electron window is blank or shows "Connection refused"
Likely Causes:
- Java 21+ not installed:
java --version - Port 59700 already in use:
lsof -i :59700 - BoxLang runtime not packaged:
npm run package:miniserver
Solutions:
# Verify Java is installed
java --version
# Kill process on port 59700
lsof -i :59700 | grep LISTEN | awk '{print $2}' | xargs kill -9
# Re-package MiniServer runtime
npm run package:miniserver
# Restart development
npm run devSymptom: runtime/bin/boxlang-miniserver: Permission denied
Solution:
chmod +x runtime/bin/boxlang-miniserver
npm run devSymptom: "Fatal error: Unable to set icon" during npm run package:win
Cause: public/includes/icon.ico missing
Solution:
npm run generate:icons
npm run package:winSymptom: CSS/JS not loading in dev-mode window
Likely Causes:
- Vite dev server not started (verify port 3000)
- ViteHelper not loading assets correctly
- publicDir setting disabled in vite.config.mjs
Solutions:
# Ensure both servers are running
npm run dev
# In a separate terminal, verify Vite server
curl http://127.0.0.1:3000
# Check ViteHelper.bx is loaded in your layout
grep -r "include.*ViteHelper" app/Symptom: Windows build fails with "fs.rmdir recursive not supported"
Cause: cross-zip (Forge dependency) requires Node.js 20 LTS; Node 22+ removed fs.rmdir
Solution:
# Use Node 20 LTS
nvm use 20
npm run package:win- ColdBox Documentation
- BoxLang Documentation
- Electron Documentation
- Electron Forge Documentation
- Vite Documentation



