> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryzuko.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Backend Setup

> Configure and run the NestJS API server locally.

The backend is a **NestJS** server that lives in `apps/backend`. It handles the REST API, authentication (Better Auth + Google OAuth), database access via Prisma, and agent routing.

***

## Prerequisites

* Repo cloned and dependencies installed (`bun install`)
* PostgreSQL running locally

***

## Environment variables

Copy the example file:

```bash theme={null}
cp apps/backend/.env.example apps/backend/.env
```

### Database

```env theme={null}
# PostgreSQL connection string (can be omitted if set in root .env)
DATABASE_URL=postgres://postgres:password@localhost:5432/zuko_dev
```

### Authentication

```env theme={null}
# Random secret for Better Auth session signing (min 32 chars)
BETTER_AUTH_SECRET=your-secret-here

# Google OAuth — create credentials at https://console.cloud.google.com/apis/credentials
# Authorized redirect URI: http://localhost:3001/auth/callback/google
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret

# Enable email/password login in addition to Google OAuth
BETTER_AUTH_INCLUDE_EMAILS_AUTH=true
```

### URLs & CORS

```env theme={null}
BACKEND_URL=http://localhost:3001
FRONTEND_URL=http://localhost:3000

# List of allowed CORS origins (comma-separated)
TRUSTED_ORIGINS=http://localhost:3000,http://localhost:3001
```

### AI & agents

```env theme={null}
OPENAI_API_KEY=sk-...

# Model for the in-process AI agent. Format: "<provider>/<model>"
# Supported: openai/gpt-4.1, openai/gpt-4o, anthropic/claude-sonnet-4-5, etc.
AGENT_MODEL=openai/gpt-4.1

# Shared secret that authenticates /api/agents/* endpoint calls
AGENT_TOKEN=your-agent-token
```

### Tracing (optional)

```env theme={null}
LANGSMITH_TRACING=false
LANGSMITH_API_KEY=
LANGSMITH_PROJECT=zuko
```

### Sandbox (Sprites)

```env theme={null}
# false = local Node.js execution (development default)
# true  = remote Sprites sandboxes (production)
SPRITES_ENABLED=false
SPRITES_TOKEN=
SPRITES_API_BASE_URL=https://sprites.fly.dev
AGENT_BRANCH=main
WORKING_DIR=/home/sprite/zuko
```

See [Sandbox Setup](/setup/sandbox) for full configuration details.

***

## Database setup

### Create the database

```bash theme={null}
createdb zuko_dev
```

### Generate the Prisma client

```bash theme={null}
bun nx run @zuko/models:prisma:generate
```

### Run migrations

```bash theme={null}
bun nx run @zuko/models:prisma:migrate -- --name init
```

### Seed test data

Creates a test user (`e2e@example.com` / `TestPassword123!`) and sample CRM data:

```bash theme={null}
bun nx run @zuko/models:seed
```

### Browse the database

```bash theme={null}
bun nx run @zuko/models:prisma:studio
# Opens Prisma Studio at http://localhost:5555
```

***

## Google OAuth

1. Go to [Google Cloud Console → Credentials](https://console.cloud.google.com/apis/credentials)
2. Click **Create Credentials → OAuth client ID**
3. Choose **Web application** and fill in:
   * **Name**: `Zuko (local)`
   * **Authorized JavaScript origins**: `http://localhost:3000`
   * **Authorized redirect URIs**: `http://localhost:3001/auth/callback/google`
4. Copy the **Client ID** and **Client Secret**
5. Paste them into `apps/backend/.env` as `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`

***

## Apollo.io OAuth

Required to enable the Apollo.io integration (contact enrichment, people/company search).

1. Go to [Apollo.io Developer Portal](https://developer.apollo.io) and open **OAuth Registration**
2. Create a new OAuth app and fill in:
   * **App name**: `Zuko (local)` (or any name)
   * **Redirect URL**: `http://localhost:3000/api/integrations/apollo/callback`
   * **Scopes**: select all of the following (must match `APOLLO_SCOPES` in `apollo-integration.service.ts`):
     * `read_user_profile`
     * `contacts_search`
     * `organizations_search`
     * `organizations_enrich`
     * `organizations_bulk_enrich`
     * `credit_usage_stats_read`
     * `emailer_campaigns_search`
     * `emailer_campaigns_create`
     * `emailer_campaigns_update`
     * `emailer_campaigns_add_contact_ids`
     * `emailer_campaigns_approve`
3. Copy the **Client ID** and **Client Secret**
4. Add to `apps/backend/.env`:

```env theme={null}
APOLLO_CLIENT_ID=your-apollo-client-id
APOLLO_CLIENT_SECRET=your-apollo-client-secret
APOLLO_REDIRECT_URI=http://localhost:3000/api/integrations/apollo/callback
APOLLO_AUTHORIZATION_ENDPOINT=https://mcp.apollo.io/mcp/oauth_metadata/redirect_to_authorize
APOLLO_TOKEN_ENDPOINT=https://mcp.apollo.io/api/v1/oauth/token
APOLLO_REVOCATION_ENDPOINT=https://mcp.apollo.io/api/v1/oauth/revoke
```

Once configured, users can connect their Apollo account from **Settings → Connections**.

***

## Start the development server

```bash theme={null}
bun nx run @zuko/backend:serve
```

The API is available at **[http://localhost:3001](http://localhost:3001)**.

| Endpoint                     | Description        |
| ---------------------------- | ------------------ |
| `http://localhost:3001`      | REST API           |
| `http://localhost:3001/auth` | Better Auth routes |

***

## Useful commands

```bash theme={null}
bun nx run @zuko/backend:serve         # Start backend only
bun nx run @zuko/backend:build         # Production build
bun nx run @zuko/backend:test          # Unit tests
bun nx run @zuko/backend:lint          # Lint

# Database
bun nx run @zuko/models:prisma:generate                   # Regenerate Prisma client
bun nx run @zuko/models:prisma:migrate -- --name <name>   # New migration
bun nx run @zuko/models:prisma:studio                     # DB browser (port 5555)
bun nx run @zuko/models:prisma:reset                      # Reset DB (destructive!)
bun nx run @zuko/models:seed                              # Seed test data
```

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="PostgreSQL connection error">
    Ensure PostgreSQL is running:

    ```bash theme={null}
    # macOS
    brew services start postgresql@16

    # Linux
    sudo systemctl start postgresql
    ```

    Test the connection:

    ```bash theme={null}
    psql -U postgres -d zuko_dev
    ```

    Check `DATABASE_URL` format: `postgres://user:password@host:port/dbname`
  </Accordion>

  <Accordion title="Prisma client errors">
    Clear the cached client and regenerate:

    ```bash theme={null}
    rm -rf node_modules/.prisma/
    bun nx run @zuko/models:prisma:generate
    ```
  </Accordion>

  <Accordion title="Auth / CORS errors">
    * Ensure `TRUSTED_ORIGINS` includes both `http://localhost:3000` and
      `http://localhost:3001` - Clear browser cookies and retry - Confirm the Google
      OAuth redirect URI is exactly `http://localhost:3001/auth/callback/google`
  </Accordion>

  <Accordion title="Port already in use">
    ```bash theme={null}
    lsof -ti:3001 | xargs kill -9
    ```
  </Accordion>
</AccordionGroup>
