---
title: "New Oliver Project — Setup Checklist"
description: "Step-by-step checklist for starting any new Oliver Agency project — from Bitbucket to deployed on optical-dev"
tags: [architecture, checklist, deployment, setup]
created: 2026-04-27
updated: 2026-04-27
---

# New Oliver Project — Setup Checklist

## Key Takeaways

- Always use Docker Compose — it's the default for all multi-service projects
- No WebSockets on GCP or optical-dev — use HTTP job polling from day 1
- Add cost-tracker from the start if any AI API calls exist
- Azure AD MSAL is the Oliver standard for authenticated tools
- Create Obsidian project note before writing code

---

## Step 0 — Decide on Stack

Use the decision guide from [[wiki/tech-patterns/_index|tech-patterns]]:

```
New project → what stack?
├── Complex AI platform, multi-user → nextjs-fastapi-fullstack
├── Standard tool with UI → fastapi-python-docker + react-vite-typescript
├── Simple client portal / proxy → nodejs-vanilla-proxy
├── Static page, no backend → plain HTML/JS
└── Needs auth? → always azure-ad-msal-auth
└── Has AI calls? → always add cost-tracker-integration
```

---

## Step 1 — Create Obsidian Project Note

Before writing code. This is where context lives.

```bash
# Create folder + note in vault
mkdir -p ~/Library/Mobile\ Documents/iCloud~md~obsidian/Documents/VadymSamoilenko/01\ Projects/{project-name}/
```

Fill in frontmatter: `client`, `status`, `tech`, `local_path`, `server`, `deploy`, `url`.

---

## Step 2 — Repo and Local Folder

```bash
# Oliver uses Bitbucket (or GitHub for some projects)
# Local project root
mkdir /Users/ai_leed/Documents/Projects/Oliver/{project-name}
cd /Users/ai_leed/Documents/Projects/Oliver/{project-name}
git init

# Standard .gitignore
echo ".env\n.env.*\n!.env.example\n__pycache__/\nnode_modules/\ndist/\n.deploy_state/" > .gitignore
```

---

## Step 3 — Project Structure

### FastAPI + React (standard)
```
{project}/
├── backend/
│   ├── app/
│   │   ├── main.py
│   │   ├── routers/
│   │   ├── models.py
│   │   └── database.py
│   ├── requirements.txt
│   ├── Dockerfile
│   └── .env.example
├── frontend/
│   ├── src/
│   ├── package.json
│   ├── vite.config.ts      ← must include base: VITE_BASE_PATH
│   └── .env.example
├── docker-compose.yml
├── docker-compose.prod.yml
├── deploy.sh
└── CLAUDE.md
```

### CLAUDE.md minimum
```markdown
# {Project Name}
- Server: optical-dev | optical-web-1
- Deploy: bash deploy.sh
- Stack: FastAPI (port 8XXX), React (Vite, /project-path/ subpath)
- Local: docker compose up --build
- No WebSockets — use HTTP polling for any async work
```

---

## Step 4 — Docker Compose

```yaml
# docker-compose.yml (local dev)
services:
  api:
    build: ./backend
    ports: ["8010:8000"]   # pick free port from optical-dev port table
    env_file: ./backend/.env
    depends_on: [db]
  
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes: ["pgdata:/var/lib/postgresql/data"]

  frontend:
    build: ./frontend
    ports: ["5173:5173"]

volumes:
  pgdata:
```

For prod (`docker-compose.prod.yml`): bind API to `127.0.0.1:8010:8000` — never expose containers directly.

---

## Step 5 — Azure AD Auth (if needed)

Required for all Oliver internal tools. See [[wiki/tech-patterns/azure-ad-msal-auth|azure-ad-msal-auth]].

**Backend `.env.example`:**
```env
AZURE_TENANT_ID=
AZURE_CLIENT_ID=
AZURE_CLIENT_SECRET=
DISABLE_AUTH=true   # local dev bypass
```

**Frontend `.env.example`:**
```env
VITE_AZURE_CLIENT_ID=
VITE_AZURE_TENANT_ID=
VITE_BACKEND_URL=http://localhost:8010
VITE_BASE_PATH=/project-name   # for optical-dev subpath
```

---

## Step 6 — Cost Tracker (if AI calls)

Add from day 1. Zero-cost to integrate, prevents budget surprises. See [[wiki/tech-patterns/cost-tracker-integration|cost-tracker-integration]].

```env
COST_TRACKER_BASE_URL=https://optical-dev.oliver.solutions/cost-tracker/v1
COST_TRACKER_API_KEY=ct_live_xxx   # get from admin UI
COST_TRACKER_SOURCE_APP={project-name}
```

---

## Step 7 — Async Work Pattern (no WebSockets)

GCP load balancer kills connections after 30s. Celery is overkill for simple cases — use the job table pattern:

```python
# POST /api/jobs → creates DB row, starts background task → returns {job_id}
# GET  /api/jobs/{id} → returns {status, result}
# Frontend polls every 2s until status == "done"
```

Only add Redis + Celery if: multiple workers needed, task retries needed, or queue length monitoring needed. See [[wiki/tech-patterns/redis-celery-worker-queue|redis-celery-worker-queue]].

---

## Step 8 — Deploy to optical-dev

See [[wiki/architecture/optical-dev-server-deploy|optical-dev-server-deploy]] for full details.

```bash
# Pick a free port (8011–8039 range is safe)
# Create deploy/apache-{project}.conf fragment
# Run deploy.sh on server
ssh optical-dev "cd /opt/{project} && git pull && bash deploy.sh"
```

Minimum `deploy.sh` structure:
1. `git pull origin main`
2. Docker image rebuild (hash-based cache)
3. `docker compose -f docker-compose.prod.yml up -d`
4. Postgres readiness wait → `alembic upgrade head`
5. `npm run build` with `VITE_BASE_PATH`
6. `rsync dist/ → /var/www/html/{project}/`
7. Apache Include injection (idempotent)
8. `apache2ctl configtest && systemctl reload apache2`

---

## Step 9 — Project Note Final Update

After first deploy, update Obsidian note:
- `url:` → actual deployment URL
- `server:` → `optical-dev` or `optical-web-1`
- `deploy:` → exact command
- Add first session entry

---

## Related

- [[wiki/architecture/optical-dev-server-deploy|optical-dev-server-deploy]] — Apache patterns, port table, deploy scripts
- [[wiki/architecture/gcp-deployment-lb-timeout|gcp-deployment-lb-timeout]] — no WebSockets rule
- [[wiki/tech-patterns/azure-ad-msal-auth|azure-ad-msal-auth]] — auth setup
- [[wiki/tech-patterns/cost-tracker-integration|cost-tracker-integration]] — AI cost tracking
- [[wiki/tech-patterns/fastapi-python-docker|fastapi-python-docker]] — backend patterns
- [[wiki/tech-patterns/react-vite-typescript|react-vite-typescript]] — frontend patterns
