Skip to content

forge-host

The forge-host crate is the main runtime executable that runs Forge applications. It embeds the Deno runtime and manages native windows, IPC, and system integration.

Overview

forge-host is launched by forge dev or bundled into the final application. It handles:

  • Deno runtime - Embeds JsRuntime for executing TypeScript/JavaScript
  • Window management - Creates and manages native windows via tao/wry
  • IPC bridge - Routes messages between Deno and WebView renderers
  • Module loading - Resolves host:* imports to extension modules
  • Asset serving - Serves app:// protocol from filesystem or embedded assets
  • Hot reload - WebSocket server for development hot module reload

Architecture

┌─────────────────────────────────────────────────────────────┐
│ forge-host │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────────────────┐ │
│ │ Deno JsRuntime │◄────►│ Event Loop (tao) │ │
│ │ (app logic) │ │ (windows, menus, tray) │ │
│ └────────┬────────┘ └──────────────┬──────────────┘ │
│ │ │ │
│ │ host:* ops │ WebView IPC │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────────────────┐ │
│ │ Extensions │ │ WebView (wry) │ │
│ │ fs,net,ui,ipc.. │ │ (renders app:// content) │ │
│ └─────────────────┘ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Module Loading

The ForgeModuleLoader handles module resolution:

  1. host:* specifiers - Maps to ext:host_*/init.js
  2. TypeScript files - Transpiled via deno_ast
  3. JavaScript files - Loaded directly
  4. JSON files - Parsed as JSON modules
host_fs/init.js
// host:window → ext:host_window/init.js

Asset Protocol

The app:// protocol serves web assets:

  • Development mode: Files read from {app_dir}/web/
  • Production mode: Files embedded in binary via build.rs
// app://index.html → {app_dir}/web/index.html
// app://styles/main.css → {app_dir}/web/styles/main.css

Event Loop

The main event loop (via tao) handles:

  • Window events (close, resize, focus, move)
  • Menu events (app menu, context menu)
  • Tray events (click, menu selection)
  • IPC messages (renderer → Deno)
  • HMR events (file watcher → WebSocket)

Manifest

Applications are configured via manifest.app.toml:

[app]
name = "My App"
identifier = "com.example.myapp"
version = "0.1.0"
crash_reporting = true
[windows]
width = 800
height = 600
resizable = true
[permissions]
fs = { read = ["~/.myapp/*"], write = ["~/.myapp/*"] }

Key Types

Manifest

Application configuration parsed from manifest.app.toml:

struct Manifest {
app: App,
windows: Option<Windows>,
permissions: Option<Permissions>,
}
struct App {
name: String,
identifier: String,
version: String,
crash_reporting: Option<bool>,
}

Preload Script

The preload script (from sdk/preload.ts) is injected into every WebView:

  • Provides window.host.send() and window.host.on() API
  • Bridges renderer to Deno via IPC
  • Handles __host_dispatch for Deno → renderer messages

File Structure

crates/forge-host/
├── src/
│ ├── main.rs # Entry point, event loop, runtime setup
│ ├── capabilities.rs # Permission system adapters
│ └── crash.rs # Crash reporting
├── build.rs # Asset embedding, preload compilation
└── Cargo.toml

Dependencies

DependencyPurpose
deno_coreJavaScript runtime
deno_astTypeScript transpilation
taoWindow management, event loop
wryWebView rendering
tokioAsync runtime
notifyFile watching (HMR)
mudaMenu system
tray-iconSystem tray
rfdFile dialogs