# Zendo universal deployment guide

Deploy on **Vultr**, **Oracle Cloud**, **AWS**, or any Docker host.

## Project structure

```
zendo/
├── backend/              ← ISOLATED API (own package.json + bun.lock + Dockerfile)
│   ├── server.ts         ← backend entry (Bun)
│   ├── package.json      ← server deps only (no Expo)
│   ├── bun.lock          ← Bun lockfile (API installs only)
│   └── Dockerfile        ← API-only image
├── app/                  ← Expo web/mobile UI
├── Dockerfile            ← full-stack image (web + API on :8080)
├── docker-compose.yml    ← API + web + Postgres (4GB+ RAM)
└── docker-compose.single.yml ← one container (1GB VMs)
```

## Deploy modes

| Mode | Use when | Command / file |
|------|----------|----------------|
| **Full stack (1 container)** | Vultr, Oracle free tier, simple VPS | `docker-compose.single.yml` + root `Dockerfile` |
| **Split stack (3 containers)** | Vultr 4GB+, production | `docker-compose.yml` |
| **API only** | Mobile apps, separate CDN for web | `backend/Dockerfile` |

## Quick start — single container (Vultr / Oracle free tier)

```bash
cp deploy/env.example .env   # edit secrets
docker compose -f docker-compose.single.yml up -d --build
```

Open `http://YOUR_VM_IP:8080` — health check at `/api/health`.

See **`VULTR_ORACLE.md`** for swap, firewall, and ARM notes.

## Quick start — Docker Compose (full stack)

```bash
cp deploy/env.example .env   # edit secrets
docker compose up -d --build
```

Open `http://localhost:8080` (web) — API at `http://api:8080` internally.

## Quick start — API only (backend folder alone)

```bash
cd backend
cp ../deploy/env.example .env
docker build -t zendo-api .
docker run -p 8080:8080 --env-file .env -v zendo_data:/data zendo-api
```

## Environment variables

See `deploy/env.example`. Minimum:

- `JWT_SECRET` (32+ chars)
- `POSTGRES_PASSWORD` (if using compose postgres)
- Stripe keys for real payments

## Endpoints

| Path | Service |
|------|---------|
| `/` | Web UI |
| `/api/trpc` | tRPC |
| `/graphql` | GraphQL |
| `/admin-api` | Admin REST |
| `/webhooks/stripe` | Stripe |
| `/api/health` | Health check |

## Local development

```bash
# Terminal 1 — API (isolated backend)
cd backend && bun install && bun run dev

# Terminal 2 — Expo
npm install && npm start
```

Set `EXPO_PUBLIC_API_BASE_URL=http://localhost:8080` in `.env` for mobile/web dev.

## AWS Express Mode (one ZIP → Fargate)

Upload **`zendo-full-deploy.zip`** (from `npm run package:full`) → Express Mode builds root **`Dockerfile`** → one container on **port 8080** serves web + API. Postgres is **RDS/Aurora** via `DATABASE_URL` (not in the ZIP).

See **`deploy/AWS_EXPRESS.md`** for health checks, env vars, and Stripe webhooks.

## AWS (self-managed)

- **Web static**: build with `npm run build:web`, upload `dist/` to S3 + CloudFront
- **API**: push `backend/Dockerfile` image to ECR → ECS/Fargate on port 8080
- **Or**: push root `Dockerfile` to ECS for all-in-one

## Package for deployment

```bash
npm run package:full
```

Creates `~/Downloads/zendo-full-deploy.zip` with frontend, backend, migrations, and Docker configs.
