chatto-client-placement
Decide whether Chatto client code goes into `@chatto/client` (packages/chatto-client) or the bundled frontend (apps/frontend). Use before you add a request, store, state, helper, or protocol rule to either, or when you move code between them.
- License 许可
- AGPL-3.0
- 最近更新
- 2026-11-11
- Stars
- ★ 2.9k
- Forks
- 143
01 前言 Front Matter
- name
- chatto-client-placement
- description
- Decide whether Chatto client code goes into `@chatto/client` (packages/chatto-client) or the bundled frontend (apps/frontend). Use before you add a request, store, state, helper, or protocol rule to either, or when you move code between them.
03 SKILL.md 正文
Placement of Chatto Client Code
@chatto/client is the one Chatto client (ADR-111). The bundled frontend,
ChattoBot, and third-party bots and frontends use it. The frontend uses the
client. The client never calls into the frontend.
Decision Procedure
Ask these questions in sequence. Stop at the first "yes".
- Does it show something to a person? Translated text, toasts, sounds, routes, components, layout, or Svelte context: put it in the frontend.
- Does it talk to a server or keep server data? Requests, sessions and tokens, realtime delivery, server and room data, the operations on this data, or a privacy or authorization boundary: put it in the client. Exception: the requests on the Allowed Frontend API Modules list stay in the frontend.
- Does it encode a protocol fact? A token format in a message body, mention rules, the permission structure, or validation that mirrors the server: put it in the client, also when only the frontend uses it now. The frontend keeps only the display part, such as labels and formatting.
- Does only one screen or flow need the state? Search sessions,
highlights, editor drafts, call media, scroll positions, sidebar shape, or
device UI preferences: put it in the frontend, in
serverUior$lib/state. - Not sure? Ask: "Does a bot or a different frontend need this to use Chatto correctly?" If yes, put it in the client.
Placement Table
| Concern | @chatto/client |
Frontend |
|---|---|---|
| A new RPC | Facade in src/api/ |
Only the allowed modules below |
| Server and room data | Stores in src/server/ and src/room/ |
Derive from the store in components |
| A copy of server data | Emit a boundary event (src/server/storeEvents.ts) for new boundaries |
Keep the copy and clear it at the boundary events |
| Per-server UI state | None | serverUi(store) in $lib/state/server/serverUi.ts |
| Snapshot query caches | None | $lib/query; cacheRegistry.ts connects them to boundary events |
| Errors | Keep the error object | errorMessage() or toastError() from $lib/utils/errorMessage |
| Render data from client stores | src/timeline/ |
Other render data in $lib/render |
| Text in client data | Take labels from the host (DirectMessageLabels in timeline/users.ts) |
Supply translated labels ($lib/render/directMessageLabels.ts) |
| Server catalogue policy | Registry API only (ADR-112) | $lib/serverCatalogue |
Features With Parts In Both
Most features have three parts:
- A facade in the client's
src/api/. - State in a client server or room store, when hosts read the data.
- Frontend UI state in
serverUi. It derives from the store. When it keeps a copy of server data, it clears the copy at the store's boundary events:onReset,onRoomAccessLost,onRoomAccessRestored,onUserDeleted,onAuthorityChanged,onPermissionsChanged,onSessionEnded, andonDispose.
Use these features as examples:
- Message search. Facade:
packages/chatto-client/src/api/messageSearch.ts. The client keeps no search state. The frontend keeps the search sessions in$lib/state/server/messageSearch.ts.serverUi.tsclears them atonReset,onRoomAccessLost,onUserDeleted, andonPermissionsChanged. - Voice calls. Facade:
src/api/voiceCalls.ts. Store state:projection.activeCalls. The frontend keeps the LiveKit media, sounds, and toasts in$lib/state/server/voiceCall.svelte.ts. - Notifications. Facade:
src/api/notifications.ts. Store:src/server/notifications.ts, withnotificationTarget. The frontend keeps attention and read views (notificationAttention.ts,readViews.ts) and turns targets into routes ($lib/notificationPath.ts).
Allowed Frontend API Modules
The frontend calls ConnectRPC services directly only for its own screens:
- Admin tools, first-run setup, and Web Push (
$lib/api). - Browser sign-in and account-linking flows, such as external identities
(
$lib/api/externalIdentities.ts). The sign-in flow uses page redirects and the origin's cookie session. Account linking starts a browser redirect. Only the frontend's sign-in and account settings screens use these flows. Bots do not use them, and a different frontend makes its own flows. - The cross-tab session channel (
$lib/auth/sessionChannel.ts).
Do not add other requests there.
Protocol Facts With Display Parts
Some features have a protocol part in the client and a display part in the frontend. Use them as patterns:
- Message timestamp tokens: the client's
messaging/timestampTokens.tshas the<t:EPOCH:F>format.$lib/messageTimestamps.tsrenders tokens. - Custom status templates: the client's
util/customStatusTemplates.tshas thechatto:status:<id>tokens.$lib/customStatusTemplates.tsadds the translated labels. - Permissions: the client's
util/permissionCatalog.tsmirrorscli/internal/core/permission.go.$lib/permissions.tsadds the translated descriptions and help. - Presence: the client's
server/presenceTracking.tsloads the choice and sends heartbeats.$lib/state/server/presenceTracking.tsconnects one tracker to the chat root.
Frontend Modules That Look Like Client Code
These modules stay in the frontend. Do not move them without a new reason:
$lib/mentions.ts: mention detection uses the frontend's Markdown renderer. The server resolves mentions and tells bots why a message addresses them.$lib/state/server/roomUnread.tsandroomDirectory.ts: optimistic read-state and membership changes, so the UI responds before the server confirms. Store events confirm them. Each host decides about its own optimistic UI.
Common Mistakes
- A request helper in
$libbecause "only the frontend uses it". - A client store that imports host state or calls back into the UI.
- Display text, translated text, or toasts in the client.
- A frontend copy of server data that does not clear at boundary events.
- Svelte runes,
svelte/reactivity, or$libimports in the client outsidesrc/svelte/.
Related Rules
packages/chatto-client/AGENTS.md: how to write client code.apps/frontend/AGENTS.md: how to write frontend code.- ADR-111 and ADR-112: the decisions.
04 同仓库更多 Skills
writing-tests
Instructions and hints for writing tests.
update-project-dependencies
Update Chatto Go and frontend dependencies within their compatible version ranges, then run tests.
svelte-docs
Look up official Svelte, SvelteKit, and Svelte CLI documentation.
svelte-core-bestpractices
Guidance on writing fast, robust, modern Svelte code. Load this skill whenever in a Svelte project and asked to write/edit or analyze a Svelte component or module. Covers reactivity, event handling, styling, integration with libraries and more.
svelte-code-writer
CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating, editing or analyzing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
session-wrap-up
Review a completed, paused, or blocked coding-agent session to identify friction, mistakes, near misses, missing context, and opportunities to improve future work. Use when the user asks to wrap up, run a retrospective, explain what issues the agent faced, capture lessons learned, or recommend improvements to repository instructions, documentation, skills, tooling, tests, or workflows. Produce an evidence-based, propose-only report; do not apply follow-up changes unless the user asks.