Files
fullstack-starter/apps/desktop/AGENTS.md

125 lines
3.3 KiB
Markdown

# 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
```bash
# 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`)
```typescript
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
```typescript
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
```typescript
// 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
```typescript
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