4.4 KiB
CLAUDE.md
Guidance for Claude Code (and humans) working in this repo.
What this is
A static demo (mock data, no real backend) of a Slack-grade messaging + inbox + support
product, shipped as a reusable React SDK + a Next.js demo app, styled to match the
LynkedUp Pro dashboard (dark + amber #FDA913, plus full light mode). Built on the BFF pattern:
the UI only ever calls its own BFF (Next route handlers over an in-memory store), so swapping to a
real backend (IIOS / NestJS / Supabase) touches only the BFF.
Commands
pnpm install # Node >= 20, pnpm >= 8
pnpm dev # dev server → http://localhost:4300
pnpm build # production build (all packages)
pnpm typecheck # type-check SDK + app
pnpm --filter @lynkd/web dev # run just the web app
There is no packageManager pin on purpose (a pin made corepack try to fetch a pnpm build
and fail offline). If corepack nags, run corepack disable once. sharp's build is intentionally
skipped (allowBuilds: sharp: false in pnpm-workspace.yaml) — not needed for the static demo.
Two backend modes — BFF_BACKEND in apps/web/.env.local:
mock(default): rich in-memory JSON workspace, everything works. Best for demos.iios: proxies the live IIOS service. Run IIOS +node scripts/seed-iios.mjsto populate it, then flip the flag. Full steps indocs/IIOS_INTEGRATION.md. Redis not required.
reactStrictMode is off (next.config) so dev matches prod render behaviour (avoids the
double-mount that broke imperative DOM effects).
Layout
packages/messaging-inbox-sdk/src/ the SDK (@lynkd/messaging-inbox-sdk)
types.ts domain model config.ts feature flags + theme tokens + env resolution
client.ts BffClient (only fetch seam) theme.ts CSS-var applier
provider.tsx <MessagingInboxProvider> + useSdk/useTheme/useFeature
hooks.ts useMessages/useThread/useInbox/useTickets/useSearch/useNotifications/…
apps/web/
app/layout.tsx server: resolves config, no-flash theme script
app/(app)/… shell routes: c/[id], inbox, support/[id], threads, saved, …
app/api/bff/** the BFF (route handlers) — 1:1 with BffClient methods
components/nav|message|inbox|support|overlays|ui presentation
lib/mock/{data,store}.ts seed data + in-memory mutable store (the swap seam)
lib/{config,ui-state,format,rich-text}.ts
Conventions
- Components using SDK hooks or
useUineed"use client". Routepage.tsxare thin server components that render a client view. - Never hard-code colors/radii. Use semantic Tailwind tokens (
bg-panel,text-muted,border-border,bg-accent,rounded-card,rounded-control) → they map to CSS vars, which is what keeps light/dark + live theming working. - Feature flags are data: add to
FeatureFlags/defaultFlagsinconfig.ts; env override is automatic (NEXT_PUBLIC_FEATURE_<UPPER_SNAKE>); read withuseFeature("x"). - Overlays/modals/toasts live in
lib/ui-state.tsx(useUi):openModal,toast,openThread,openProfile,startHuddle, etc. Escape closes the top-most surface. - The composer is a contentEditable WYSIWYG that serializes to markdown;
lib/rich-text.tsxrenders that markdown. Keep the two in sync if you add a marker. - Adding a data feature touches, in order:
lib/mock/store.ts→app/api/bff/**/route.ts→client.ts→hooks.ts→ the component.
Gotchas
- The mock store is a
globalThissingleton to survive HMR. If you add/rename a store method and get "X is not a function" at runtime, bump the cache key (__lynkdStore_vN) inlib/mock/store.tsor restartpnpm dev. - Next 15 route-handler
paramsare async:{ params }: { params: Promise<…> }+await params. - Next.js is pinned at a demo version with a known CVE — bump before any real deploy.
- BFF params/mock timestamps are relative to server start; the store resets on restart.
Verifying changes
Drive the real app (Playwright MCP or a browser) — don't rely on types alone. Quick checks:
send a message, react via hover, create a channel, resolve a ticket, toggle theme, resize to
~400px. See docs/ for deep dives and .claude/ for project memory.
Docs
README.md · docs/SETUP_LOCAL.md · docs/ARCHITECTURE.md · docs/BFF.md · docs/SDK.md ·
docs/THEMING.md · docs/FEATURE_FLAGS.md · docs/IIOS_INTEGRATION.md · .claude/ONBOARDING.md