3.3 KiB
3.3 KiB
AGENTS.md - Desktop App Guidelines
Electrobun desktop shell — loads the server app in a native window.
⚠️ This project uses Bun — NOT Node.js / npm. All commands use
bun. Never usenpm,npx, ornode.
Architecture
- Type: Electrobun desktop application
- Design: Bun main process + CEF renderer (Chromium Embedded Framework)
- Dev mode: Connects to
localhost:3000(requires server dev running) - Prod mode: Embeds server bundle and starts local HTTP server
- Config:
electrobun.config.ts— app metadata, build entrypoint, platform options
Commands
# Development (from apps/desktop/)
bun dev # Start Electrobun dev mode
# Build
bun build # Build canary release (current platform)
bun build:all # Build canary release (all platforms)
bun build:stable # Build stable release (current platform)
bun build:stable:all # Build stable release (all platforms)
# Code Quality
bun fix # Biome auto-fix (lint + format)
bun typecheck # TypeScript check
Directory Structure
apps/desktop/
├── src/
│ └── bun/
│ └── index.ts # Main process entry (BrowserWindow + server wait)
├── electrobun.config.ts # App name, identifier, version, build config
├── package.json
├── tsconfig.json # Extends @furtherverse/tsconfig/bun.json
└── turbo.json # Build output config
Development Workflow
- Start server dev first:
bun devfromapps/server/ - Start Electrobun:
bun devfromapps/desktop/ - Desktop app polls
localhost:3000until server responds, then opens window
Electrobun Patterns
Config (electrobun.config.ts)
import type { ElectrobunConfig } from 'electrobun'
export default {
app: {
name: 'MyApp',
identifier: 'com.example.myapp',
version: '0.1.0',
},
build: {
bun: { entrypoint: 'src/bun/index.ts' },
linux: { bundleCEF: true },
},
} satisfies ElectrobunConfig
BrowserWindow
import { BrowserWindow } from 'electrobun/bun'
new BrowserWindow({
title: 'My App',
url: 'http://localhost:3000',
frame: { x: 100, y: 100, width: 1200, height: 800 },
renderer: 'cef',
})
Server Readiness Check
// Poll server before opening window — don't block indefinitely
async function waitForServer(url: string, timeoutMs = 30000): Promise<boolean> {
const start = Date.now()
while (Date.now() - start < timeoutMs) {
try {
const response = await fetch(url, { method: 'HEAD' })
if (response.ok) return true
} catch {
await Bun.sleep(100)
}
}
return false
}
Application Events
import Electrobun from 'electrobun/bun'
Electrobun.events.on('will-quit', () => {
console.log('App quitting...')
})
Critical Rules
DO:
- Run server dev before desktop dev
- Use
catalog:for dependency versions - Wait for server readiness before opening BrowserWindow
- Handle server timeout gracefully (exit with helpful error message)
DON'T:
- Use
npm,npx,node,yarn,pnpm— always usebun/bunx - Hardcode dependency versions (use catalog)
- Block main thread with synchronous waits
- Use
unwrap()-style patterns without error handling