Skip to content

Building & Compiling Guide

This guide covers the build pipeline, development workflow, and compilation process for creating distributable applications.

Development Workflow

tronbun dev

The fastest way to develop. Starts your app with hot reload:

bash
npx tronbun dev

What happens:

  1. Full build (backend + types + frontend)
  2. App launches with TRONBUN_DEV_MODE=true
  3. File watchers start monitoring:
Watch TargetExtensionsOn Change
Backend (src/).ts, .jsRebuild backend + types, restart app
Frontend (src/web/).ts, .tsx, .js, .jsx, .html, .cssRebuild frontend, hot reload (no restart)
Public (public/)All filesRebuild frontend

Hot reload works via a .dev-reload timestamp file. When the frontend detects the file has changed, it reloads content without restarting the native process.

Detecting dev mode in your code:

typescript
if (process.env.TRONBUN_DEV_MODE === "true") {
  // Enable dev tools, verbose logging, etc.
}

Build Process

tronbun build

Compiles your TypeScript source into runnable JavaScript:

bash
npx tronbun build
npx tronbun build --watch    # Rebuild on changes
npx tronbun build --dev      # Skip minification

Build steps:

  1. Backend build — Compiles backend.entry to backend.outDir using bun build

    • Target: bun runtime
    • Minification: respects build.minify (skipped in --dev mode)
    • Sourcemaps: respects build.sourcemap
  2. Type generation — Scans for @windowName and @mainHandler decorators, generates src/ipc-types.ts

  3. Frontend build — Compiles web.entry to web.outDir using bun build

    • Target: browser
    • Format: ESM (ES Modules)
    • Clears output directory before building
  4. Public assets — Copies contents of web.publicDir to web.outDir

tronbun run

Runs the previously built application:

bash
npx tronbun build && npx tronbun run

Executes bun dist/main.js (or whatever your built entry is).

tronbun clean

Removes build artifacts:

bash
npx tronbun clean

Deletes backend.outDir and web.outDir.

Compilation

tronbun compile

Creates a standalone native executable with all assets embedded:

bash
npx tronbun compile
npx tronbun compile -o my-app
npx tronbun compile --platform macos
npx tronbun compile --platform windows

How Compilation Works

Source files


Build (backend + frontend)


Collect web assets from dist/web/
    │  ├── Skip .map files
    │  ├── Remove sourcemap references
    │  └── Optionally obfuscate JS


Compress (gzip) + base64 encode


Generate embedded-assets.ts
    │  (registers __TRONBUN_EMBEDDED_FILES_COMPRESSED__)


bun build --compile


Copy native helpers (webview_main, tray_main, libnotification)


Platform packaging (Info.plist, code signing, etc.)


Clean up temporary files

macOS App Bundle

Output structure:

MyApp.app/
├── Contents/
│   ├── MacOS/
│   │   ├── MyApp                     # Main Bun executable
│   │   ├── webview_main              # Native webview process
│   │   ├── tray_main                 # Native tray process
│   │   └── libnotification.dylib     # Notification FFI library
│   ├── Resources/
│   │   ├── icon.icns                 # App icon
│   │   └── assets/                   # Copied from project assets/
│   └── Info.plist                    # Bundle metadata

Info.plist is generated with:

  • CFBundleIdentifier from app.identifier config
  • CFBundleIconFile pointing to icon.icns
  • LSUIElement = true (no dock icon by default)
  • NSHighResolutionCapable = true (Retina support)
  • Minimum macOS version: 10.15
  • Optional LSApplicationCategoryType from app.category

The bundle is ad-hoc code signed with codesign --force --deep -s -.

Windows Executable

Output structure:

build/
├── MyApp.exe                         # Main Bun executable
├── webview_main_win.exe              # Native webview process
├── tray_main_win.exe                 # Native tray process
└── libnotification.dll               # Notification FFI library

All files in build/ must be distributed together.

Asset Embedding

All web assets are embedded into the executable:

  • No external dist/ folder needed in distribution
  • Assets are gzip-compressed and base64-encoded (40-80% size reduction)
  • Available at runtime as globalThis.__TRONBUN_EMBEDDED_FILES_COMPRESSED__
  • Window.navigate() auto-detects compiled mode and uses setHtml() with embedded content

Code Obfuscation

Enable in tronbun.config.json to protect frontend code:

json
{
  "build": {
    "obfuscation": {
      "enabled": true,
      "compact": true,
      "stringArray": true,
      "stringArrayEncoding": ["base64"]
    }
  }
}

Obfuscation is applied only during compilation, not during build or dev.

Warnings:

  • renameGlobals: true breaks window.* IPC APIs
  • selfDefending: true may cause issues with React
  • unicodeEscapeSequence: true impacts performance

See Configuration for all options.

Native Prerequisites

Before compiling, you need the native webview components built:

bash
cd webview && make all

This compiles platform-specific binaries:

  • macOS: webview_main, tray_main, TronbunNotifier.app, libnotification.dylib
  • Windows: webview_main_win.exe, tray_main_win.exe, libnotification.dll

These are required by the compile step and are copied into the app bundle.

Cross-Compilation

Use --platform to target a specific platform:

bash
# On macOS, target macOS explicitly
npx tronbun compile --platform macos

# Target Windows (requires Windows native binaries)
npx tronbun compile --platform windows

The default (auto) detects the current platform.

Note: Cross-compilation requires having the target platform's native binaries available. Building Windows binaries on macOS (or vice versa) requires cross-compilation of the native C/C++ components.

Customizing Output

Custom executable name

bash
npx tronbun compile -o "My Cool App"

App icon

Set in tronbun.config.json:

json
{
  "app": {
    "icon": "assets/icon.icns",
    "iconWin": "assets/icon.ico"
  }
}

Bundle identifier

json
{
  "app": {
    "identifier": "com.mycompany.myapp",
    "category": "public.app-category.productivity"
  }
}

See Also

Released under the GPLv3 License.