Skip to main content

Key Technical Points

5.1 Authentication & API Client​

Auth: localStorage.auth_token drives useAuth() / checkAuth() and protected-route redirects. 401 responses clear the token and route to /auth.

API client: zenspaceApi.request() (src/common/helpers/api.ts) returns a parsed ApiResponse<T>; non-OK HTTP responses are returned (not thrown) — call sites check res?.success.

The public magic-link page is the exception — it uses raw fetch via joinBackendUrl().

5.2 Organization Context​

OrganizationProvider reads ?orgId= and loads org into Redux (organization slice).

Protected pages read the org from Redux. All API calls, breadcrumbs, and timezone formatting use this context.

5.3 Redux Slices​

SlicePurpose
commonGlobal flags; hardRefresh signal that triggers list re-fetches
meetingRoomDisplayMeeting Room Display list + detail state
webhookLogsWebhook log lists for both displays and physical spaces
organizationCurrently selected org loaded by OrganizationProvider
IoTGatewayIoT Adapter list + detail state
physicalSpacePhysical Space list + detail state
bookingAccessCredentialBooking-access credential attempt log state

common.hardRefresh is the cross-feature invalidation signal — ListViewTable refetches whenever it changes.

5.4 List Views​

Most lists use ListViewTable with a shared URL contract: page, limit, sortBy, sortOrder, search, plus direct filter params.

5.5 Plaintext API Keys​

Security Requirement

Plaintext API keys are shown exactly once in OrgApiKeySecretModal after create or rotate. Do not log, store, or surface them anywhere else.

Raw fetch to /magic-links/:token/context; iframe sandbox is allow-scripts only.

The route must remain unauthenticated.

5.7 Backends​

ZenCore — REST API at VITE_BACKEND_URL.

ZenEdge — Realtime WebSocket at VITE_WEBSOCKET_SERVICE_URL.

See CLAUDE.md for full terminology and API contracts.