appkit

GitHub

The full stack toolkit to build onchain app UX

RAW Rules

AGENTS.md

# AGENTS.md

Reown AppKit โ€” a multi-chain onchain SDK providing wallet connection, authentication, swaps, on-ramp, and transaction UX for 700+ wallets across EVM, Solana, Bitcoin, Polkadot, and TON. Available for React, Next.js, Vue, Nuxt, Svelte, vanilla JS, React Native, Flutter, and native mobile.

## Quick Reference

- **Package manager**: pnpm workspaces (`pnpm-workspace.yaml`)
- **Build orchestration**: Turborepo (`turbo.json`)
- **State management**: valtio (always import from `valtio/vanilla`)
- **UI framework**: LitElement Web Components
- **Testing**: Vitest (unit), Playwright (E2E in `apps/laboratory`)
- **TypeScript**: Strict mode, ESM only, `experimentalDecorators` enabled

## Commands

```bash
pnpm install              # Install dependencies
pnpm build                # Build all packages (run before apps or tests)
pnpm test                 # Unit tests (Vitest)
pnpm typecheck            # Type checking (depends on build)
pnpm lint                 # ESLint
pnpm run prettier:format  # Format code (run before committing)
pnpm changeset            # Create a changeset for versioning
pnpm laboratory           # Run E2E testing app
pnpm demo:dev             # Run demo app
pnpm gallery              # Run Storybook component gallery
```

## Repository Layout

```
packages/
  appkit/              โ†’ @reown/appkit             Main SDK facade
  controllers/         โ†’ @reown/appkit-controllers  Valtio state management
  ui/                  โ†’ @reown/appkit-ui           Atomic wui-* Web Components
  scaffold-ui/         โ†’ @reown/appkit-scaffold-ui  High-level w3m-* UI flows
  common/              โ†’ @reown/appkit-common       Shared types and utilities
  appkit-utils/        โ†’ @reown/appkit-utils        Chain-specific helpers
  wallet/              โ†’ @reown/appkit-wallet       Wallet models
  pay/                 โ†’ @reown/appkit-pay          Payment flows
  siwe/                โ†’ @reown/appkit-siwe         Sign-In With Ethereum
  siwx/                โ†’ @reown/appkit-siwx         Cross-chain authentication
  adapters/
    wagmi/             โ†’ EVM via Wagmi/Viem
    ethers/            โ†’ EVM via ethers v6
    ethers5/           โ†’ EVM via ethers v5
    solana/            โ†’ Solana
    bitcoin/           โ†’ Bitcoin
    polkadot/          โ†’ Polkadot
    ton/               โ†’ TON
apps/
  laboratory/          โ†’ E2E testing (Next.js + Playwright)
  demo/                โ†’ Marketing demo
  gallery/             โ†’ Storybook component gallery
examples/              โ†’ Integration examples (next-*, react-*, vue-*, svelte-*, html-*)
```

## Architecture Rules

### Layer Order (dependencies flow downward only)

```
apps & examples
  โ†“
adapters (wagmi, solana, bitcoin, ethers, ...)
  โ†“
@reown/appkit (SDK facade)
  โ†“
scaffold-ui (w3m-*) ยท pay
  โ†“
ui (wui-*) ยท controllers ยท appkit-utils
  โ†“
common ยท wallet ยท polyfills
```

### Import Boundaries

- **ui** (`wui-*`): Cannot import from controllers, scaffold-ui, appkit, or adapters
- **controllers**: Cannot import from ui, scaffold-ui, appkit, or adapters
- **scaffold-ui** (`w3m-*`): Uses relative imports within the package, not `@reown/` paths
- **adapters**: Import from `@reown/appkit` and foundations, never from controllers or ui directly
- **Cross-package**: Always use package entrypoints or declared subpath exports, never deep internal paths

### Chain Namespaces

| Namespace  | Chain    | Adapter                |
| ---------- | -------- | ---------------------- |
| `eip155`   | EVM      | wagmi, ethers, ethers5 |
| `solana`   | Solana   | solana                 |
| `bip122`   | Bitcoin  | bitcoin                |
| `polkadot` | Polkadot | polkadot               |
| `ton`      | TON      | ton                    |

## Where to Put Things

