Files
galaxy-game/ui
Ilia Denisov 2ecdecad1e feat(ui): lobby site-style sidebar + profile screen (#47)
- Wrap lobby and profile in a shared `lobby-shell.svelte` chrome:
  page-list sidebar (Overview/Profile) and a top "Player-xxxx"
  identity strip mirroring the project site's monospace look.
- Strip the legacy `lobby.title`, device-session-id `<code>`, and
  `lobby.greeting` paragraph; the identity strip both names the user
  and opens the profile editor.
- Add a top-level `profile` AppScreen with a three-field form
  (`display_name`, `preferred_language`, `time_zone`) backed by a new
  `src/api/account.ts` wrapper around `user.account.get`,
  `user.profile.update`, and `user.settings.update`. Saving switches
  the active i18n locale in-place when the new preferred language is
  one the UI ships translations for.
- Update e2e fixture + auth-flow / lobby-flow specs to use the new
  `lobby-account-name` testid and wait for the loaded identity before
  releasing pending `SubscribeEvents` (webkit revocation race). New
  `profile-screen.spec.ts` covers navigation, edit-save, and cancel.
- Sync `ui/docs/lobby.md` and `ui/docs/navigation.md` to the new
  layout.

Closes #47
2026-05-26 22:25:40 +02:00
..
2026-05-23 16:55:02 +02:00
2026-05-07 07:18:55 +02:00

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 web target is a finalized, installable PWA: a shared design-token system with light/dark themes, WCAG 2.2 AA accessibility, en/ru localisation with a persisted choice, a central error surface, and offline tolerance — see the topic docs below.

The legacy Fyne client under client/ is reference-only. Nothing in ui/ imports from it.

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 design notes live under ui/docs/.

Targets

Target Wrapper Toolchain Status
web browser tab Vite + WASM implemented
web-mobile mobile browser Vite + WASM implemented
desktop (mac) Wails v2 Go + Wails CLI planned (see ROADMAP.md)
desktop (win) Wails v2 Go + Wails CLI planned (see ROADMAP.md)
desktop (linux) Wails v2 Go + Wails CLI planned (see ROADMAP.md)
iOS Capacitor gomobile + Xcode planned (see ROADMAP.md)
Android Capacitor gomobile + Gradle planned (see ROADMAP.md)

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.
  • Single-URL app-shell navigation: the game UI is one route served at /game/; the screen (login / lobby / game) and the in-game view are in-memory state (lib/app-nav.svelte.ts), not URLs, so the address bar never changes. Browser Back/Forward move between screens via shallow routing without touching the URL — a model that also suits the bundled standalone targets (Wails / Capacitor) that have no URLs. 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. See docs/navigation.md.

Repository layout

ui/
├── PLAN.md                 staged implementation plan
├── ROADMAP.md              planned desktop / mobile / multi-turn features
├── PLAN-finalize.md        PWA, accessibility, localisation, error UX
├── 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
│   ├── order-composer.md    order draft model, persistence, history-mode wiring
│   ├── 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
├── mobile-bridge/           gomobile bindings (planned — see ROADMAP.md)
├── desktop/                 Wails project (planned — see ROADMAP.md)
├── mobile/                  Capacitor project (planned — see ROADMAP.md)
└── frontend/                SvelteKit / Vite source
    ├── src/api/             GalaxyClient + typed Connect client + auth + session
    ├── src/lib/             app-shell nav + screens + game shell, env config, session store, stores
    ├── 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/          single-URL app-shell: `/game/` dispatcher (+page.svelte) + `/__debug/*`
    └── static/              core.wasm + wasm_exec.js (built by `make wasm` / CI; gitignored)

Linked topic docs:

  • docs/navigation.md — single-URL app-shell, screens and views as in-memory state, screen history, sidebar tools.
  • docs/auth-flow.md — email-code login, session store state machine, revocation watcher.
  • docs/lobby.md — lobby UI sections, application / invite lifecycle, create-game form defaults.
  • docs/i18n.md — translation primitive, native-name language picker, recipe for adding a new locale.
  • docs/storage.md — web KeyStore/Cache, IndexedDB schema, browser baseline.
  • docs/order-composer.md — local order draft store, persistence, history-mode wiring.
  • docs/wasm-toolchain.md — TinyGo build, loading recipe, bundle size budget.
  • docs/design-system.md — design tokens, light/dark theming, component conventions.
  • docs/a11y.md — WCAG 2.2 AA approach, axe + keyboard gates, shared a11y primitives.
  • docs/error-state-ux.md — central error surface, shared loading/empty/error states, selection marker, sheet dismissal.
  • docs/pwa-strategy.md — installable, offline PWA: service worker, manifest, icons.
  • docs/testing.md — Tier 1 per-PR + Tier 2 release test tiers.

Build pipeline

Every cross-target build flows through make at this level. Native targets are placeholders until their platform work lands; running make with no arguments prints the current placeholder map.

make web             Vite production build
make wasm            TinyGo → core.wasm
make ts-protos       Connect-ES + Protobuf-ES gen
make fbs-ts          FlatBuffers TS bindings via flatc
make gomobile        gomobile bind → ios + android   (planned — see ROADMAP.md)
make desktop-mac     Wails build for darwin           (planned — see ROADMAP.md)
make desktop-win     Wails build for windows          (planned — see ROADMAP.md)
make desktop-linux   Wails build for linux            (planned — see ROADMAP.md)
make ios             Capacitor + xcodebuild           (planned — see ROADMAP.md)
make android         Capacitor + gradle               (planned — see ROADMAP.md)
make all             every target above

Local development

For UI work against a real stack, the tools/local-dev/ docker compose brings up postgres + redis + mailpit + backend + gateway in one command, and ui/frontend/.env.development is already wired to talk to it:

make -C tools/local-dev up        # build + start, wait for healthy
pnpm -C ui/frontend dev           # Vite on the host
# UI:     http://localhost:5173
# Mailpit: http://localhost:8025

The stack accepts a fixed dev code (123456) in addition to the real Mailpit-delivered one. Full runbook in ../tools/local-dev/README.md.

For testing the production-shaped surface — Caddy in front of the gateway, statically served UI bundle, real https://*.galaxy.lan hostnames — use the long-lived dev environment at ../tools/dev-deploy/. It is redeployed by Gitea Actions on every merge into development.

Topic docs

Topic docs live under ui/docs/ (testing tiers, WASM toolchain, navigation shell, renderer internals, sync protocol, auth flow, and so on).

Cross-references

  • PLAN.md — staged implementation plan (historical record of completed work).
  • ROADMAP.md — planned desktop / mobile / multi-turn projection features.
  • PLAN-finalize.md — PWA, accessibility, localisation, error UX finalization work.
  • ../docs/ARCHITECTURE.md — platform architecture and the transport security model (§15) the client envelope contract derives from.
  • ../docs/FUNCTIONAL.md — per-domain user stories that drive the UI flows.
  • ../docs/TESTING.md — project-wide testing layers; UI-specific test tiers (Vitest, Playwright) live in ui/docs/testing.md.