Files
galaxy-game/ui/README.md
T
Ilia Denisov f57a290432 phase 8: lobby UI + cross-stack lobby command catalog + TS FlatBuffers
- Extend pkg/model/lobby and pkg/schema/fbs/lobby.fbs with public-games
  list, my-applications/invites lists, game-create, application-submit,
  invite-redeem/decline. Mirror the matching transcoder pairs and Go
  fixture round-trip tests.
- Wire the seven new lobby message types through
  gateway/internal/backendclient/{routes,lobby_commands}.go with
  per-command REST helpers, JSON-tolerant decoding of backend wire
  shapes, and httptest-based unit coverage for success / 4xx / 5xx /
  503 across each command.
- Introduce TS-side FlatBuffers via the `flatbuffers` runtime dep, a
  `make fbs-ts` target driving flatc, and the generated bindings under
  ui/frontend/src/proto/galaxy/fbs. Phase 7's `user.account.get` decode
  now uses these bindings as well, closing the JSON.parse vs
  FlatBuffers gap that would have failed against a real local stack.
- Replace the placeholder lobby with five sections (my games, pending
  invitations, my applications, public games, create new game) and the
  /lobby/create form. Submit-application uses an inline race-name
  form on the public-game card; create-game keeps name / description /
  turn_schedule / enrollment_ends_at always visible and the rest under
  an Advanced toggle with TS-side defaults.
- Update lobby/+page.svelte to throw LobbyError on non-ok result codes;
  GalaxyClient.executeCommand now returns { resultCode, payloadBytes }.
- Vitest binding round-trips, lobby.ts wrapper unit tests, lobby-page
  + lobby-create component tests, Playwright lobby-flow.spec covering
  create / submit / accept across all four projects. Phase 7 e2e was
  migrated to the FlatBuffers fixtures and to click+fill against the
  Safari-autofill readonly inputs.
- Mark Phase 8 done in ui/PLAN.md, mirror the wire-format note into
  Phase 7, append the new lobby commands to gateway/README.md and
  docs/ARCHITECTURE.md, add ui/docs/lobby.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 18:05:08 +02:00

155 lines
7.6 KiB
Markdown

