62 lines
3.1 KiB
Markdown
62 lines
3.1 KiB
Markdown
# CLAUDE.md — HomeOS
|
||
|
||
Self-built smart-home control plane. Single household, self-hosted, LAN-first.
|
||
**Not** Home Assistant / not a wrapper: own data model, own integrations, own UI.
|
||
|
||
Authoritative build spec: **`handoff.md`**. Non-negotiable conventions: **`rules.md`**.
|
||
Approved design direction: **`design-mockup.html`** (open in a browser).
|
||
Read all three before non-trivial work.
|
||
|
||
## Locked decisions (see handoff §12)
|
||
|
||
- **Framework:** Laravel 13 · **Livewire v3** class-based (NOT Volt) · **Tailwind v4** (CSS-first `@theme`, no `tailwind.config.js`) · Vite
|
||
- **DB:** PostgreSQL 17 + TimescaleDB (telemetry hypertables + compression/retention)
|
||
- **Realtime:** Laravel Reverb + Echo — **every channel PRIVATE**
|
||
- **Queue/Cache:** Redis (+ Horizon)
|
||
- **MQTT:** Eclipse Mosquitto 2 · client `php-mqtt/laravel-client` · Python discovery sidecar
|
||
- **Git:** local repo, no remote yet · feature branches, never commit to `main`
|
||
- **Name:** "HomeOS" is a working title
|
||
|
||
## Everything runs in containers (R8 — host has only Docker)
|
||
|
||
The host has **no PHP / Composer / Node** for project work. Always exec into the stack:
|
||
|
||
```bash
|
||
docker compose up -d # start stack
|
||
docker compose exec app php artisan … # artisan
|
||
docker compose exec app composer … # composer
|
||
docker compose exec app npm … # node/vite (or: docker compose exec app npm run build)
|
||
docker compose logs -f app # tail
|
||
```
|
||
|
||
The `app`, `horizon`, `scheduler`, `reverb` (and later `mqtt-listener`) services share one image
|
||
(`docker/app/Dockerfile`). Ports are env-driven in `.env` (`APP_PORT`, `VITE_PORT`,
|
||
`REVERB_HOST_PORT`, `DB_HOST_PORT`). `HOST_UID`/`HOST_GID` come from `id nexxo` — never hardcode.
|
||
|
||
## Architecture (handoff §3)
|
||
|
||
MQTT-first hybrid. Mosquitto is the bus. `mqtt-listener` (artisan daemon) parses + dispatches only
|
||
(H2) → Horizon jobs upsert `device_states` → Reverb private channels → Livewire (Echo).
|
||
UI action → `DeviceCommandService` → driver (`ShellyMqttDriver` first) → device, every command
|
||
audited in `commands` (H1). Vendor specifics only in `app/Support/Mqtt` + `app/Support/Drivers` (H3).
|
||
|
||
## Design system (handoff §8)
|
||
|
||
"Enterprise Ops, dark OLED" — UniFi/Grafana-class console, not a consumer app. Tokens live in
|
||
`resources/css/app.css` `@theme` (ported verbatim from the mockup). Status via colored dot/pill +
|
||
text (never color alone, never emoji, R9). Every numeric value / MAC / IP / timestamp in
|
||
`font-mono` with `tabular-nums`. Hairline borders, no shadows. Accent (cyan) sparingly.
|
||
|
||
## Non-negotiable rules
|
||
|
||
See **`rules.md`** (R1–R17 + H1–H5). Highlights: class-based Livewire pages (R1/R2), tokens-only
|
||
styling (R3/R10), wire-elements/modal for confirms (R5), UUID route keys (R11), browser-verify every
|
||
page (R12), English routes / German labels (R13), self-hosted fonts (R14), Codex review gate (R15),
|
||
full localization DE+EN (R16). **On any conflict: STOP and ask.**
|
||
|
||
## Build order (handoff §13)
|
||
|
||
1. Bootstrap → 2. Domain core → 3. MQTT ingest → 4. Discovery → 5. Presence → 6. Automations →
|
||
7. Polish + PWA. Each phase ends **browser-verified (R12) + Codex-clean (R15) + committed on a
|
||
feature branch**.
|