Files
message-inbox-web-frontend-sdk/docs/ARCHITECTURE.md
T
2026-07-17 21:48:37 +05:30

6.4 KiB

Architecture

The one idea

Three product surfaces — Messaging, Inbox, Support — are built on one kernel: a headless React SDK talking to a BFF. Everything a user sees is a projection of the same data model, exactly like the IIOS "everything is an interaction" spine (see IIOS_INTEGRATION.md).

┌──────────────────────────────────────────────────────────────────────┐
│  Browser (Next.js app · apps/web)                                      │
│                                                                        │
│   Components (nav / message / inbox / support / overlays)              │
│        │  use hooks, never fetch directly                             │
│   ┌────▼───────────────────────────────────────────┐                 │
│   │  @lynkd/messaging-inbox-sdk                      │                 │
│   │   Provider · hooks · theme · feature flags       │                 │
│   │   BffClient  ────────────────┐                   │                 │
│   └──────────────────────────────┼───────────────────┘                 │
└──────────────────────────────────┼─────────────────────────────────────┘
                                    │  fetch /api/bff/**   (the ONLY seam)
┌──────────────────────────────────▼─────────────────────────────────────┐
│  BFF (Next.js route handlers · apps/web/app/api/bff/**)                 │
│     bootstrap · channels · messages · threads · reactions · inbox ·     │
│     support/tickets · search · notifications                            │
│        │                                                                │
│   ┌────▼─────────────────────────┐         (swap this box for real)     │
│   │  Mock store (in-memory)      │  ──►  IIOS service / NestJS / Supabase │
│   └──────────────────────────────┘                                       │
└──────────────────────────────────────────────────────────────────────────┘

Layers

1. SDK — packages/messaging-inbox-sdk

Framework-agnostic-ish React layer (needs React 18/19). No knowledge of Next.js, no backend coupling.

  • types.ts — the domain model. User, Channel (channel/private/dm/group_dm), Message (+ parts, reactions, attachments, thread metadata), InboxItem, Ticket, Notification, SearchResult, Bootstrap.
  • config.tsFeatureFlags + ThemeConfig + resolveConfig() (defaults → env → props).
  • theme.ts — turns a ThemeConfig into CSS variables and applies them to <html>.
  • client.tsBffClient: one typed method per BFF endpoint. The only place that does fetch.
  • provider.tsx<MessagingInboxProvider> holds config, the client, bootstrap data, and theme/scheme state. Exposes useSdk, useFeature(s), useTheme.
  • hooks.ts — data hooks: useChannels, useMessages, useThread, useInbox, useTickets, useTicket, useSearch, useNotifications, useAvailability, useTyping.

2. BFF — apps/web/app/api/bff/**

Next.js Route Handlers. This is the Backend-For-Frontend: it shapes data specifically for this UI, keeps secrets/tokens server-side, and decouples the client from the real backend. Today each handler calls the in-memory mock store; each maps 1:1 to a BffClient method.

3. Mock store — apps/web/lib/mock/

data.ts is the seed (a full LynkedUp-flavoured workspace). store.ts is a mutable singleton (persists across requests in one Node process) implementing send/react/pin/save/patch/reply/ search. This is the box you replace to go real — nothing above it changes.

4. App shell + components — apps/web/components

  • nav/WorkspaceRail (Slack-style far-left), Sidebar (sectioned channels + user card), Header (title + search + theme + notifications + user).
  • message/ChannelView, MessageItem, Composer, ThreadPanel, EmojiPicker.
  • inbox/InboxView.
  • support/SupportView (master-detail console).
  • overlays/CommandPalette, NotificationsPanel, ProfileDrawer, ThemingPanel, HuddleBar.
  • ui/primitives.tsxAvatar, PresenceDot, CountBadge, Chip, IconButton.
  • AppShell.tsx composes rail + sidebar + main + thread panel + overlays.

Request lifecycle (send a message)

  1. Composer calls send(body) from useMessages(channelId).
  2. The hook calls client.sendMessage(channelId, body)POST /api/bff/channels/:id/messages.
  3. The route handler calls store.send(...), which appends a Message and bumps thread/channel metadata, and returns it.
  4. The hook appends the returned message to local state → it renders instantly.

Reactions, pins, saves, inbox transitions, and ticket replies follow the same shape.

Config lifecycle (flags + theme)

  1. app/layout.tsx (server) calls getServerConfig()resolveConfig({ env: process.env }).
  2. The resolved plain SdkConfig is passed to <Providers config=…> (client) and the theme is inlined into <head> for a flash-free first paint.
  3. MessagingInboxProvider applies theme vars to <html>, manages light/dark, and exposes flags via useFeature.

Why these choices

See ../.claude/memory/architecture-decisions.md for the rationale (workspace layout, BFF seam, server-resolved config, CSS-variable theming, data-driven flags, and why the NestJS/DB backend is documented rather than built for this demo).