# ui — Galaxy Cross-Platform Client
`ui/` hosts the new cross-platform Galaxy client. A single
TypeScript + Svelte source tree builds to five targets: web,
web-mobile, standalone PC (mac/win/linux), iOS, and Android. A
shared Go module (`ui/core`) carries envelope cryptography, the
FlatBuffers codec, keypair management, and a thin bridge over
`pkg/calc/` for UI-side game math; it is compiled to WASM for the
web targets, gomobile native libraries for mobile, and embedded
directly in Wails on desktop. All network I/O lives on the
TypeScript side via ConnectRPC, so the Go module is a pure compute
boundary on every platform.
The legacy Fyne client under `client/` is reference-only.
Nothing in `ui/` imports from it.
The full staged implementation plan lives in `PLAN.md`. The
strategic rationale (why Svelte, why PixiJS, why Go-as-WASM, why
Wails+Capacitor) lives outside the repo at
`~/.claude/plans/buzzing-questing-fountain.md`. This README is a
quick orientation; deeper per-phase design notes earn their place
under `ui/docs/` as they are introduced.
## Targets
| Target | Wrapper | Toolchain | Phase |
| --------------- | ---------------- | ----------------------- | -------- |
| web | browser tab | Vite + WASM | 5+ |
| web-mobile | mobile browser | Vite + WASM | 5+ |
| desktop (mac) | Wails v2 | Go + Wails CLI | 31 |
| desktop (win) | Wails v2 | Go + Wails CLI | 31 |
| desktop (linux) | Wails v2 | Go + Wails CLI | 31 |
| iOS | Capacitor | gomobile + Xcode | 32+ |
| Android | Capacitor | gomobile + Gradle | 32+ |
## Layered architecture
- **TypeScript + Svelte 5 frontend**, shared across all five targets,
scaffolded with SvelteKit + Vite.
- **PixiJS v8** with dual WebGPU/WebGL backend for the world map
renderer.
- **Go module `ui/core/`** as a compute-only library (canonical bytes,
Ed25519 sign/verify, FlatBuffers codec, keypair, thin bridge to
`pkg/calc/`) compiled to WASM, gomobile, and Wails-embedded native.
- **TypeScript-side `Core` interface** with three adapters
(`WasmCore`, `WailsCore`, `CapacitorCore`) selected at build time.
- **`GalaxyClient`** on top of `Core` performs all network I/O via
ConnectRPC (`@connectrpc/connect-web`) on every platform.
- **Per-platform storage:** WebCrypto + IndexedDB on web, OS keychain
+ SQLite on desktop, iOS Keychain / Android Keystore + SQLite on
mobile, all behind a single `KeyStore` and `Cache` TypeScript
interface.
- **Mobile-first navigation:** one active view occupies the main area
at a time; the sidebar holds a single tool (calculator, inspector,
or order) with persistent state on switch.
## Repository layout
```text
ui/
├── PLAN.md staged implementation plan (Phases 1-36)
├── Makefile wasm / ts-protos / web / mobile / desktop targets
├── README.md this file
├── buf.gen.yaml local-plugin TS Protobuf-ES generator
├── docs/ topic-based design notes
│ ├── auth-flow.md email-code login, session store, revocation
│ ├── i18n.md translation primitive, native-name picker, extensibility
│ ├── storage.md web KeyStore/Cache, IDB schema, baseline
│ ├── testing.md per-PR / release test tiers
│ └── wasm-toolchain.md TinyGo build, JSDOM loading, bundle budget
├── core/ ui/core Go module (canonical bytes, keypair)
├── wasm/ TinyGo entry point exposing Core to JS
└── frontend/ SvelteKit / Vite source
├── src/api/ GalaxyClient + typed Connect client + auth + session
├── src/lib/ env config, session store, revocation watcher
├── src/platform/core/ Core interface + WasmCore adapter
├── src/platform/store/ KeyStore/Cache interfaces + web adapter
├── src/proto/ generated Protobuf-ES + Connect descriptors + FlatBuffers TS bindings
├── src/routes/ SvelteKit routes (/, /login, /lobby, /lobby/create)
└── static/ core.wasm + wasm_exec.js (committed artefacts)
```
Linked topic docs:
- [`docs/auth-flow.md`](docs/auth-flow.md) — email-code login,
session store state machine, revocation watcher.
- [`docs/lobby.md`](docs/lobby.md) — lobby UI sections, application
/ invite lifecycle, create-game form defaults.
- [`docs/i18n.md`](docs/i18n.md) — translation primitive, native-name
language picker, recipe for adding a new locale.
- [`docs/storage.md`](docs/storage.md) — web KeyStore/Cache,
IndexedDB schema, browser baseline.
- [`docs/wasm-toolchain.md`](docs/wasm-toolchain.md) — TinyGo build,
loading recipe, bundle size budget.
- [`docs/testing.md`](docs/testing.md) — Tier 1 per-PR + Tier 2
release test tiers.
```text
ui/
├── README.md this file
├── PLAN.md staged implementation plan
├── Makefile cross-target build placeholders
├── pnpm-workspace.yaml pnpm workspace root
├── .gitignore
├── docs/ per-phase topic docs (added per phase)
├── frontend/ TS + Svelte source, shared across targets
├── core/ Go module ui/core (Phase 3+)
├── wasm/ TinyGo entry point for core.wasm (Phase 5)
├── mobile-bridge/ gomobile bindings (Phase 32+)
├── desktop/ Wails project (Phase 31)
├── mobile/ Capacitor project (Phase 32+)
└── web/ static deploy assets (Phase 30+)
```
## Build pipeline
Every cross-target build flows through `make` at this level. All
named targets are placeholders until the named phase lands; running
`make` with no arguments prints the current placeholder map.
```text
make web Vite production build Phase 5+
make wasm TinyGo → core.wasm Phase 5
make ts-protos Connect-ES + Protobuf-ES gen Phase 5
make fbs-ts FlatBuffers TS bindings via flatc Phase 8
make gomobile gomobile bind → ios + android Phase 32+
make desktop-mac Wails build for darwin Phase 31
make desktop-win Wails build for windows Phase 31
make desktop-linux Wails build for linux Phase 31
make ios Capacitor + xcodebuild Phase 32+
make android Capacitor + gradle Phase 32+
make all every target above
```
## Per-phase docs
Topic docs live under `ui/docs/` and are added per phase as they're
needed (testing tiers, WASM toolchain, navigation shell, renderer
internals, sync protocol, auth flow, and so on). The staged plan in
`PLAN.md` names the topic doc each phase produces.
## Cross-references
- [`PLAN.md`](./PLAN.md) — staged implementation plan with goals,
artifacts, dependencies, acceptance criteria, and targeted tests
per phase.
- [`../docs/ARCHITECTURE.md`](../docs/ARCHITECTURE.md) — platform
architecture and the transport security model (§15) the client
envelope contract derives from.
- [`../docs/FUNCTIONAL.md`](../docs/FUNCTIONAL.md) — per-domain user
stories that drive the UI flows.
- [`../docs/TESTING.md`](../docs/TESTING.md) — project-wide testing
layers; UI-specific test tiers (Vitest, Playwright) live in
`ui/docs/testing.md` from Phase 2 onward.