Skip to content

Commit 7f78b39

Browse files
authored
chore: add CLAUDE.md for Claude Code guidance (#3533)
## 🎯 Goal Add a `CLAUDE.md` file so that Claude Code (claude.ai/code) has the context it needs to work productively in this repo without lengthy exploration each session. ## πŸ›  Implementation details Single new file at repo root covering: - **Common commands** β€” build, lint, test (including single-test), install, sample app - **Architecture** β€” package structure, component hierarchy, source directory map - **Key patterns** β€” component override props, context three-layer pattern, native module abstraction, state stores, memoization strategy - **Testing patterns** β€” provider wrapping, mock builders and generators - **Theme system** β€” token tiers, topological resolution, generated platform tokens, mergeThemes - **Native / Expo relationship** β€” thin wrapper pattern, runtime platform branching - **Chat root provider** β€” client setup, subscription lifecycle, provider stack - **Offline DB** β€” schema location, version-based reinit - **Translations** β€” validation rules, build-translations sync - **Conventions** β€” commits, linting, formatting, branching, shared native sync ## 🎨 UI Changes N/A β€” documentation only. ## πŸ§ͺ Testing No code changes; no tests needed. ## β˜‘οΈ Checklist - [x] I have signed the [Stream CLA](https://docs.google.com/forms/d/e/1FAIpQLScFKsKkAJI7mhCr7K9rEIOpqIDThrWxuvxnwUq2XkHyG154vQ/viewform) (required) - [x] PR targets the `develop` branch - [ ] Documentation is updated - [x] New code is tested in main example apps, including all possible scenarios - [x] SampleApp iOS and Android - [x] Expo iOS and Android
1 parent 2cd2aa7 commit 7f78b39

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

β€ŽCLAUDE.mdβ€Ž

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Repository Overview
6+
7+
Stream Chat React Native SDK monorepo. The main SDK code lives in `package/` (published as `stream-chat-react-native-core`). Built on top of the `stream-chat` JS client library.
8+
9+
## Common Commands
10+
11+
All commands below run from the repo root unless noted otherwise.
12+
13+
### Build
14+
15+
```bash
16+
yarn build # Build all packages (runs in package/)
17+
cd package && yarn build # Build SDK directly
18+
```
19+
20+
### Lint & Format
21+
22+
```bash
23+
cd package && yarn lint # Check prettier + eslint + translation validation (max-warnings 0)
24+
cd package && yarn lint-fix # Auto-fix lint and formatting issues
25+
```
26+
27+
### Test
28+
29+
```bash
30+
cd package && yarn test:unit # Run all unit tests (sets TZ=UTC)
31+
cd package && yarn test:coverage # Run with coverage report
32+
cd package && TZ=UTC npx jest path/to/test.test.tsx # Run a single test file
33+
```
34+
35+
Tests use Jest with `react-native` preset and `@testing-library/react-native`. Test files live alongside source at `src/**/__tests__/*.test.ts(x)`. Mock builders are in `src/mock-builders/`.
36+
37+
To run a single test, you can also temporarily add the file path to the `testRegex` array in `package/jest.config.js`.
38+
39+
### Install
40+
41+
```bash
42+
yarn install --frozen-lockfile # Root dependencies
43+
cd package && yarn install-all # SDK + native-package + expo-package
44+
```
45+
46+
### Sample App
47+
48+
```bash
49+
cd examples/SampleApp && yarn install
50+
cd examples/SampleApp && yarn start # Metro bundler
51+
cd examples/SampleApp && yarn ios # Run iOS
52+
cd examples/SampleApp && yarn android # Run Android
53+
```
54+
55+
## Architecture
56+
57+
### Package Structure
58+
59+
- `package/` β€” Main SDK (`stream-chat-react-native-core`)
60+
- `package/native-package/` β€” React Native native module wrappers
61+
- `package/expo-package/` β€” Expo-compatible wrapper
62+
- `examples/SampleApp/` β€” Full sample app with navigation
63+
- `release/` β€” Semantic release scripts
64+
65+
### SDK Source (`package/src/`)
66+
67+
**Component hierarchy**: `<Chat>` β†’ `<Channel>` β†’ `<MessageList>` / `<MessageInput>` / `<Thread>`
68+
69+
- `components/` β€” UI components (~28 major ones: ChannelList, MessageList, MessageInput, Thread, Poll, ImageGallery, etc.)
70+
- `contexts/` β€” React Context providers (~33 contexts). The primary way components receive state and callbacks. Key contexts: `ChatContext`, `ChannelContext`, `MessagesContext`, `ThemeContext`, `TranslationContext`
71+
- `hooks/` β€” Custom hooks (~27+). Access contexts via `useChannelContext()`, `useMessageContext()`, etc.
72+
- `state-store/` β€” Client-side state stores using `useSyncExternalStore` with selector pattern (audio player, image gallery, message overlay, etc.)
73+
- `store/` β€” Offline SQLite persistence layer. `OfflineDB` class with mappers for channels, messages, reactions, members, drafts, reminders. Schema in `store/schema.ts`
74+
- `theme/` β€” Deep theming system (colors, typography, spacing, per-component overrides) via `ThemeContext`
75+
- `i18n/` β€” Internationalization with i18next (14 languages). `Streami18n` wrapper class
76+
- `middlewares/` β€” Command UI middlewares (attachments, emoji)
77+
- `icons/` β€” SVG icon components
78+
79+
### Key Patterns
80+
81+
**Component override pattern**: Nearly every UI element is replaceable via props. Parent components (e.g., `Channel`) accept 50+ `React.ComponentType` props for sub-components (`Message`, `MessageContent`, `DateHeader`, `TypingIndicator`, etc.). These props are forwarded into Context providers so deeply nested children can access them without prop drilling.
82+
83+
**Context three-layer pattern**: Each context follows the same structure:
84+
85+
1. `createContext()` with a sentinel default value (`DEFAULT_BASE_CONTEXT_VALUE`)
86+
2. A `<XProvider>` wrapper component
87+
3. A `useXContext()` hook that throws if used outside the provider (suppressed in test env via `isTestEnvironment()`)
88+
89+
Context values are assembled in dedicated `useCreateXContext()` hooks (e.g., `useCreateChannelContext`) that carefully memoize with selective dependencies to avoid unnecessary re-renders.
90+
91+
**Native module abstraction**: `native.ts` defines TypeScript interfaces for all platform-specific capabilities (image picking, compression, haptics, audio/video, clipboard). Implementations are injected at runtime via `registerNativeHandlers()` β€” `stream-chat-expo` provides Expo implementations, `stream-chat-react-native` provides bare RN ones. Calling an unregistered handler throws with a message to import the right package.
92+
93+
**State stores**: `useSyncExternalStore`-based stores in `state-store/` with `useStateStore(store, selector)` for fine-grained subscriptions outside the context system.
94+
95+
**Memoization**: Components use `React.memo()` with custom `areEqual` comparators (not HOCs) to prevent re-renders.
96+
97+
**Offline-first**: SQLite-backed persistence with sync status tracking and pending task management.
98+
99+
**Builder-bob builds**: Outputs CommonJS (`lib/commonjs`), ESM (`lib/module`), and TypeScript declarations (`lib/typescript`).
100+
101+
### Testing Patterns
102+
103+
Tests use `renderHook()` and `render()` from `@testing-library/react-native`. Components/hooks must be wrapped in the required provider stack (e.g., `Chat` β†’ `Channel` β†’ feature provider).
104+
105+
**Mock builders** (`src/mock-builders/`):
106+
107+
- `api/initiateClientWithChannels.js` β€” creates a test client + channels in one call
108+
- `generator/` β€” factories: `generateMessage()`, `generateChannel()`, `generateUser()`, `generateMember()`, `generateStaticMessage(seed)` (deterministic via UUID v5)
109+
- `attachments.js` β€” `generateImageAttachment()`, `generateFileAttachment()`, `generateAudioAttachment()`
110+
111+
Reanimated and native modules are mocked via Proxy patterns in test setup files.
112+
113+
### Theme System
114+
115+
Themes follow a three-tier token architecture: **Primitives** (raw colors) β†’ **Semantics** (e.g., `colors.error.primary`) β†’ **Components** (per-component overrides). Token references use `$key` string syntax (e.g., `"$blue500"`) and are resolved via topological sort in `theme/topologicalResolution.ts`, so declaration order doesn't matter.
116+
117+
Platform-specific tokens are **generated** files in `src/theme/generated/{light,dark}/StreamTokens.{ios,android,web}.ts` β€” regenerate via `sync-theme.sh` if design tokens change; don't hand-edit.
118+
119+
Custom themes are passed as `style` prop to `<Chat>`. `mergeThemes()` deep-merges custom style over base theme (deep-cloned via `JSON.parse(JSON.stringify())`). Light/dark mode is auto-detected via `useColorScheme()`.
120+
121+
### Native / Expo Package Relationship
122+
123+
`native-package/` and `expo-package/` are thin wrappers around `stream-chat-react-native-core`. They:
124+
125+
1. Call `registerNativeHandlers()` with platform-specific implementations (native modules vs Expo APIs)
126+
2. Export optional dependency wrappers (`Audio`, `Video`, `FlatList`) from `src/optionalDependencies/`
127+
3. Re-export everything from core: `export * from 'stream-chat-react-native-core'`
128+
129+
Platform branching uses runtime `Platform.select()` / `Platform.OS` checks β€” there are no `.ios.ts` / `.android.ts` source file splits.
130+
131+
### Chat Component (Root Provider)
132+
133+
`<Chat client={client}>` is the entry point. It:
134+
135+
- Sets SDK metadata on the `stream-chat` client (identifier, device info)
136+
- Disables the JS client's `recoverStateOnReconnect` (the SDK handles recovery itself)
137+
- Registers subscriptions for threads, polls, and reminders (cleaned up on unmount)
138+
- Initializes `OfflineDB` if `enableOfflineSupport` is true
139+
- Wraps children in: `ChatProvider` β†’ `TranslationProvider` β†’ `ThemeProvider` β†’ `ChannelsStateProvider`
140+
141+
### Offline DB
142+
143+
SQLite schema is in `store/schema.ts`. DB versioning uses `PRAGMA user_version` β€” a version mismatch triggers full DB reinit (no incremental migrations). Current version is tracked in `SqliteClient.dbVersion`.
144+
145+
### Translations
146+
147+
Translation JSON files live in `src/i18n/`. `validate-translations` (run as part of `yarn lint`) checks that no translation key has an empty string value. When adding/updating translations, run `yarn build-translations` (i18next-cli sync) to keep files in sync.
148+
149+
## Conventions
150+
151+
- **Conventional commits** enforced by commitlint: `feat:`, `fix:`, `docs:`, `refactor:`, etc.
152+
- **ESLint 9 flat config** at `package/eslint.config.mjs`, strict (max-warnings 0)
153+
- **Prettier**: single quotes, trailing commas, 100 char width (see `.prettierrc`)
154+
- **TypeScript strict mode** with platform-specific module suffixes (`.ios`, `.android`, `.web`)
155+
- Git branches: PRs target `develop`, `main` is production releases only
156+
- **Shared native sync**: Run `yarn shared-native:sync` from `package/` after modifying shared native code to copy to native-package and expo-package

0 commit comments

Comments
Β (0)