WebSocket connection authenticated at handshake, subscribed to a per-order channel. Server pushes status events; client merges into local state (TanStack Query cache or a simple reducer). Handle reconnection with backoff + resubscription, request a snapshot on connect to fill missed events, dedupe by event id, and fall back to polling on persistent failure. Consider SSE for one-way streams — simpler infrastructure, automatic reconnect.
Time-based grid (day/week/month). Events stored normalized with start/end + recurrence rule (RRULE). Render by computing visible occurrences for the current view. Handle overlap layout, drag-to-create/move, and timezones.
Break out into Board / Column / Card components. State shape keyed by id with column → ids ordering. APIs for move/reorder via optimistic updates. Discuss scalability (virtualization, pagination), offline, real-time, and accessibility.
Streaming transport (WS or SSE) feeds a normalized client store; the UI subscribes to slices via selectors. Reconciliation, presence, conflict resolution, backpressure, reconnect/replay are explicit design choices.
Two flag types: release flags (kill-switch, gradual rollout — short-lived) and experiment flags (A/B with variants and metrics — bounded life). Evaluate server-side when possible to avoid bundle-time flicker; deliver to the client via a context provider and a stable hashing rule on user/session id. Bake in: targeting rules, percentage rollouts, sticky assignment, defaults that fail safe, dashboards, and a process to remove dead flags.
Treat the local store as the source of truth; the network is an eventual-consistency partner. Cache shell assets via a Service Worker, persist data in IndexedDB (Dexie), queue mutations for replay on reconnect, and resolve merge conflicts via versioning or CRDTs. Surface offline state in the UI; never block the user on a request. Plan for partial connectivity (slow, flaky, captive portal), not just on/off.
Organize by feature domains, not by file type. Each module owns its UI, state, API calls, and types — and exposes a small public API. Enforce boundaries with lint rules (import restrictions), shared primitives only via a `core` package, and avoid cross-feature imports. Use TS path aliases, codeowners, and dependency-cruiser to keep the graph from collapsing.
Evaluate flags server-side when possible, ship a typed flag client, default to OFF, kill-switch every change, and prune flags aggressively after launch.
Split the UI into apps owned by different teams that deploy independently. Composition: server-side stitching, build-time integration, runtime (Module Federation), or iframes. Independent deploys solve org coordination, not technical performance. The costs — bundle duplication, shared-state coupling, cross-app navigation, design consistency — are real; only adopt when org structure demands it.