Getting Started
Client Structure and Checklist
A suggested client layout, and what to verify before shipping.
Suggested client structure
core/
network/
ApiClient — base URL, JSON, the Authorization interceptor
TokenStore — keychain read/write; the ONLY place the token lives
AuthInterceptor — attaches the token; captures set-auth-token on the way back
ErrorMapper — HTTP status + body → a typed AppError
media/
resolveMedia() — path → absolute URL
AuthedImageLoader — image requests that carry the session
feature/
auth/ sign-in, password reset, sign-out
feed/ feed list, composer, post detail, comments
directory/ people list, filters, profile, org chart
profile/ my profile, editor, avatar, work timeline
events/ list, create, reschedule
notifications/ list, badge, push handling, deep links
admin/ members, teams ← gate on role == super_adminAdd one more thing beside network/:
core/
realtime/
EventStream — the single SSE connection; reconnect + Last-Event-ID
EventRouter — event type → which cached reads to dropThree rules worth holding to:
- One place attaches the token, one place handles 401. An interceptor that clears the store and emits a "signed out" event keeps that decision out of every screen.
- Mutations return the updated object. Reacting, bookmarking, voting and commenting all hand back the whole post. Render from the response instead of patching local state, and the card can never disagree with the server.
- One stream for the app, not one per screen (Live updates (SSE)). Open it once, route events to whatever is listening, and drop the affected cached reads. A screen should never own a connection.
Before you ship
- Token in the keychain, never in logs or plain storage
-
Authorizationsent on API calls and on image/file loads - 401 clears the token and routes to sign-in, everywhere
-
set-auth-tokenon any response overwrites the stored token - Media paths resolved against the base URL
- Push token registered on every launch with
platformset - Push token deleted before sign-out
- Android notification channel
super-peoplecreated at launch - One SSE connection for the whole app, opened after sign-in, closed on sign-out
-
Last-Event-IDsent on reconnect;resyncrefetches what is on screen - Events acted on regardless of
actorId— your own other devices depend on it - Unread badge driven by
notification.created, not by a timer - Everything still works with the stream disconnected
- Cursor paging, not offsets;
limit≤ 50 -
messagehandled as string or array of strings - Photos downscaled before upload; progress shown; retry offered
- Admin UI gated on
role, and 403 still handled gracefully - No sign-up screen — accounts are created by an admin