Files
seastem-electronjs/apps/desktop/AGENTS.md

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 use npm, npx, or node.

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

  1. Start server dev first: bun dev from apps/server/
  2. Start Electrobun: bun dev from apps/desktop/
  3. Desktop app polls localhost:3000 until 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 use bun / bunx
  • Hardcode dependency versions (use catalog)
  • Block main thread with synchronous waits
  • Use unwrap()-style patterns without error handling