Files
Toju/toju-app/CONTEXT.md
Myx ee293d7daf
Some checks failed
Deploy Web Apps / deploy (push) Successful in 5m52s
Build Android APK / build-android-apk (push) Failing after 23m15s
Queue Release Build / prepare (push) Successful in 1m42s
Queue Release Build / build-linux (push) Failing after 9m33s
Queue Release Build / build-windows (push) Successful in 26m5s
Queue Release Build / finalize (push) Has been skipped
feat: Rename to Toju and add translation
2026-06-05 17:17:29 +02:00

4.9 KiB

Product Client (toju-app)

Owns the user-facing Angular 21 desktop chat experience: rendering and orchestrating chat, voice, screen-share, plugin UI, theming, and identity flows on top of the Electron window.api bridge and the server WebSocket. Houses every bounded context the end user interacts with, organized DDD-style under src/app/domains/.

Format reference:

  • Vocabulary — bold term, one-sentence definition, aliases to avoid.
  • Relationships — bullets with bold terms and cardinality.
  • Boundaries / IO — what this subdomain exposes and consumes.
  • Invariants — rules that always hold.
  • Flagged ambiguities — terms in dispute with proposed resolutions.

See agents-docs/AGENTS_CONTEXT.md for the contract. Update in the same turn a trigger fires (see agents-docs/AGENT_WORKFLOW.md § CONTEXT.md upkeep).

Vocabulary

Term Definition Aliases to avoid
Domain A bounded context under src/app/domains/<name>/ that owns its own models, services, NgRx slice, and components — e.g. chat, voice-session, plugins. "module", "feature" (Angular reserves these for different things)
Shared kernel Cross-domain contracts in src/app/shared-kernel/ — wire-format models, P2P transfer utilities, plugin contracts, signaling contracts — imported by multiple domains. "common", "core"
Infrastructure Technical-runtime concerns shared by domains: persistence/ (client-side store wiring), realtime/ (WebSocket adapter), and mobile/ (Capacitor/native facades). Not a domain. "shared", "lib"
Mobile facade An injectable service under infrastructure/mobile/ that wraps Capacitor or web adapters so domains never import @capacitor/* directly. "Capacitor service", "native plugin"
Capacitor SQLite backend Native persistence path selected by DatabaseService when PlatformService.isCapacitor is true; uses @capacitor-community/sqlite instead of IndexedDB. "mobile database", "Capacitor DB"
Rules file A pure-function module suffixed *.rules.ts that encodes domain logic without Angular or NgRx dependencies — easy to unit-test. "helpers", "utils"
Custom emoji User-created image emoji assets stored locally, synced peer-to-peer, and referenced from messages/reactions by stable :emoji[id](name) tokens. "sticker", "emote"
App locale The active UI language for the product client, resolved by resolveAppLocale() in core/i18n/; only en is shipped today. "language", "i18n locale"
Translation catalog JSON string tables under public/i18n/catalog/*.json, merged to public/i18n/en.json via npm run i18n:sync, loaded at startup by AppI18nService. "locale file", "messages file"

Relationships

  • A Domain owns zero or more Components, Services, NgRx slices, and Rules files.
  • A Domain may consume Shared kernel contracts but must never import from another Domain directly — cross-domain coupling goes through the shared kernel or NgRx events.
  • The Realtime infrastructure adapts server WebSocket envelopes (defined in src/app/shared-kernel/signaling-contracts.ts and mirrored in server/src/websocket/types.ts) into NgRx actions consumed by domains.
  • The Plugins domain consumes plugin manifests loaded by Electron's plugin-library.ts and exposes a sandboxed runtime that other domains may hook into.
  • The Custom emoji domain owns custom emoji assets and usage ranking; the Chat domain consumes it for reactions and composer insertion.

Boundaries / IO

  • Exposes: the Angular SPA bundle served at :4200 in dev (ng serve) or mounted by Electron in production; NgRx store events that other domains in this subdomain consume; UI surface to the end user.
  • Consumes:
    • window.api.* IPC surface exposed by Electron preload (defined in electron/preload.ts and electron/api/).
    • WebSocket envelopes from server/src/websocket/ (typed by shared-kernel/signaling-contracts.ts).
    • REST endpoints from the server's server/src/routes/ (server directory, invites, join requests, link metadata, klipy).
    • Plugin manifests resolved by Electron's plugin library.

Invariants

  • A Domain never imports from another Domain directly — only through the Shared kernel or NgRx actions.
  • Rules files stay framework-free (no Angular, no NgRx) so they can be Vitest-tested as plain functions.
  • Wire-format types (anything that crosses the WebSocket or IPC boundary) live in Shared kernel, never inside a single domain.

Flagged ambiguities

  • None recorded yet — add entries when a domain term resists clean definition.

Agent-procedural rules (TDD, lint, etc.) live in /AGENTS.md. Per-domain implementation detail lives in src/app/domains/<name>/README.md. This file is the bounded-context domain artefact for the product client as a whole.