forked from imbytecat/fullstack-starter
4.7 KiB
4.7 KiB
AGENTS.md - Desktop App Guidelines
Thin Electrobun shell hosting the fullstack server app.
Tech Stack
⚠️ This project uses Bun — NOT Node.js / npm. All commands use
bun. Never usenpm,npx, ornode.
- Type: Electrobun desktop application
- Design: Server-driven desktop (thin native shell hosting web app)
- Runtime: Bun (Main process) + CEF (Chromium Embedded Framework)
- Framework: Electrobun
- Build: Electrobun CLI + Turborepo
Architecture
- Server-driven design: The desktop app is a "thin" native shell. It does not contain UI or business logic; it merely hosts the
apps/serverTanStack Start application in a native window. - Dev mode: Connects to an external Vite dev server at
localhost:3000. Requiresapps/serverto be running separately. - Prod mode: Spawns an embedded TanStack Start server (Nitro) as a child process and loads the dynamically assigned local URL.
- Config:
electrobun.config.tsmanages app metadata (identifier, name), build entries, and asset bundling.
Commands
# Development
bun dev # Start Electrobun dev mode (requires server dev running)
# Build
bun build # Build stable release (all platforms)
# Code Quality
bun fix # Biome auto-fix
bun typecheck # TypeScript check
Directory Structure
.
├── src/
│ └── bun/
│ └── index.ts # Main process entry (Window management + server lifecycle)
├── electrobun.config.ts # App metadata and build/copy configuration
├── package.json # Scripts and dependencies
├── turbo.json # Build pipeline dependencies (depends on server build)
└── AGENTS.md # Desktop guidelines (this file)
Development Workflow
- Start server: In
apps/server, runbun dev. - Start desktop: In
apps/desktop, runbun dev. - Connection: The desktop app polls
localhost:3000until responsive, then opens the native window.
Production Architecture
Build Pipeline
The desktop build is orchestrated by Turbo. It depends on the server's production build:
turbo.json:@furtherverse/desktop#builddepends on@furtherverse/server#build.electrobun.config.ts: Copies../server/.outputtoserver-outputfolder within the app bundle.
Server Lifecycle
In production, the main process manages the embedded server:
- Spawn: Spawns server from
server-output/server/index.mjsusingBun.spawn. - Port Allocation: Server is started with
PORT=0andHOST=127.0.0.1. - Port Detection: The main process parses the server's
stdoutusing a regex to find the dynamically assigned port. - Lifecycle: The server process is tied to the app; it is killed on
SIGTERM,SIGINT, or app exit. If the server process crashes, the app exits with an error.
Environment Detection
The application determines its environment via the ELECTROBUN_BUILD_ENV variable, automatically set by the Electrobun CLI:
const isDev = () => {
const env = process.env.ELECTROBUN_BUILD_ENV
return !env || env === 'dev'
}
- dev: Development mode (connects to external host).
- canary / stable: Production mode (starts embedded server).
Environment Variables
ELECTROBUN_BUILD_ENV: Auto-set by CLI. Determines whether to use local dev server or embedded server.DATABASE_URL: Required by the server process. Must be passed through from the parent environment to the spawned child process.
Electrobun Patterns
BrowserWindow Configuration
The main window uses the CEF renderer for consistency across platforms.
new BrowserWindow({
title: 'Furtherverse',
url: serverUrl,
frame: {
x: 100,
y: 100,
width: 1200,
height: 800,
},
renderer: 'cef',
})
Path Aliases
The main process uses electrobun/bun for native APIs and PATHS for locating bundled assets.
import { BrowserWindow, PATHS } from 'electrobun/bun'
// Locate the embedded server bundle
const serverEntryPath = join(PATHS.VIEWS_FOLDER, '..', 'server-output', 'server', 'index.mjs')
Critical Rules
DO:
- Use arrow functions for all components and utility functions.
- Ensure
apps/serveris built before buildingapps/desktop(handled by Turbo). - Parse the server's stdout for the port instead of hardcoding ports in production.
- Handle server process termination to avoid orphan processes.
- Use
catalog:for all dependency versions inpackage.json.
DON'T:
- Use
npm,npx,node,yarn, orpnpm. Always usebun. - Hardcode
localhost:3000for production builds. - Include UI components or business logic in the desktop app (keep it thin).
- Use
as anyor@ts-ignore.