# Tier 3 Upgrade Plan

Order chosen so the toolchain (TS, lint, CSS) is current before touching framework + ORM. Each phase is a separate PM2-reload-able commit so any breakage rolls back cleanly.

**Backups before starting:**
```bash
cp package.json package.json.pre-tier3
cp package-lock.json package-lock.json.pre-tier3
cp prisma/schema.prisma prisma/schema.prisma.pre-tier3
git checkout -b tier3-upgrades
```

---

## Phase 1 — TypeScript 5 → 6  (~2–6h)

1. `npm i -D typescript@6`
2. `npx tsc --noEmit` — fix any new errors (expected 0–5).
3. `npm run build` — confirm Next.js still type-checks.
4. Commit: `chore(deps): typescript 5 → 6`.

**Rollback:** `npm i -D typescript@5`.

---

## Phase 2 — ESLint 9 → 10  (<1h)

1. `npm i -D eslint@10 eslint-config-next@latest`
2. `npm run lint` — Next.js injects flat config automatically.
3. If lint fails on flat-config requirement, add minimal `eslint.config.mjs`:
   ```js
   import next from 'eslint-config-next';
   export default [...next()];
   ```
4. Commit: `chore(deps): eslint 9 → 10`.

---

## Phase 3 — Tailwind 3 → 4  (1–3h)

1. `npm i -D tailwindcss@4 @tailwindcss/postcss@4`
2. Update `postcss.config.js`: replace `tailwindcss: {}` → `'@tailwindcss/postcss': {}`.
3. In your global CSS (likely `app/globals.css`), replace `@tailwind base/components/utilities;` with single `@import "tailwindcss";`.
4. Migrate `tailwind.config.ts` theme extends → CSS-first `@theme` block (6 custom colors).
5. `npm run build` then visually diff landing page + dashboard.
6. Commit: `chore(deps): tailwind 3 → 4`.

**Watch for:** default border color changed from `gray-200` to `currentColor` — explicit borders may need a color.

---

## Phase 4 — Next.js 15 → 16  (2–4h)

1. `npm i next@16 eslint-config-next@16`
2. Run codemod (catches anything missed): `npx @next/codemod@latest upgrade latest`
3. `npm run build` and start dev server.
4. Smoke-test in browser:
   - `/` (landing — JSON loader)
   - Auth flow through `middleware.ts` (`withAuth`)
   - 2–3 dynamic API routes (`/api/files/[fileId]/download`, `/api/messages/[messageId]/read`)
5. PM2 reload on staging if available; otherwise reload prod off-hours.
6. Commit: `chore(deps): next 15 → 16`.

**Watch for:** middleware Edge runtime tightening with `next-auth`. If `withAuth` breaks, pin `next-auth` to its Next-16-compatible release.

---

## Phase 5 — Prisma 6 → 7  (1–2 days, the actual work)

1. **Snapshot DB first:** `pg_dump` to `/home/mahlinacstrat/backups/`.
2. `npm i prisma@7 @prisma/client@7`
3. Update `prisma/schema.prisma` generator:
   ```prisma
   generator client {
     provider = "prisma-client-js"
     // add engineType if edge runtime is needed
   }
   ```
4. `npx prisma generate`
5. `npx prisma migrate dev --name prisma7-baseline` on a dev DB copy. **Do not run migrate on prod yet.**
6. Regression test the 28 API routes that touch Prisma. Focus areas where Prisma 7 changed semantics:
   - JSON field filtering (schema has several `Json` columns)
   - Nested writes / `connectOrCreate`
   - Relation count / `_count` queries
7. Run full app against the migrated dev DB for at least one full day.
8. When green: apply migration to prod with `npx prisma migrate deploy`, PM2 reload.
9. Commit: `chore(deps): prisma 6 → 7`.

**Rollback:** restore pg_dump + `npm i prisma@6 @prisma/client@6`. This is why Prisma is last — earlier phases are reversible without DB state.

---

## Final verification (after all phases)

```bash
npm run build
/root/.n/lib/node_modules/pm2/bin/pm2 reload ecosystem.config.js
curl -sS -o /dev/null -w "Site: %{http_code}\nAPI:  %{http_code}\n" \
  https://lovisamedia.com/ http://127.0.0.1:3001/api/health
npm audit
```

Tag the release: `git tag tier3-complete && git push --tags` (only if you want it pushed — ask first).
