forked from imbytecat/fullstack-starter
125 lines
3.3 KiB
Markdown
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
|