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

# Getting started

> Step-by-step guide to run Payoes on your machine from a fresh clone.

Follow these steps in order. Each step builds on the previous one.

## 1. Clone and install

```bash theme={null}
git clone <your-payoes-repo-url>
cd payoes
npm install
```

This installs dependencies for the monorepo (`apps/web`, `packages/*`).

## 2. Start PostgreSQL and MinIO

From the repository root:

```bash theme={null}
npm run docker:up
```

Wait until both containers are healthy:

```bash theme={null}
docker compose ps
```

You should see `payoes-postgres` and `payoes-minio` running. The `minio-init` job creates the `payoes-uploads` bucket automatically.

<Tip>
  To stop services later: `npm run docker:down`
</Tip>

## 3. Create your environment file

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

Open `apps/web/.env.local` and set the **minimum required** values below.

### Minimum config for first run

```bash theme={null}
# Generate a random secret:
# openssl rand -base64 32
AUTH_SECRET=your-generated-secret-here
AUTH_URL=http://localhost:3000

# Google OAuth (or register with email/password at /register)
AUTH_GOOGLE_ID=your-client-id.apps.googleusercontent.com
AUTH_GOOGLE_SECRET=your-client-secret

# Database (matches docker-compose.yml)
DATABASE_URL=postgresql://payoes:payoes@localhost:5432/payoes

# MinIO (matches docker-compose.yml)
S3_ENDPOINT=http://localhost:9000
S3_PUBLIC_URL=http://localhost:9000/payoes-uploads
S3_ACCESS_KEY=payoes
S3_SECRET_KEY=payoessecret
S3_BUCKET=payoes-uploads
S3_REGION=us-east-1

# Docs link in dashboard
NEXT_PUBLIC_DOCS_URL=http://localhost:3001

# Soroban escrow (required before creating payments)
# Run: ./scripts/soroban-deploy-contract.sh --operator-account payoes-operator --source-account payoes-operator
# STELLAR_TESTNET_OPERATOR_SECRET=S...
# SOROBAN_TESTNET_RPC_URL=https://soroban-testnet.stellar.org
# SOROBAN_TESTNET_CONTRACT_ID=C...
```

Leave SMTP and Persona variables empty for now. You can add them later.

<Warning>
  Payments and checkout require Soroban escrow configuration. See [Soroban escrow setup](/local-setup/soroban-escrow-setup) before creating payments.
</Warning>

## 4. Run database migrations

```bash theme={null}
npm run db:migrate
```

You should see `migrations applied successfully`. This creates all tables (organizations, payments, team invites, verification, and more).

<Warning>
  Run migrations after every `git pull` that adds new files under `apps/web/drizzle/`.
</Warning>

## 5. Start the web app

```bash theme={null}
npm run dev
```

