# Deploying Ask QIEN to Vercel

This guide walks you through deploying Ask QIEN to production using **Vercel** (app hosting) and **Vercel Postgres** (database, powered by Neon). It is written for someone who has never deployed to Vercel before.

Before you start, complete the [pre-deployment checklist](pre_deployment.md).

---

## What you will set up

| Piece | Service | Cost |
|---|---|---|
| App hosting | Vercel (Hobby plan) | Free |
| PostgreSQL + pgvector | Vercel Postgres (Neon) | Free up to 256 MB |
| AI job queue | Inngest Cloud | Free up to 50k steps/month |
| Magic-link email | Resend | Free up to 100 emails/day |

Upgrade paths exist on every service when you need them.

---

## Accounts you need before starting

Create accounts at these four services. All have free tiers and no credit card required to start.

1. **GitHub** — [github.com](https://github.com) — your code must be in a GitHub repository
2. **Vercel** — [vercel.com/signup](https://vercel.com/signup) — sign up with your GitHub account
3. **Inngest** — [app.inngest.com/sign-up](https://app.inngest.com/sign-up)
4. **Resend** — [resend.com/signup](https://resend.com/signup) — for sending magic-link emails

---

## Step 1 — Push your code to GitHub

If your code is not already on GitHub:

1. Go to [github.com/new](https://github.com/new) and create a new **private** repository called `ask-qien`.
2. In your terminal, inside the project folder:

```bash
git remote add origin https://github.com/YOUR-USERNAME/ask-qien.git
git push -u origin main
```

---

## Step 2 — Import the project into Vercel

1. Go to [vercel.com/new](https://vercel.com/new).
2. Click **Continue with GitHub** if prompted.
3. Find your `ask-qien` repository in the list and click **Import**.
4. On the configuration screen:
   - **Framework Preset** — Vercel should auto-detect **Next.js**. If not, select it manually.
   - **Root Directory** — leave blank (the project root is correct).
   - **Build Command** — leave as default (`next build`).
   - **Output Directory** — leave as default.
5. **Do not click Deploy yet.** You need to add environment variables first. Scroll down to the **Environment Variables** section — you will fill this in during Steps 4–7 below.

---

## Step 3 — Add a Postgres database

1. In the Vercel dashboard, click into your new project.
2. Click the **Storage** tab at the top.
3. Click **Connect Store** → **Create New** → **Postgres**.
4. Choose a name (e.g. `ask-qien-db`) and a region closest to your users.
5. Click **Create**.

Vercel will automatically add these environment variables to your project:

- `POSTGRES_URL` — pooled connection (used by the running app)
- `POSTGRES_URL_NON_POOLING` — direct connection (used for running migrations)
- `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_HOST`, `POSTGRES_DATABASE`

You do not need to copy these manually — they are already wired up.

---

## Step 4 — Generate a secret for Auth.js

Auth.js needs a random secret to sign session tokens. Run this command in your terminal:

```bash
openssl rand -base64 32
```

Copy the output. You will paste it as `AUTH_SECRET` in the next step.

---

## Step 5 — Set up Resend for email

Magic links are sent by email. Resend is the simplest option.

1. Log into [resend.com](https://resend.com) and go to **API Keys**.
2. Click **Create API Key**, give it a name like `ask-qien-production`, and copy the key (starts with `re_`).
3. In your Resend dashboard, go to **Domains** and add your domain (or use the shared Resend domain `onboarding@resend.dev` for testing — fine for early use).

You will need:
- **SMTP host:** `smtp.resend.com`
- **SMTP port:** `465`
- **SMTP user:** `resend`
- **SMTP password:** the API key you just copied (starts with `re_`)
- **From address:** `noreply@yourdomain.com` (or `onboarding@resend.dev` for testing)

---

## Step 6 — Set up Inngest Cloud

Inngest handles the AI job queue (completeness checks, summarization, draft responses, KB updates).

1. Log into [app.inngest.com](https://app.inngest.com).
2. Create a new app — give it the name `ask-qien`.
3. Go to **Manage** → **Keys**.
4. Copy your **Event Key** and **Signing Key**. You will paste these into Vercel in the next step.

---

## Step 6b — Set up Google OAuth (optional but recommended)

This enables the **Sign in with Google** button on the login page. Skip this step if you want magic-link only for now — you can add it later without redeploying.

1. Go to [console.cloud.google.com](https://console.cloud.google.com/).
2. Create a new project (or select an existing one).
3. Go to **APIs & Services** → **OAuth consent screen**.
   - User type: **External**
   - Fill in app name (`Ask QIEN`), support email, and developer contact email. Everything else can be left blank for now.
   - Click **Save and Continue** through the remaining screens.
4. Go to **APIs & Services** → **Credentials** → **Create Credentials** → **OAuth client ID**.
   - Application type: **Web application**
   - Name: `Ask QIEN`
   - Scroll down to the **Authorized redirect URIs** section (it is near the bottom of the form, below "Authorized JavaScript origins"). Click **+ Add URI** and add each URL on its own line:
     - `https://quality-intelligence.co/api/auth/callback/google`
     - `https://qip-qien.vercel.app/api/auth/callback/google` (your Vercel URL as fallback)
   - If you already created the credential and need to edit it: go to **APIs & Services** → **Credentials**, click the pencil ✏️ icon on your OAuth 2.0 Client ID, and scroll to **Authorized redirect URIs** near the bottom.
5. Click **Save** (or **Create** if this is new). Copy the **Client ID** and **Client Secret** that appear in the confirmation dialog — you will paste these into Vercel in Step 7.

---

## Step 7 — Add all environment variables to Vercel

Go to your Vercel project → **Settings** → **Environment Variables**.

Add each variable below. For each one: type the name in the **Key** field, paste the value in the **Value** field, make sure all three environments are checked (Production, Preview, Development), and click **Save**.

| Variable | Value |
|---|---|
| `DATABASE_URL` | Paste the value of `POSTGRES_URL` from the Storage tab — click Storage → your database → `.env.local` tab to view it |
| `AUTH_SECRET` | The output from `openssl rand -base64 32` in Step 4 |
| `NEXTAUTH_URL` | Your Vercel deployment URL, e.g. `https://ask-qien.vercel.app` — you can update this after first deploy |
| `AUTH_TRUST_HOST` | `true` |
| `EMAIL_SERVER_HOST` | `smtp.resend.com` |
| `EMAIL_SERVER_PORT` | `465` |
| `EMAIL_SERVER_USER` | `resend` |
| `EMAIL_SERVER_PASSWORD` | Your Resend API key (starts with `re_`) |
| `EMAIL_FROM` | `noreply@yourdomain.com` (or `onboarding@resend.dev` for testing) |
| `ANTHROPIC_API_KEY` | Your Anthropic API key |
| `INNGEST_EVENT_KEY` | From Step 6 |
| `INNGEST_SIGNING_KEY` | From Step 6 |
| `TENANT_CONFIG_PATH` | `./tenant.config.yaml` |
| `GOOGLE_CLIENT_ID` | From Step 6b (leave unset to disable Google sign-in) |
| `GOOGLE_CLIENT_SECRET` | From Step 6b (leave unset to disable Google sign-in) |

**Important — do NOT set these in production:**
- `AUTH_DEV_EMAIL_MODE` — only used locally; leave it unset
- `INNGEST_DEV` — only used locally; leave it unset

---

## Step 8 — Deploy

1. Go to the **Deployments** tab in your Vercel project.
2. Click **Redeploy** on the most recent deployment (or trigger a new deploy by pushing a commit).
3. Watch the build log. A successful build ends with `✓ Compiled successfully`.

If the build fails, check the log for missing environment variables or TypeScript errors.

---

## Step 9 — Run database migrations

The database is empty. You need to apply the schema before the app works.

Install the Vercel CLI if you do not have it:

```bash
npm install -g vercel
```

Log in:

```bash
vercel login
```

Pull the production environment variables to a local file:

```bash
vercel env pull .env.production.local
```

This creates a `.env.production.local` file with your live database credentials. Now run migrations against the production database:

```bash
DATABASE_URL=$(grep POSTGRES_URL_NON_POOLING .env.production.local | cut -d= -f2-) pnpm db:migrate
```

> **Why the non-pooling URL?** Drizzle migrations open a direct connection and run DDL statements. Pooled connections (PgBouncer) can cause issues with migrations, so we use the direct URL here.

Then seed the initial data:

```bash
DATABASE_URL=$(grep POSTGRES_URL_NON_POOLING .env.production.local | cut -d= -f2-) pnpm db:seed
```

Delete the local env file when you are done (it contains production secrets):

```bash
rm .env.production.local
```

---

## Step 10 — Connect Inngest to your deployment

Inngest needs to know where your app's `/api/inngest` endpoint is.

1. Log into [app.inngest.com](https://app.inngest.com).
2. Go to **Apps** → your app → **Sync**.
3. Enter your deployment URL: `https://your-app.vercel.app/api/inngest`
4. Click **Sync App**. Inngest will discover your functions automatically.

You should see your functions listed (completeness agent, summarization, etc.).

---

## Step 11 — Smoke test

Open your deployed app and run through this checklist:

- [ ] Go to `/login`, enter `expert@example.com`, click **Send magic link**, click **Open magic link** — you should land in `/inbox`
- [ ] Go to `/submit` (log out first or use a private window logged in as `factorymgr1@example.com`) — submit a test ticket
- [ ] Watch the Inngest dashboard — the completeness, summarization, and draft-response jobs should fire within a few seconds
- [ ] Back in `/inbox` as the expert, the ticket should appear with a status and AI-generated draft
- [ ] Open the ticket, fill in the response form, and submit — ticket should move to resolved
- [ ] Go to `/knowledge` — the KB update proposal should appear

---

## Step 12 — Set your production URL

If Vercel assigned a URL like `ask-qien-abc123.vercel.app`, you can add a custom domain.

1. In Vercel → **Settings** → **Domains**, add your domain.
2. Follow Vercel's DNS instructions (usually adding a CNAME or A record).
3. Once the domain is live, update `NEXTAUTH_URL` in your environment variables to match.

---

## Ongoing deployments

Every `git push` to `main` triggers an automatic deploy. The Vercel build runs
checked-in Drizzle migrations before `next build`, using `POSTGRES_URL_NON_POOLING`
when Vercel provides it.

If a deployment ever reports a missing column, pull production env vars and run
the same migrations manually:

```bash
vercel env pull .env.production.local
DATABASE_URL=$(grep POSTGRES_URL_NON_POOLING .env.production.local | cut -d= -f2-) pnpm db:migrate
rm .env.production.local
```

---

## Troubleshooting

**Build fails with "Module not found"**
Check that all dependencies are in `package.json`, not just `devDependencies`.

**`AUTH_SECRET` error on login**
Make sure `AUTH_SECRET` is set in Vercel environment variables and you have redeployed since adding it.

**Magic link email not arriving**
Check the Resend dashboard for delivery status. Verify `EMAIL_SERVER_PASSWORD` is your Resend API key (not a password you invented). If using `onboarding@resend.dev`, check the Resend logs — delivery to some providers may be filtered.

**Inngest jobs not firing**
Make sure `INNGEST_DEV` is not set in production. Verify the sync URL in Inngest matches your deployment URL exactly. Check the Inngest dashboard for error logs.

**Database connection errors**
Verify `DATABASE_URL` is set to the pooled `POSTGRES_URL` value (not the non-pooling one). The pooled URL is required at runtime on Vercel's serverless functions.
