|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Development Commands |
| 6 | + |
| 7 | +### Package Management |
| 8 | + |
| 9 | +- Use `pnpm install` (or `pnpm install --ignore-scripts` on Windows) |
| 10 | +- Monorepo managed with Turborepo and pnpm workspaces |
| 11 | + |
| 12 | +### Building |
| 13 | + |
| 14 | +```bash |
| 15 | +# Build all packages |
| 16 | +pnpm build |
| 17 | + |
| 18 | +# Build specific packages with dependencies |
| 19 | +turbo run build --filter=./packages/* |
| 20 | + |
| 21 | +# Development with watch mode |
| 22 | +pnpm dev # Core thirdweb package |
| 23 | +pnpm dashboard # Run dashboard + dependencies |
| 24 | +pnpm playground # Run playground + dependencies |
| 25 | +pnpm portal # Run portal docs + dependencies |
| 26 | +``` |
| 27 | + |
| 28 | +### Testing |
| 29 | + |
| 30 | +```bash |
| 31 | +# Run all tests |
| 32 | +pnpm test |
| 33 | + |
| 34 | +# Interactive testing (thirdweb package) |
| 35 | +cd packages/thirdweb && pnpm test:devr |
| 36 | + |
| 37 | +# Test specific file |
| 38 | +pnpm test:dev <path-to-test-file> |
| 39 | + |
| 40 | +# E2E testing (dashboard) |
| 41 | +cd apps/dashboard && pnpm playwright |
| 42 | +``` |
| 43 | + |
| 44 | +### Code Quality |
| 45 | + |
| 46 | +```bash |
| 47 | +# Lint all packages |
| 48 | +pnpm lint |
| 49 | + |
| 50 | +# Auto-fix linting issues |
| 51 | +pnpm fix |
| 52 | + |
| 53 | +# Format code |
| 54 | +turbo run format |
| 55 | + |
| 56 | +# Biome is the primary linter/formatter |
| 57 | +``` |
| 58 | + |
| 59 | +### Development Workflow |
| 60 | + |
| 61 | +```bash |
| 62 | +# Start development server for dashboard |
| 63 | +pnpm dashboard |
| 64 | + |
| 65 | +# Start playground for SDK testing |
| 66 | +pnpm playground |
| 67 | + |
| 68 | +# Generate changeset for releases |
| 69 | +pnpm changeset |
| 70 | + |
| 71 | +# Version packages |
| 72 | +pnpm version-packages |
| 73 | +``` |
| 74 | + |
| 75 | +## Repository Architecture |
| 76 | + |
| 77 | +### Monorepo Structure |
| 78 | + |
| 79 | +This is a Turborepo monorepo with the main thirdweb v5 SDK consolidated into `/packages/thirdweb/`. Legacy packages are in `/legacy_packages/`. |
| 80 | + |
| 81 | +### Core Package (`/packages/thirdweb/`) |
| 82 | + |
| 83 | +**Main Modules:** |
| 84 | + |
| 85 | +- `client/` - ThirdwebClient foundation |
| 86 | +- `chains/` - 50+ supported blockchain definitions |
| 87 | +- `contract/` - Contract interaction with automatic ABI resolution |
| 88 | +- `transaction/` - Transaction management and execution |
| 89 | +- `wallets/` - Comprehensive wallet integration system |
| 90 | +- `extensions/` - Modular contract extensions (ERC20, ERC721, etc.) |
| 91 | +- `auth/` - SIWE authentication and signature verification |
| 92 | +- `pay/` - Fiat and crypto payment infrastructure |
| 93 | +- `storage/` - IPFS integration for decentralized storage |
| 94 | +- `rpc/` - Low-level blockchain communication |
| 95 | + |
| 96 | +**Exports Structure:** |
| 97 | +The SDK uses modular exports from `src/exports/` including: |
| 98 | + |
| 99 | +- `thirdweb.ts` - Core client and utilities |
| 100 | +- `chains.ts` - Chain definitions |
| 101 | +- `wallets.ts` - Wallet connectors |
| 102 | +- `react.ts` - React hooks and components |
| 103 | +- `extensions/` - Contract standards and protocols |
| 104 | + |
| 105 | +### Applications (`/apps/`) |
| 106 | + |
| 107 | +- **dashboard** - Web-based developer console (Next.js, Chakra UI) |
| 108 | +- **playground-web** - Interactive SDK testing environment |
| 109 | +- **portal** - Documentation site with MDX |
| 110 | +- **nebula** - Account abstraction and smart wallet management |
| 111 | +- **wallet-ui** - Wallet interface and testing |
| 112 | + |
| 113 | +### Key Packages (`/packages/`) |
| 114 | + |
| 115 | +- **thirdweb** - Main SDK (TypeScript, React, React Native) |
| 116 | +- **engine** - thirdweb Engine API client |
| 117 | +- **insight** - Analytics and data APIs |
| 118 | +- **nebula** - Account abstraction client |
| 119 | +- **service-utils** - Shared utilities across services |
| 120 | + |
| 121 | +## Development Practices |
| 122 | + |
| 123 | +### GitHub Workflow & Pull Requests |
| 124 | + |
| 125 | +- **PR titles**: Must start with affected workspace in brackets (e.g. `[SDK]`, `[Dashboard]`, `[Portal]`, `[Playground]`) |
| 126 | +- **PR descriptions**: Begin with one-sentence summary, add checklist of changes, reference issues with `Fixes #123` |
| 127 | +- **Commits**: Keep small and topical – one logical change per commit |
| 128 | +- **Branch naming**: Use `area/brief-topic` format (e.g. `sdk/fix-gas-estimate`). Avoid personal names |
| 129 | +- **Reviews**: Request at least one core maintainer review. Do not self-merge unless sole package owner |
| 130 | +- **CI requirements**: All checks (type-check, Biome, tests) must pass before merging |
| 131 | + |
| 132 | +### Code Quality & Formatting |
| 133 | + |
| 134 | +- **Biome**: Primary linter/formatter (rules in `biome.json`) |
| 135 | +- **Pre-commit**: Run `pnpm biome check --apply` before committing |
| 136 | +- **Build verification**: Run `pnpm build` after each file change to ensure everything builds |
| 137 | +- Avoid editor-specific configs; rely on shared settings |
| 138 | + |
| 139 | +### TypeScript Guidelines |
| 140 | + |
| 141 | +- **Style**: Write idiomatic TypeScript with explicit function declarations and return types |
| 142 | +- **File structure**: Limit each file to one stateless, single-responsibility function for clarity |
| 143 | +- **Types**: Re-use shared types from `@/types` or local `types.ts` barrels |
| 144 | +- **Interfaces vs Types**: Prefer type aliases over interface except for nominal shapes |
| 145 | +- **Type safety**: Avoid `any` and `unknown` unless unavoidable; narrow generics when possible |
| 146 | +- **Architecture**: Choose composition over inheritance; leverage utility types (`Partial`, `Pick`, etc.) |
| 147 | + |
| 148 | +### Testing Strategy |
| 149 | + |
| 150 | +- **Co-location**: Place tests alongside code: `foo.ts` ↔ `foo.test.ts` |
| 151 | +- **Test approach**: Use real function invocations with stub data; avoid brittle mocks |
| 152 | +- **Network mocking**: Use Mock Service Worker (MSW) for fetch/HTTP call interception |
| 153 | +- **Test quality**: Keep tests deterministic and side-effect free |
| 154 | +- **Running tests**: `cd packages/thirdweb && pnpm test:dev <filename>` |
| 155 | +- **Test accounts**: Predefined accounts in `test/src/test-wallets.ts` |
| 156 | +- **Chain forking**: Use `FORKED_ETHEREUM_CHAIN` for mainnet interactions, `ANVIL_CHAIN` for isolated tests |
| 157 | + |
| 158 | +### SDK Development (`packages/thirdweb`) |
| 159 | + |
| 160 | +#### Public API Guidelines |
| 161 | +- **Exports**: Export everything via `exports/` directory, grouped by feature |
| 162 | +- **Documentation**: Every public symbol must have comprehensive TSDoc with: |
| 163 | + - At least one `@example` block that compiles |
| 164 | + - Custom annotation tags (`@beta`, `@internal`, `@experimental`) |
| 165 | +- **Comments**: Comment only ambiguous logic; avoid restating TypeScript in prose |
| 166 | + |
| 167 | +#### Performance Optimization |
| 168 | +- **Lazy loading**: Load heavy dependencies inside async paths to keep initial bundle lean: |
| 169 | + ```typescript |
| 170 | + const { jsPDF } = await import("jspdf"); |
| 171 | + ``` |
| 172 | +- **Bundle budgets**: Track via `package.json#size-limit` |
| 173 | +- **Dependencies**: De-duplicate across packages through pnpm workspace hoisting |
| 174 | + |
| 175 | +### Dashboard & Playground Development |
| 176 | + |
| 177 | +#### UI Component Standards |
| 178 | +- **Core components**: Import primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) |
| 179 | +- **Navigation**: Use `NavLink` for internal navigation with automatic active states |
| 180 | +- **Organization**: Group feature-specific components under `feature/components/*` with barrel `index.ts` |
| 181 | + |
| 182 | +#### Styling Conventions |
| 183 | +- **CSS framework**: Tailwind CSS only – no inline styles or CSS modules |
| 184 | +- **Class merging**: Use `cn()` from `@/lib/utils` for conditional logic |
| 185 | +- **Design tokens**: Use design system tokens (backgrounds: `bg-card`, borders: `border-border`, muted text: `text-muted-foreground`) |
| 186 | +- **Component API**: Expose `className` prop on root element for overrides |
| 187 | + |
| 188 | +#### Component Architecture |
| 189 | +- **Server Components** (Node edge): |
| 190 | + - Start files with `import "server-only";` |
| 191 | + - Read cookies/headers with `next/headers` |
| 192 | + - Access server-only environment variables |
| 193 | + - Perform heavy data fetching |
| 194 | + - Implement redirect logic with `redirect()` from `next/navigation` |
| 195 | +- **Client Components** (browser): |
| 196 | + - Begin files with `'use client';` |
| 197 | + - Handle interactive UI with React hooks (`useState`, `useEffect`, React Query, wallet hooks) |
| 198 | + - Access browser APIs (`localStorage`, `window`, `IntersectionObserver`) |
| 199 | + - Support fast transitions with prefetched data |
| 200 | + |
| 201 | +#### Data Fetching Patterns |
| 202 | +- **Server Side**: |
| 203 | + - Always call `getAuthToken()` to retrieve JWT from cookies |
| 204 | + - Use `Authorization: Bearer` header – never embed tokens in URLs |
| 205 | + - Return typed results (`Project[]`, `User[]`) – avoid `any` |
| 206 | +- **Client Side**: |
| 207 | + - Wrap calls in React Query (`@tanstack/react-query`) |
| 208 | + - Use descriptive, stable `queryKeys` for cache hits |
| 209 | + - Configure `staleTime`/`cacheTime` based on freshness (default ≥ 60s) |
| 210 | + - Keep tokens secret via internal API routes or server actions |
| 211 | + |
| 212 | +#### Analytics Event Guidelines |
| 213 | +- **When to add**: Only create events that answer clear product/business questions |
| 214 | +- **Check duplicates**: Review `src/@/analytics/report.ts` first |
| 215 | +- **Naming**: |
| 216 | + - Event name: human-readable `<subject> <verb>` (e.g. "contract deployed") |
| 217 | + - Function: `report<Subject><Verb>` (PascalCase) |
| 218 | +- **Template**: |
| 219 | + ```typescript |
| 220 | + /** |
| 221 | + * ### Why do we need to report this event? |
| 222 | + * - Tracks number of contracts deployed |
| 223 | + * |
| 224 | + * ### Who is responsible for this event? |
| 225 | + * @username |
| 226 | + */ |
| 227 | + export function reportContractDeployed(properties: { |
| 228 | + address: string; |
| 229 | + chainId: number; |
| 230 | + }) { |
| 231 | + posthog.capture("contract deployed", properties); |
| 232 | + } |
| 233 | + ``` |
| 234 | +- **Client-side only**: Never import `posthog-js` in server components |
| 235 | +- **Changes**: Inform **#eng-core-services** before renaming/removing events |
| 236 | + |
| 237 | +### Extension Development |
| 238 | + |
| 239 | +- Extensions follow modular pattern in `src/extensions/` |
| 240 | +- Auto-generated contracts from ABI definitions |
| 241 | +- Composable functions with TypeScript safety |
| 242 | +- Support for read/write operations |
| 243 | + |
| 244 | +### Wallet Architecture |
| 245 | + |
| 246 | +- Unified `Wallet` and `Account` interfaces |
| 247 | +- Support for in-app wallets (social/email login) |
| 248 | +- Smart wallets with account abstraction |
| 249 | +- EIP-1193, EIP-5792, EIP-7702 standard support |
| 250 | + |
| 251 | +## Contribution Workflow |
| 252 | + |
| 253 | +1. **Fork and Clone**: Create fork, clone, create feature branch |
| 254 | +2. **Install**: `pnpm install` (use `--ignore-scripts` on Windows) |
| 255 | +3. **Develop**: Use appropriate dev commands above |
| 256 | +4. **Test**: Write unit tests, run linting, test on demo apps |
| 257 | +5. **Changeset**: Run `pnpm changeset` for semantic versioning |
| 258 | +6. **PR**: Submit pull request to main branch |
| 259 | + |
| 260 | +### Release Testing |
| 261 | + |
| 262 | +Comment `/release-pr` on PR to trigger dev release to npm for testing. |
| 263 | + |
| 264 | +### Changeset Guidelines |
| 265 | + |
| 266 | +Each change in `packages/*` should contain a changeset for the appropriate package with the appropriate version bump: |
| 267 | +- **patch**: Changes that don't impact the public API |
| 268 | +- **minor**: Any new/modified public API |
| 269 | +- **major**: Breaking changes (surface prominently in PR descriptions) |
| 270 | + |
| 271 | +### Documentation Standards |
| 272 | + |
| 273 | +- For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code |
| 274 | +- Surface breaking changes prominently in PR descriptions |
| 275 | +- Keep documentation focused on developer experience and practical usage |
| 276 | + |
| 277 | +## Multi-Platform Support |
| 278 | + |
| 279 | +The SDK supports: |
| 280 | + |
| 281 | +- **Web**: React hooks and components |
| 282 | +- **React Native**: Mobile-specific exports and components |
| 283 | +- **Node.js**: Server-side functionality |
| 284 | +- **Framework Adapters**: Wagmi, Ethers compatibility layers |
| 285 | + |
| 286 | +Key files: |
| 287 | + |
| 288 | +- `src/exports/react.native.ts` - React Native specific exports |
| 289 | +- `packages/react-native-adapter/` - Mobile platform shims |
| 290 | +- `packages/wagmi-adapter/` - Wagmi ecosystem integration |
0 commit comments