3babe2b3ab
New multiplatform SwiftUI app under apps/zacus-hub/ generated via
XcodeGen (project.yml). Three modes share a HubSession actor that
talks to tools/zacus-gateway over Tailscale-only HTTP/WS.
Game-master: live state stream (WebSocket /v1/state/ws), backend
health badges, hint trigger, journal.
Companion: push-to-talk via AVAudioRecorder (M4A AAC 16 kHz),
fallback file picker, hint request, transcript via voice-bridge
proxy.
Studio: YAML editor with validate/save (existing /v1/studio
routes), plus a Scratch tab hosting a Blockly + zelos-renderer
workspace in WKWebView. 38 custom Zacus block types across 10
categories (Scènes, NPC, Audio, LCD, Hardware ESP32, ESP-NOW,
BOX-3, M5, PLIP, Logique), .sb3 export/import via JSZip (procedure
calls + embedded YAML for lossless round-trip), Flasher sheet that
calls /v1/flash/{board} with auto/hot/cold strategies and shows
per-board step results including the cold-flash idf.py command.
ATS exception domains cover the Tailscale CGNAT range plus the
electron-server / studio / macm1 hostnames so the WebView and
URLSession can hit plain HTTP on the tailnet without TLS.
Token stays in the Keychain (cc.saillant.zacus.hub) — never
committed to source.
64 lines
2.3 KiB
Markdown
64 lines
2.3 KiB
Markdown
# Zacus Hub — SwiftUI app (macOS + iOS)
|
|
|
|
Foundation scaffolded 2026-05-24. Three modes: **Game-master**, **Companion**, **Studio**.
|
|
See `docs/specs/2026-05-24-zacus-hub-app.md`.
|
|
|
|
## Generate the Xcode project
|
|
|
|
```bash
|
|
brew install xcodegen # one-time
|
|
cd apps/zacus-hub
|
|
xcodegen generate
|
|
open ZacusHub.xcodeproj
|
|
```
|
|
|
|
XcodeGen reads `project.yml` and produces a multiplatform `.xcodeproj`
|
|
targeting iOS 17 + macOS 14. `ZacusHub.xcodeproj/` is git-ignored —
|
|
regenerate after editing `project.yml` or adding source files in new
|
|
directories.
|
|
|
|
## Layout
|
|
|
|
```
|
|
apps/zacus-hub/
|
|
├── project.yml XcodeGen spec
|
|
├── Resources/
|
|
│ ├── Info.plist shared (iOS leaves macOS keys harmless)
|
|
│ └── ZacusHub.entitlements sandbox + network + mic + camera
|
|
└── Sources/
|
|
├── App/ @main, RootView (tabs/sidebar), Settings
|
|
├── Shared/ HubSession, HubAPI (actor), Keychain
|
|
├── GameMaster/ operator view (sprint 1+)
|
|
├── Companion/ player voice + hints (sprint 3+)
|
|
└── Studio/ YAML browser (sprint 5+)
|
|
```
|
|
|
|
All sources live in one app target — Swift sees them as a single module,
|
|
so SourceKit errors before `xcodegen generate` are expected noise.
|
|
|
|
## Configure at first launch
|
|
|
|
1. Start the gateway (`tools/zacus-gateway/README.md`), copy the token.
|
|
2. In the app: gear icon → paste **URL** (e.g. `http://studio:8400`) +
|
|
**token**. Saved to Keychain (`cc.saillant.zacus.hub`).
|
|
3. The Settings sheet shows live auth state (`/v1/auth/ping`).
|
|
|
|
## Sprint 0 status
|
|
|
|
| Surface | State |
|
|
|---------|-------|
|
|
| App skeleton (3 modes, settings, auth check) | ✅ scaffolded |
|
|
| Gateway connection | ✅ wired |
|
|
| Game-master state refresh | ✅ pull (stub data) |
|
|
| Companion hint request | ✅ wired to gateway proxy |
|
|
| Studio scenario browse | ✅ list + read |
|
|
| Push-to-talk, live WS, scenario edit | ⏳ later sprints |
|
|
|
|
## Conventions
|
|
|
|
- Swift 5.10, strict concurrency on.
|
|
- All network calls go through `HubAPI` actor — never raw URLSession in views.
|
|
- View files own no network state — they read from `HubSession` or pass
|
|
via `@State` after awaiting an actor call.
|
|
- French for user-visible strings, English for code/comments.
|