127 lines
2.8 KiB
Markdown
127 lines
2.8 KiB
Markdown
# Toes - Claude Code Guide
|
|
|
|
## What It Is
|
|
|
|
Personal web server framework that auto-discovers and runs multiple web apps on your home network. "Set it up, turn it on, forget about the cloud."
|
|
|
|
## How It Works
|
|
|
|
1. Host server scans `/apps` directory for valid apps
|
|
2. Valid app = has `package.json` with `scripts.toes` entry
|
|
3. Each app spawned as child process with unique port (3001+)
|
|
4. Dashboard UI shows all apps with current status, logs, and links
|
|
|
|
## Key Files
|
|
|
|
- `src/server/apps.ts` - **The heart**: app discovery, process management, lifecycle
|
|
- `src/server/index.tsx` - Entry point (minimal, just initializes Hype)
|
|
- `src/pages/index.tsx` - Dashboard UI
|
|
- `apps/*/package.json` - Must have `"toes": "bun run --watch index.tsx"` script
|
|
- `TODO.md` - User-maintained task list (read this!)
|
|
|
|
## Tech Stack
|
|
|
|
- **Bun** runtime (not Node)
|
|
- **Hype** (custom HTTP framework wrapping Hono) from git+https://git.nose.space/defunkt/hype
|
|
- **Forge** (typed CSS-in-JS) from git+https://git.nose.space/defunkt/forge
|
|
- TypeScript + Hono JSX
|
|
|
|
## Running
|
|
|
|
```bash
|
|
bun run --hot src/server/index.tsx # Dev mode with hot reload
|
|
```
|
|
|
|
## App Structure
|
|
|
|
```tsx
|
|
// apps/example/index.tsx
|
|
import { Hype } from "hype"
|
|
const app = new Hype()
|
|
app.get("/", (c) => c.html(<h1>Content</h1>))
|
|
export default app.defaults
|
|
```
|
|
|
|
## Conventions
|
|
|
|
- Apps get `PORT` env var from host
|
|
- Each app is isolated process with own dependencies
|
|
- No path-based routing - apps run on separate ports
|
|
- `DATA_DIR` env controls where apps are discovered
|
|
|
|
## Current State
|
|
|
|
- Core infrastructure: ✓ Complete (discovery, spawn, watch, ports, UI)
|
|
- Apps: basic, profile (working); risk, tictactoe (empty)
|
|
- Check TODO.md for planned features
|
|
|
|
## Coding Guidelines
|
|
|
|
TS files should be organized in the following way:
|
|
|
|
- imports
|
|
- re-exports
|
|
- const/lets
|
|
- enums
|
|
- interfaces
|
|
- types
|
|
- classes
|
|
- functions
|
|
- module init (top level function calls)
|
|
|
|
In each section, put the `export`s first, in alphabetical order.
|
|
|
|
Then, after the `export`s (if there were any), put everything else,
|
|
also in alphabetical order.
|
|
|
|
For single-line functions, use `const fn = () => {}` and put them in the
|
|
"functions" section of the file.
|
|
|
|
All other functions use the `function blah(){}` format.
|
|
|
|
Example:
|
|
|
|
```ts
|
|
import { code } from "coders"
|
|
import { something } from "somewhere"
|
|
|
|
export type { SomeType }
|
|
|
|
const RETRY_TIMES = 5
|
|
const WIDTH = 480
|
|
|
|
enum State {
|
|
Stopped,
|
|
Starting,
|
|
Running,
|
|
}
|
|
|
|
interface Config {
|
|
name: string
|
|
port: number
|
|
}
|
|
|
|
type Handler = (req: Request) => Response
|
|
|
|
class App {
|
|
config: Config
|
|
|
|
constructor(config: Config) {
|
|
this.config = config
|
|
}
|
|
}
|
|
|
|
const isApp = (name: string) =>
|
|
apps.has(name)
|
|
|
|
function createApp(name: string): App {
|
|
const app = new App({ name, port: 3000 })
|
|
apps.set(name, app)
|
|
return app
|
|
}
|
|
|
|
function start(app: App): void {
|
|
console.log(`Starting ${app.config.name}`)
|
|
}
|
|
```
|