| What you're building     | Where it goes                                                                                           |
| ------------------------ | ------------------------------------------------------------------------------------------------------- |
| New state/business logic | `packages/controllers/src/controllers/` โ€” follow [controller pattern](.agents/context/controllers.md)   |
| New atomic UI element    | `packages/ui/src/composites/wui-<name>/` โ€” follow [UI guide](.agents/context/ui-components.md)          |
| New modal view/screen    | `packages/scaffold-ui/src/views/w3m-<name>-view/` โ€” register in RouterController + w3m-router           |
| Reusable UI section      | `packages/scaffold-ui/src/partials/w3m-<name>/`                                                         |
| New blockchain adapter   | `packages/adapters/<name>/` โ€” extend AdapterBlueprint, see [adapter guide](.agents/context/adapters.md) |
| Shared types or utils    | `packages/common/src/`                                                                                  |
| Chain-specific helpers   | `packages/appkit-utils/src/`                                                                            |
| Public SDK API           | `packages/appkit/exports/` โ€” treat changes as potentially breaking                                      |
| Unit tests               | Co-located `tests/` directory in the relevant package                                                   |
| E2E tests                | `apps/laboratory/tests/` using Page Object Model                                                        |
| Integration example      | `examples/<framework>-<adapter>/`                                                                       |

## Code Patterns

### Controllers (valtio state)

```typescript
// packages/controllers/src/controllers/MyController.ts
import { proxy, subscribe as sub } from 'valtio/vanilla'
import { subscribeKey as subKey } from 'valtio/vanilla/utils'

// -- Types ----
export interface MyControllerState {
  value: string
}

// -- State ----
const state = proxy<MyControllerState>({ value: '' })

// -- Controller ----
const controller = {
  state,
  subscribe(callback: (s: MyControllerState) => void) {
    return sub(state, () => callback(state))
  },
  subscribeKey<K extends keyof MyControllerState>(key: K, cb: (v: MyControllerState[K]) => void) {
    return subKey(state, key, cb)
  },
  setValue(v: string) {
    state.value = v
  }
}
export const MyController = withErrorBoundary(controller)
```

Section comments (`// -- Types ----`, `// -- State ----`, `// -- Controller ----`) are enforced by DangerJS.

### UI Atoms (wui-\*)

```typescript
// packages/ui/src/composites/wui-my-thing/index.ts
@customElement('wui-my-thing')
export class WuiMyThing extends LitElement {
  public static override styles = [resetStyles, styles] // resetStyles required
  // -- State & Properties ----
  @property() public variant = 'default' // @state() NOT allowed
  // -- Render ----
  public override render() {
    return html`<slot></slot>`
  }
}
```

### Scaffold Views (w3m-\*)

```typescript
// packages/scaffold-ui/src/views/w3m-my-view/index.ts
@customElement('w3m-my-view')
export class W3mMyView extends LitElement {
  private unsubscribe: (() => void)[] = [] // Cleanup required
  @state() private value = SomeController.state.value

  constructor() {
    super()
    this.unsubscribe.push(
      SomeController.subscribeKey('value', v => {
        this.value = v
      })
    )
  }

  public override disconnectedCallback() {
    this.unsubscribe.forEach(u => u())
  }
}
```

### Adapters

Extend `AdapterBlueprint` from `packages/controllers/src/controllers/AdapterController/ChainAdapterBlueprint.ts`. Implement: `connect()`, `disconnect()`, `switchNetwork()`, `signMessage()`, `sendTransaction()`, `getBalance()`. Host SDKs go in `peerDependencies`.

## PR Requirements

1. Run `pnpm build && pnpm run prettier:format` before submitting
2. Use conventional commit format for PR titles (`feat:`, `fix:`, `chore:`, `refactor:`, `test:`, `docs:`)
3. Bug fixes and new features require tests
4. Create a changeset: `pnpm changeset`
5. DangerJS validates import boundaries, naming conventions, section comments, and dependency rules

## Versioning

All `@reown/appkit-*` packages are versioned together as a fixed group via Changesets. Release channels: `latest`, `alpha`, `beta`, `canary`. `@examples/*` and `@apps/*` are excluded from publishing.

## Detailed Context

For in-depth guidance on specific topics:

- [Architecture & Initialization Flow](.agents/context/architecture.md) โ€” layer diagram, import boundaries, init sequence, network request policy
- [Controllers Reference](.agents/context/controllers.md) โ€” valtio patterns, all controllers, state shapes
- [UI Components Guide](.agents/context/ui-components.md) โ€” wui-_ and w3m-_ patterns, DangerJS rules, adding views
- [Blockchain Adapters Guide](.agents/context/adapters.md) โ€” AdapterBlueprint, creating new adapters
- [Testing Guide](.agents/context/testing.md) โ€” Vitest, Playwright, test locations, writing new tests
- [Package Reference](.agents/context/packages.md) โ€” all packages, build outputs, adding packages
- [Contributing & PR Guide](.agents/context/contributing.md) โ€” PR checks, changesets, release process