|
| 1 | +--- |
| 2 | +description: Monorepo-wide rules for Reown AppKit: structure, layering, packaging, and TS/SDK best practices |
| 3 | +globs: |
| 4 | + - "packages/**" |
| 5 | + - "apps/**" |
| 6 | + - "examples/**" |
| 7 | + - "services/**" |
| 8 | + - "scripts/**" |
| 9 | + - "turbo.json" |
| 10 | + - "pnpm-workspace.yaml" |
| 11 | + - "vitest.workspace.ts" |
| 12 | +alwaysApply: true |
| 13 | +--- |
| 14 | + |
| 15 | +## Cursor Rules: Reown AppKit Monorepo |
| 16 | + |
| 17 | +This document orients Cursor to the structure, relationships, and common patterns across the Reown AppKit monorepo. It also encodes TypeScript and SDK development best practices to keep edits consistent, safe, and maintainable. |
| 18 | + |
| 19 | +### Monorepo Overview |
| 20 | + |
| 21 | +- **Package manager**: `pnpm` workspaces (`pnpm-workspace.yaml`) |
| 22 | +- **Build Orchestration**: `turbo` tasks (`turbo.json`) with cached `build`, `typecheck`, `lint`, `test` |
| 23 | +- **Testing**: `vitest` (workspace config in `vitest.workspace.ts`, default `jsdom` env) |
| 24 | +- **Repo roots**: |
| 25 | + - `packages/` — publishable libraries and internal SDK modules |
| 26 | + - `apps/` — product and demo applications (`gallery`, `laboratory`, `demo`, `browser-extension`) |
| 27 | + - `examples/` — integration examples (Next, React, Vue, Svelte, plain HTML) |
| 28 | + - `services/` — ancillary services (e.g., `id-allocation-service`) |
| 29 | + - `scripts/`, `patches/`, root configs |
| 30 | + |
| 31 | +### High-Level Architecture and Package Roles |
| 32 | + |
| 33 | +- **SDK Facade**: `@reown/appkit` |
| 34 | + |
| 35 | + - Public, framework-agnostic entrypoint. Re-exports subdomains and framework layers via subpath exports. |
| 36 | + - Depends on: `@reown/appkit-common`, `@reown/appkit-controllers`, `@reown/appkit-pay`, `@reown/appkit-polyfills`, `@reown/appkit-scaffold-ui`, `@reown/appkit-ui`, `@reown/appkit-utils`, `@reown/appkit-wallet`, plus ecosystem deps (`valtio`, `viem`, `@walletconnect/universal-provider`). |
| 37 | + - Provides subpaths like `./react`, `./vue`, `./utils`, `./adapters`, `./connectors`, etc. |
| 38 | + |
| 39 | +- **Domain Foundations**: |
| 40 | + |
| 41 | + - `@reown/appkit-common`: shared types, math/date utils, light helpers. ESM only. |
| 42 | + - `@reown/appkit-wallet`: wallet models, schema validation, core wallet utilities (depends on `common`, `polyfills`). |
| 43 | + - `@reown/appkit-controllers`: stateful logic and business rules, with `valtio` for reactive state. Framework-agnostic; provides optional `react`/`vue` subpaths. |
| 44 | + - `@reown/appkit-utils`: integration helpers per chain/family (Ethers, Solana, Bitcoin, Wallet Standard). Depends on `common`, `controllers`, `wallet`, `polyfills`. |
| 45 | + |
| 46 | +- **UI Layers**: |
| 47 | + |
| 48 | + - `@reown/appkit-ui`: low-level UI as Web Components (Lit). Exports many `wui-*` components; no app logic. |
| 49 | + - `@reown/appkit-scaffold-ui`: mid/high-level UI flows (modal, router containers, pay/onramp flows). Composes `@reown/appkit-ui` and `controllers`. |
| 50 | + - `@reown/appkit-wallet-button`: focused UI package that composes `ui`, `controllers`, `utils`; optional `@lit/react` wrapper. |
| 51 | + |
| 52 | +- **Authentication and Pay**: |
| 53 | + |
| 54 | + - `@reown/appkit-siwe`: Sign-In With Ethereum UX + controllers integration. |
| 55 | + - `@reown/appkit-siwx`: Cross-chain SIWx utilities for EVM, Solana, Bitcoin, etc. No direct UI dependency. |
| 56 | + - `@reown/appkit-pay`: UI + state for pay flows; composes `ui`, `controllers`, `utils`. |
| 57 | + |
| 58 | +- **Adapters (ecosystem integrations)**: `packages/adapters/*` |
| 59 | + |
| 60 | + - `@reown/appkit-adapter-wagmi`, `-ethers`, `-ethers5`, `-solana`, `-bitcoin` (and private `-polkadot`). |
| 61 | + - All depend on `@reown/appkit` + foundations; expose framework subpaths when relevant (`react`, `vue` in some packages). |
| 62 | + - Use `peerDependencies` for host frameworks/SDKs (e.g., `wagmi`, `viem`, `ethers`) and `optionalDependencies` for optional wallets/providers. |
| 63 | + |
| 64 | +- **Bridging, Polyfills, Experimental, CDN**: |
| 65 | + |
| 66 | + - `@reown/appkit-universal-connector`: thin bridge to `@walletconnect/universal-provider`. |
| 67 | + - `@reown/appkit-polyfills`: browser `buffer` and similar shims. |
| 68 | + - `@reown/appkit-experimental`: gated/unstable features (e.g., smart session). Depends on core packages. |
| 69 | + - `@reown/appkit-cdn`: prebundled CDN builds (not tree-shaken by consumers). Depends on `appkit` and adapters. |
| 70 | + |
| 71 | +- **Tooling**: |
| 72 | + - `@reown/appkit-testing`: test harnesses (includes Playwright for e2e; depends on `@reown/appkit`). |
| 73 | + - `@reown/appkit-cli`: simple scaffolding/utility CLI. |
| 74 | + - `@reown/appkit-codemod`: upgrade helper for dependency migrations. |
| 75 | + - `@reown/appkit-core` (in `core-legacy/`): legacy compatibility wrapper around controllers. |
| 76 | + |
| 77 | +### Allowed Dependencies and Import Boundaries |
| 78 | + |
| 79 | +- Favor a layered graph from foundations → controllers → ui/scaffold → appkit (facade) → adapters/apps. |
| 80 | +- Avoid cyclical imports. Do not import upward across layers (e.g., `ui` must not import from `appkit` or app code). |
| 81 | +- Only import via package entrypoints or declared subpath exports; avoid deep, relative cross-package imports. |
| 82 | + - Good: `import { X } from '@reown/appkit-controllers'` |
| 83 | + - Good: `import { WuiButton } from '@reown/appkit-ui/wui-button'` |
| 84 | + - Avoid: `import { X } from '@reown/appkit-controllers/dist/...` (internal paths are not stable) |
| 85 | +- Framework subpaths are explicitly exported (e.g., `./react`, `./vue`) when available; prefer those over bundling framework internals. |
| 86 | +- Keep optional or host-specific libraries as `peerDependencies` (e.g., `wagmi`, `viem`, `ethers`) and mark optional features as `optionalDependencies` to keep the core light. |
| 87 | + |
| 88 | +### Packaging and Build Conventions |
| 89 | + |
| 90 | +- All packages are ESM (`"type": "module"`). |
| 91 | +- Build outputs: |
| 92 | + - JS: `dist/esm/...` |
| 93 | + - Types: `dist/types/...` |
| 94 | + - `package.json` uses `exports` map and (where relevant) `typesVersions` for editor compatibility. |
| 95 | +- Use `"sideEffects": false` when the package is tree-shakeable (most are). Ensure top-level side effects are avoided. |
| 96 | +- Scripts: |
| 97 | + - `build:clean`: remove `dist` |
| 98 | + - `build`: `tsc --build` (some use `tsconfig.build.json`) |
| 99 | + - `watch`: `tsc --watch` |
| 100 | + - `typecheck`: `tsc --noEmit` |
| 101 | + - `lint`: ESLint across TS/JS files |
| 102 | + - `test`: Vitest (most with coverage) |
| 103 | +- Orchestration: |
| 104 | + - Use `turbo run build --filter={./packages/**/*}` for workspace builds. |
| 105 | + - `typecheck` and `lint` are cached by turbo; `test` is typically not cached. |
| 106 | + |
| 107 | +### UI Patterns |
| 108 | + |
| 109 | +- Base UI uses Lit Web Components, exported as `wui-*` elements from `@reown/appkit-ui`. |
| 110 | +- Higher-level UI flows and composition live in `@reown/appkit-scaffold-ui` and focus on orchestration (modal, router container, lists, pay/onramp flows). |
| 111 | +- Do not embed business logic into `@reown/appkit-ui`. Use `controllers`/`utils` for non-visual logic and data. |
| 112 | +- If providing React wrappers for Web Components, expose them via explicit subpath exports (e.g., `./react`) and keep them optional to avoid forcing React in core packages. |
| 113 | + |
| 114 | +### State, Data, and External SDKs |
| 115 | + |
| 116 | +- State management is uniform with `valtio`. Controllers own reactive state; UI subscribes. |
| 117 | +- EVM stack uses `viem` and `wagmi` (in adapters). Solana uses `@solana/web3.js` and wallet-standard libs. Bitcoin uses `bitcoinjs-lib`, `sats-connect`. |
| 118 | +- WalletConnect v2 is integrated via `@walletconnect/universal-provider`. Keep provider interactions isolated in `controllers`/`utils`/adapters. |
| 119 | + |
| 120 | +### Testing Conventions |
| 121 | + |
| 122 | +- `vitest` with `jsdom` by default for DOM-related packages; Node for pure utility packages as needed. |
| 123 | +- Place tests under `tests/` per package. |
| 124 | +- `@reown/appkit-testing` includes shared testing utilities and e2e dependencies (e.g., Playwright) but is not a runtime dependency. |
| 125 | + |
| 126 | +### Versioning and Release |
| 127 | + |
| 128 | +- Managed with `changesets`. Some overrides/patches exist under `patches/`. |
| 129 | +- Internal packages use `workspace:*` ranges to synchronize versions. |
| 130 | +- Keep public API changes aggregated through `@reown/appkit` where possible to minimize breaking surface area. |
| 131 | + |
| 132 | +### Adding or Modifying Packages (Checklist) |
| 133 | + |
| 134 | +1. Create a new package under `packages/<name>` with: |
| 135 | + - `package.json` using ESM, `exports` map, `files: ["dist", "README.md"]`, and `sideEffects: false` if safe. |
| 136 | + - `tsconfig.json` and optionally `tsconfig.build.json` with incremental builds. |
| 137 | + - `vitest.config.ts` if tests are present. |
| 138 | +2. Define clear dependencies: |
| 139 | + - Internal deps via `workspace:*`. |
| 140 | + - External host libs as `peerDependencies` (and mark optional when applicable). |
| 141 | + - Optional providers/wallets as `optionalDependencies`. |
| 142 | +3. Expose subpaths deliberately (e.g., `./react`, `./vue`, `./utils`) only when stable and necessary. |
| 143 | +4. Keep layering intact: do not import up the stack; avoid cross-layer leakage. |
| 144 | +5. Add targeted unit tests for new behavior and update examples if developer UX changes. |
| 145 | +6. Run `pnpm build`, `pnpm run typecheck`, `pnpm run lint`, and `pnpm test` locally. |
| 146 | + |
| 147 | +### Adapter Authoring Guidelines |
| 148 | + |
| 149 | +- Mirror existing adapters for structure and scripts. |
| 150 | +- Depend on `@reown/appkit`, `@reown/appkit-controllers`, `@reown/appkit-utils`, `@reown/appkit-common`, and where needed `@reown/appkit-ui`. |
| 151 | +- Treat ecosystem SDKs as `peerDependencies` (e.g., `wagmi`, `viem`, `ethers`) to defer version control to the host app; use `optionalDependencies` for optional wallet SDKs (e.g., Coinbase, Safe). |
| 152 | +- Keep business logic inside controllers/utilities; adapters should translate between host SDK APIs and AppKit abstractions. |
| 153 | + |
| 154 | +### Import and API Design Best Practices (TypeScript) |
| 155 | + |
| 156 | +- Public APIs must be explicitly exported via the `exports` map and stable subpaths. Avoid deep internal imports. |
| 157 | +- Use `export type` for types-only exports to aid tree-shaking and ergonomics. |
| 158 | +- Prefer narrow, well-named interfaces and parameter objects over positional args. |
| 159 | +- Do not leak implementation-specific types from third-party SDKs across package boundaries; wrap or map to internal domain types. |
| 160 | +- Add `strict` TS configs and avoid `any`. Use discriminated unions for variant states. |
| 161 | +- Use early returns and guard clauses; avoid deep nesting. |
| 162 | +- Validate inputs near boundaries (e.g., adapter entrypoints). Use `zod` when schemas are involved. |
| 163 | +- Errors: throw typed errors or return structured `Result`-like objects where it improves developer ergonomics; never swallow exceptions. |
| 164 | + |
| 165 | +### Performance and Security Notes |
| 166 | + |
| 167 | +- Keep packages tree-shakeable; avoid top-level side effects and large transitive deps in core layers. |
| 168 | +- Use `peerDependencies` to avoid bundling multiple versions of large SDKs. |
| 169 | +- Be mindful of SSR: avoid direct `window` access in shared code; gate browser-only code. |
| 170 | +- Sanitize and validate user inputs in UI flows and adapters. Do not interpolate untrusted values into DOM without escaping. |
| 171 | +- Avoid logging secrets or PII. Use structured logs (debug-only in dev paths). |
| 172 | + |
| 173 | +### Practical Examples |
| 174 | + |
| 175 | +Imports (prefer subpaths when they exist): |
| 176 | + |
| 177 | +```ts |
| 178 | +import { createAppKit } from '@reown/appkit' |
| 179 | +import { createWagmiAdapter } from '@reown/appkit-adapter-wagmi' |
| 180 | +import { AccountController } from '@reown/appkit-controllers' |
| 181 | +import { W3mModal } from '@reown/appkit-scaffold-ui/w3m-modal' |
| 182 | +import { WuiButton } from '@reown/appkit-ui/wui-button' |
| 183 | +``` |
| 184 | + |
| 185 | +React/Vue subpaths (when provided): |
| 186 | + |
| 187 | +```ts |
| 188 | +import { ControllersProvider } from '@reown/appkit-controllers/react' |
| 189 | +import { AppKitProvider } from '@reown/appkit/react' |
| 190 | +``` |
| 191 | + |
| 192 | +### What Cursor Should Assume When Editing |
| 193 | + |
| 194 | +- Respect the layering and import boundaries above. If a change requires crossing a boundary, propose an abstraction in a lower layer instead. |
| 195 | +- When adding a new exported module: |
| 196 | + - Update the package `exports` map and type paths. |
| 197 | + - Add unit tests and minimal examples. |
| 198 | + - Keep `sideEffects: false` valid by avoiding module-level effects. |
| 199 | +- For UI changes: |
| 200 | + - Add new components under `@reown/appkit-ui` with `wui-` prefix, minimal logic. |
| 201 | + - Compose flows under `@reown/appkit-scaffold-ui`. |
| 202 | + - Keep controllers/data-fetching outside UI layers. |
| 203 | +- For adapters: |
| 204 | + - Prefer compile-time type safety over runtime checks; encode invariants in types. |
| 205 | + - Ensure version constraints are compatible with examples and CDN builds. |
| 206 | + |
| 207 | +### Quick Map of Key Packages |
| 208 | + |
| 209 | +- `@reown/appkit` — SDK facade and top-level exports |
| 210 | +- `@reown/appkit-common` — shared types/utils |
| 211 | +- `@reown/appkit-wallet` — wallet models/utilities |
| 212 | +- `@reown/appkit-controllers` — stateful domain logic (valtio state) |
| 213 | +- `@reown/appkit-utils` — chain/wallet helpers |
| 214 | +- `@reown/appkit-ui` — base UI (Lit Web Components, `wui-*`) |
| 215 | +- `@reown/appkit-scaffold-ui` — modal/router/pay/onramp flows |
| 216 | +- `@reown/appkit-pay` — pay feature surface (UI + controllers) |
| 217 | +- `@reown/appkit-siwe` / `@reown/appkit-siwx` — auth flows and utilities |
| 218 | +- `@reown/appkit-universal-connector` — WalletConnect bridge |
| 219 | +- `@reown/appkit-adapter-*` — ecosystem adapters (Wagmi/Ethers/Ethers5/Solana/Bitcoin) |
| 220 | +- `@reown/appkit-polyfills` — browser polyfills |
| 221 | +- `@reown/appkit-cdn` — CDN bundles |
| 222 | +- `@reown/appkit-testing` — test harnesses |
| 223 | +- `@reown/appkit-cli` / `@reown/appkit-codemod` — dev tooling |
| 224 | +- `@reown/appkit-core` — legacy wrapper around controllers |
| 225 | + |
| 226 | +--- |
| 227 | + |
| 228 | +If a change seems to violate these rules, prefer refactoring toward these boundaries or proposing a clear abstraction that preserves the layering. |
0 commit comments