Open [http://localhost:3000](http://localhost:3000).

## 6. Sign in and complete onboarding

1. Go to [http://localhost:3000/register](http://localhost:3000/register) and create an account, or sign in with Google at [http://localhost:3000/login](http://localhost:3000/login)
2. Verify your email if you registered with email/password
3. Complete onboarding:
   * Create an organization (name + logo)
   * Connect a **testnet** settlement wallet (use [Stellar Laboratory](https://laboratory.stellar.org/#account-creator?network=test) to generate and fund one)

You should land on the dashboard with sandbox mode enabled.

## 7. Deploy the Soroban escrow contract

Payments require a deployed contract. From the repository root:

```bash theme={null}
stellar keys generate --global payoes-operator
curl "https://friendbot.stellar.org?addr=$(stellar keys address payoes-operator)"

./scripts/soroban-deploy-contract.sh \
  --operator-account payoes-operator \
  --source-account payoes-operator
```

Copy `CONTRACT_ID` and `OPERATOR_SECRET` from the output into `apps/web/.env.local`, then restart `npm run dev`.

See [Soroban escrow setup](/local-setup/soroban-escrow-setup) for separate funder accounts, other networks, and troubleshooting.

## 8. Verify the setup works

Run a quick smoke test:

<Steps>
  <Step title="Create a sandbox API key">
    Dashboard → **Developers → API Keys** → create a key with the `pk_test_` prefix.
  </Step>

  <Step title="Create a payment">
    Dashboard → **Payments** → create a payment, or use the API:

    ```bash theme={null}
    curl -X POST http://localhost:3000/api/v1/payments \
      -H "Authorization: Bearer pk_test_YOUR_KEY" \
      -H "Content-Type: application/json" \
      -d '{"amount": "1", "asset": "XLM", "description": "Local test"}'
    ```
  </Step>

  <Step title="Open checkout">
    Open the `checkout_url` from the response in a browser and complete payment with a testnet wallet.
  </Step>
</Steps>

If payment status becomes `completed`, your local stack is working.

## 9. Preview the docs site

In a second terminal, from the repository root:

```bash theme={null}
npm run docs:dev
```

Open [http://localhost:3001](http://localhost:3001) to preview this documentation site.

## Common issues

<AccordionGroup>
  <Accordion title="Database connection refused">
    * Ensure Docker is running: `docker compose ps`
    * Restart services: `npm run docker:down && npm run docker:up`
    * Confirm `DATABASE_URL` matches `docker-compose.yml` credentials
  </Accordion>

  <Accordion title="Migration errors">
    * Make sure PostgreSQL is up before running `npm run db:migrate`
    * If you changed schema locally, run `npm run db:generate` only when intentionally creating new migrations
  </Accordion>

  <Accordion title="Cannot sign in">
    * Check `AUTH_SECRET` is set (not empty)
    * For Google sign-in, confirm `AUTH_GOOGLE_ID` and `AUTH_GOOGLE_SECRET` are set
    * For email/password, register at `/register` and verify your email first
    * Restart the dev server after changing `.env.local`
  </Accordion>

  <Accordion title="Logo upload fails">
    * Confirm MinIO is running on port 9000
    * Check `S3_*` variables match `docker-compose.yml`
    * Open [http://localhost:9001](http://localhost:9001) and verify bucket `payoes-uploads` exists
  </Accordion>

  <Accordion title="Payment or checkout setup errors">
    * Run the Soroban deploy script: [Soroban escrow setup](/local-setup/soroban-escrow-setup)
    * Confirm `STELLAR_TESTNET_OPERATOR_SECRET` and `SOROBAN_TESTNET_CONTRACT_ID` are set in `.env.local`
    * Restart the dev server after changing env vars
  </Accordion>

  <Accordion title="Build fails">
    ```bash theme={null}
    npm run build
    ```

    Fix TypeScript or lint errors reported in the output. Run from the repository root.
  </Accordion>
</AccordionGroup>

## Useful commands

| Command                  | Description                                       |
| ------------------------ | ------------------------------------------------- |
| `npm run dev`            | Start web app on port 3000                        |
| `npm run build`          | Production build                                  |
| `npm run docker:up`      | Start PostgreSQL + MinIO                          |
| `npm run docker:down`    | Stop Docker services                              |
| `npm run db:migrate`     | Apply database migrations                         |
| `npm run db:studio`      | Open Drizzle Studio (database GUI)                |
| `npm run soroban:deploy` | Deploy and initialize the Soroban escrow contract |
| `npm run docs:dev`       | Preview Mintlify docs on port 3001                |
| `npm run lint`           | Lint `apps/web`                                   |

## Next steps

<CardGroup cols={2}>
  <Card title="Soroban escrow setup" icon="cube" href="/local-setup/soroban-escrow-setup">
    Deploy the contract and configure checkout payments.
  </Card>

  <Card title="Environment variables" icon="sliders" href="/local-setup/environment-variables">
    Full reference for OAuth, SMTP, Stellar, and Persona KYC settings.
  </Card>

  <Card title="KYC verification" icon="shield-check" href="/local-setup/kyc-verification">
    Persona identity verification for production mode.
  </Card>
</CardGroup>
