> For the complete documentation index, see [llms.txt](https://gotts.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gotts.gitbook.io/docs/monorepo-infrastructure/monorepo/02-architecture.md).

# Architecture

> **Part of**: [Monorepo Infrastructure PRD](/docs/monorepo-infrastructure/monorepo.md) | **Last Updated**: 2026-02-19

***

## Directory Structure

```
gotts-monorepo/
├── .github/
│   ├── workflows/
│   │   ├── ci.yml                    # Main CI pipeline
│   │   ├── release.yml               # Changesets release workflow
│   │   └── renovate.yml              # Renovate auto-merge (optional)
│   ├── CODEOWNERS
│   └── renovate.json5                # Renovate configuration
├── .husky/
│   ├── pre-commit                    # lint-staged
│   └── commit-msg                    # commitlint
├── .vscode/
│   ├── extensions.json               # Recommended extensions
│   └── settings.json                 # Workspace settings
├── apps/
│   └── web/                          # Next.js debug UI
│       ├── src/
│       │   ├── app/                  # App Router pages
│       │   └── components/           # App-specific components
│       ├── public/
│       ├── next.config.ts
│       ├── tailwind.css              # Tailwind v4 entry (CSS-first)
│       ├── tsconfig.json
│       └── package.json
├── packages/
│   ├── core/                         # @gotts.ai/core — Config, errors, constants (published)
│   │   ├── src/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── package.json
│   ├── chain/                        # @gotts.ai/chain — ETH math, address utils, RPC (internal)
│   │   ├── src/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   └── package.json
│   ├── crypto/                       # @gotts.ai/crypto — P-256 key gen, signing, DER (internal)
│   │   ├── src/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   └── package.json
│   ├── policy/                       # @gotts.ai/policy — Privy policy builders (internal)
│   │   ├── src/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   └── package.json
│   ├── wallet/                       # @gotts.ai/wallet — Wallet abstraction (published)
│   │   ├── src/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── package.json
│   ├── test-utils/                   # @gotts.ai/test-utils — Shared MSW handlers (internal dev)
│   │   ├── src/
│   │   ├── tsconfig.json
│   │   └── package.json
│   ├── safe/                         # @gotts.ai/safe — Gotts Safe MCP server
│   │   ├── src/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── package.json
│   ├── vault/                        # @gotts.ai/vault — Vault SDK + contracts
│   │   ├── contracts/
│   │   │   └── src/                  # Solidity (Foundry)
│   │   ├── sdk/src/                  # TypeScript SDK
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   ├── foundry.toml
│   │   └── package.json
│   ├── agent-proxy/                  # @gotts.ai/agent-proxy — Time-delay proxy
│   │   ├── contracts/src/
│   │   ├── sdk/src/
│   │   ├── monitor/
│   │   ├── test/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   ├── foundry.toml
│   │   └── package.json
│   ├── devenv/                          # @gotts.ai/devenv — Local Uniswap testnet
│   │   ├── src/
│   │   ├── ui/                          # Devenv debug UI (:3001)
│   │   ├── tsconfig.json
│   │   └── package.json
│   ├── testnet/                         # @gotts.ai/testnet — Generic EVM test toolkit
│   │   ├── src/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── package.json
│   ├── create/                          # @gotts.ai/create — Install wizard CLI
│   │   ├── src/
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── package.json
│   ├── typescript-config/            # @gotts.ai/typescript-config (internal)
│   │   ├── base.json
│   │   ├── library.json
│   │   ├── nextjs.json
│   │   └── package.json
│   ├── eslint-config/                # @gotts.ai/eslint-config (internal)
│   │   ├── src/
│   │   │   ├── base.ts
│   │   │   ├── library.ts
│   │   │   ├── nextjs.ts
│   │   │   └── index.ts
│   │   ├── tsconfig.json
│   │   └── package.json
│   └── ui/                           # @gotts.ai/ui — Shared React components (internal)
│       ├── src/
│       │   ├── components/
│       │   └── index.ts
│       ├── tsconfig.json
│       └── package.json
├── prd/                              # Product Requirements Documents
├── research/                         # Market research
├── scripts/
├── .gitignore
├── .npmrc                            # pnpm config
├── .prettierrc                       # Prettier config
├── .prettierignore
├── commitlint.config.ts              # Commitlint config
├── eslint.config.ts                  # Root ESLint config
├── knip.config.ts                    # Knip unused dependency config
├── lint-staged.config.mjs            # lint-staged config
├── package.json                      # Root workspace config
├── pnpm-lock.yaml                    # pnpm lockfile
├── pnpm-workspace.yaml               # Workspace definitions
├── syncpack.config.ts                # Syncpack version consistency
├── tsconfig.json                     # Root TypeScript config
├── turbo.json                        # Turborepo pipeline config
└── vitest.config.ts                  # Root Vitest config (projects mode)
```

## Package Dependency Graph

```
@gotts.ai/core         (zero workspace deps — config, errors, constants)
       │
       ├──────────────────────────┐
       ▼                          ▼
@gotts.ai/chain        @gotts.ai/crypto
(zero workspace deps)  (zero workspace deps)
       │                          │
       ▼                          │
@gotts.ai/policy       ──────────┘
(depends on chain for address validation)
       │
       ▼
@gotts.ai/wallet       (depends on core, chain, crypto, policy)
       │
       ├─────────────────┬─────────────────┐
       ▼                 ▼                 ▼
@gotts.ai/safe   @gotts.ai/vault    @gotts.ai/portal

       @gotts.ai/testnet  (zero DeFi deps — generic EVM toolkit)
              │
              ▼
       @gotts.ai/devenv   (adds Uniswap deployment on top of testnet)
              │
              ├─────────────────────┐
              ▼                     ▼
       @gotts.ai/vault        @gotts.ai/safe
              │                     │
              ▼                     │
       @gotts.ai/agent-proxy        │
              │                     │
              └──────┬──────────────┘
                     ▼
                @gotts.ai/ui  (shared components + design tokens)
                     │
                     ▼
                 apps/web     (Next.js app)

@gotts.ai/test-utils   (dev dependency only — not in production graph)
```

**Dependency rules** (normative):

1. Config packages (`typescript-config`, `eslint-config`) have **zero** workspace dependencies
2. Primitive packages (`core`, `chain`, `crypto`, `policy`) have **zero** workspace dependencies from above their layer
3. `wallet` depends only on primitive packages (`core`, `chain`, `crypto`, `policy`)
4. `ui` depends only on config packages — never on `safe`, `vault`, or `agent-proxy`
5. `safe`, `vault`, `portal`, and `agent-proxy` may depend on `wallet` and on each other where documented in their respective PRDs
6. `test-utils` is a **dev-only** dependency — never imported in `src/` directories
7. `apps/web` may depend on any `packages/*` package
8. Circular dependencies are **prohibited** — the dependency graph must be a DAG

## Workspace Configuration

### `pnpm-workspace.yaml` (normative)

```yaml
packages:
  - "packages/*"
  - "apps/*"
```

### Root `package.json` (normative)

```jsonc
{
  "name": "gotts-monorepo",
  "private": true,
  "packageManager": "pnpm@9.15.9",
  "engines": {
    "node": ">=20.0.0",
  },
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "test": "turbo run test",
    "test:integration": "turbo run test:integration",
    "lint": "turbo run lint",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "check-types": "turbo run check-types",
    "clean": "turbo run clean && rm -rf node_modules .turbo",
    "clean:turbo": "rm -rf .turbo **/node_modules/.cache/turbo",
    "changeset": "changeset",
    "version-packages": "changeset version",
    "release": "turbo run build --filter='./packages/*' && changeset publish",
    "knip": "knip",
    "syncpack:check": "syncpack lint",
    "syncpack:fix": "syncpack fix-mismatches",
    "prepare": "husky",
  },
}
```

> **`packageManager` field**: Enables Corepack. Running `corepack enable` ensures the correct pnpm version is used automatically — no global install required.

### `.npmrc` (normative)

```ini
# Hoist only peer dependencies needed by tools that don't support pnpm's strict layout
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*

# Strict mode: fail on missing peer dependencies
strict-peer-dependencies=true

# Use the fastest resolution strategy
resolution-mode=highest
```

## Turborepo Configuration

### `turbo.json` (normative)

```jsonc
{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env.*local"],
  "ui": "tui",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json", "tsdown.config.ts", "package.json"],
      "outputs": ["dist/**"],
    },
    "check-types": {
      "dependsOn": ["^check-types"],
      "inputs": ["src/**", "test/**", "tsconfig.json"],
      "outputs": [],
    },
    "dev": {
      "cache": false,
      "persistent": true,
    },
    "lint": {
      "dependsOn": ["^build"],
      "inputs": [
        "src/**",
        "test/**",
        "eslint.config.ts",
        "../../eslint.config.ts",
      ],
      "outputs": [],
    },
    "test": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "test/**", "vitest.config.ts"],
      "outputs": [],
    },
    "test:integration": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "test/**"],
      "outputs": [],
      "cache": false,
    },
    "clean": {
      "cache": false,
    },
  },
}
```

**Key design decisions:**

1. **`dependsOn: ["^build"]`** — Tasks wait for upstream workspace dependencies to build first. This is critical for published packages that consume other published packages.
2. **`inputs` arrays** — Only the files that affect task output are listed. Turborepo uses these for cache key computation. Adding irrelevant files (like `README.md`) would cause unnecessary cache misses.
3. **`dev` is not cached** — Dev servers are long-running processes (`persistent: true`) that should never be cached.
4. **`test:integration` is not cached** — Integration tests hit external services (RPC endpoints, subgraphs) and must always run fresh.
5. **`ui: "tui"`** — Enables Turborepo's terminal UI for interactive task monitoring during `turbo run dev`.

### Filtering

Turborepo's filter syntax for targeting specific packages:

```bash
# Build only the vault package and its dependencies
pnpm turbo run build --filter=@gotts.ai/vault...

# Run tests in packages that changed since main
pnpm turbo run test --filter='...[main]'

# Dev mode for the web app only
pnpm turbo run dev --filter=web

# Build everything except apps
pnpm turbo run build --filter='./packages/*'
```

## Internal vs Published Packages

The monorepo uses two package patterns:

### Published Packages

Packages distributed to npm under the `@gotts.ai` scope. These require a build step.

* **Build tool**: tsdown (see [04-build-test.md](/docs/monorepo-infrastructure/monorepo/04-build-test.md))
* **Output**: `dist/` directory with ESM + CJS
* **Examples**: `@gotts.ai/safe`, `@gotts.ai/vault`, `@gotts.ai/agent-proxy`

### Internal Packages

Packages consumed only within the monorepo. These use TypeScript source directly — **no build step**.

* **Build tool**: None
* **Output**: None (`dist/` does not exist)
* **Resolution**: Via `exports` field in `package.json` pointing to TypeScript source
* **Examples**: `@gotts.ai/typescript-config`, `@gotts.ai/eslint-config`, `@gotts.ai/ui`

See [04-build-test.md](/docs/monorepo-infrastructure/monorepo/04-build-test.md) for the internal packages pattern implementation.
