# Deploy Jaipur Handloomia to cPanel — step-by-step

This is the exact runbook to put the store live on your cPanel host. It assumes the host
supports **Node.js apps (Passenger)** and **PostgreSQL** (confirm with the checklist below).

Two apps run side by side:

| App | Folder | Port | Domain |
|---|---|---|---|
| **Backend** (Medusa: API + admin) | `platform/backend` (runs from `.medusa/server`) | 9000 | `admin.jaipurhandloomia.com` |
| **Storefront** (Next.js shop) | `platform/storefront` | 8000 | `jaipurhandloomia.com` |

> Everything below was verified working in development: install → migrate → seed → build →
> start → the store serves the handloom catalog. On the host you run the same steps once.

---

## Your domains (set these once)

The platform is **two web apps** and the browser must reach both, so use **two subdomains**:

| App | Use this domain |
|---|---|
| **Storefront** (the shop) | `app.jaipurhandloomia.com` |
| **Backend** (API + admin dashboard) | `api.jaipurhandloomia.com` |

Create `api.jaipurhandloomia.com` in **cPanel → Subdomains** (and `app.` if not already).

> Throughout this guide, wherever you see `jaipurhandloomia.com` use your **storefront**
> domain `app.jaipurhandloomia.com`, and wherever you see `admin.jaipurhandloomia.com` use
> your **backend** domain `api.jaipurhandloomia.com`. The concrete values are also in §3 and §6.

**Switching to your main domain later** (e.g. storefront on `jaipurhandloomia.com`):
1. Add/point the new subdomains/domain in cPanel and re-run AutoSSL.
2. Update `STORE_CORS`/`ADMIN_CORS`/`AUTH_CORS` in the backend `.env` and restart it.
3. Update `MEDUSA_BACKEND_URL` + `NEXT_PUBLIC_BASE_URL` in the storefront `.env.local`,
   then **`npm run build` again** — the storefront bakes these URLs in at build time, so a
   rebuild is required after any domain change. Restart the storefront app.

---

## 0. Pre-flight checklist (do this first)

In cPanel → **Terminal** (or SSH), confirm:

```bash
node -v          # must be >= 20 (we tested on 20 and 22)
which psql       # PostgreSQL client present
```

Also confirm in cPanel: **Setup Node.js App** exists, **PostgreSQL Databases** exists, and you
have **Terminal/SSH** access. If any is missing, see `docs/platform/05-deployment-cpanel.md`
for the managed-Node fallback (the code is identical; only where the backend runs changes).

## 1. Create the database

cPanel → **PostgreSQL Databases**:
1. Create database e.g. `jh_medusa`.
2. Create user e.g. `jh_user` with a strong password.
3. Add the user to the database with **All Privileges**.
4. Note the connection string:
   `postgres://jh_user:PASSWORD@127.0.0.1:5432/jh_medusa`

## 2. Get the code onto the host

Either:
- **Git (recommended):** in Terminal, `cd ~` then
  `git clone <your-repo-url> ~/apps/jh` (and `git checkout <branch>`), **or**
- **Upload:** run `deploy/package-release.sh` locally to make `jh-platform-release.tgz`,
  upload it via cPanel File Manager to `~/apps/jh`, and `tar xzf jh-platform-release.tgz`.

You should end up with `~/apps/jh/platform/backend` and `~/apps/jh/platform/storefront`.

## 3. Configure the backend

```bash
cd ~/apps/jh/platform/backend
cp .env.template .env
```
Edit `.env` (cPanel File Manager → edit, or `nano .env`):
```
DATABASE_URL=postgres://jh_user:PASSWORD@127.0.0.1:5432/jh_medusa
STORE_CORS=https://app.jaipurhandloomia.com
ADMIN_CORS=https://api.jaipurhandloomia.com
AUTH_CORS=https://api.jaipurhandloomia.com,https://app.jaipurhandloomia.com
JWT_SECRET=<long random string>
COOKIE_SECRET=<long random string>
# Razorpay (add when ready — see §8):
# RAZORPAY_KEY_ID=...
# RAZORPAY_KEY_SECRET=...
# RAZORPAY_WEBHOOK_SECRET=...
# Redis (recommended on cPanel — see §9):
# REDIS_URL=rediss://...
```

## 4. Install, migrate, seed, build (backend)

```bash
cd ~/apps/jh/platform/backend
npm install
npx medusa db:migrate
npx medusa exec ./src/scripts/import-agent-runs.ts   # imports your 25-agent history
npx medusa exec ./src/scripts/seed.ts                 # creates regions + handloom catalog
npx medusa user -e you@jaipurhandloomia.com -p 'YourAdminPassword'   # admin login
npm run build
```
**Copy the publishable key** printed by the seed (`pk_...`) — you need it in §6.
(You can also create more keys later in the admin under Settings → Publishable API Keys.)

## 5. Register the backend as a Node.js App (Passenger)

cPanel → **Setup Node.js App** → Create Application:
- **Node version:** 20+
- **Application root:** `apps/jh/platform/backend/.medusa/server`  ← note: the *build output*
- **Application URL:** `admin.jaipurhandloomia.com`
- **Application startup file:** leave default; then in the app's Terminal run
  `npm install --omit=dev` inside `.medusa/server`, and set the run command to start Medusa
  (`npx medusa start`). Save & **Restart**.

Verify: visiting `https://admin.jaipurhandloomia.com/health` returns `OK`, and `/app` shows
the admin login.

> Why `.medusa/server`? Medusa serves the built admin + API from the build output, not the
> project root. This is the single most common deploy mistake — use the `.medusa/server` path.

## 6. Configure + register the storefront

```bash
cd ~/apps/jh/platform/storefront
cp .env.template .env.local
```
Edit `.env.local`:
```
MEDUSA_BACKEND_URL=https://api.jaipurhandloomia.com
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_...   # from §4
NEXT_PUBLIC_BASE_URL=https://app.jaipurhandloomia.com
NEXT_PUBLIC_DEFAULT_REGION=in
REVALIDATE_SECRET=<long random string>
```
Then:
```bash
npm install
npm run build
```
cPanel → **Setup Node.js App** → Create Application:
- **Application root:** `apps/jh/platform/storefront`
- **Application URL:** `jaipurhandloomia.com`
- Start command: `npm run start` (serves on port 8000). Save & **Restart**.

Visit `https://jaipurhandloomia.com` — you should see the handloom store.

## 7. SSL + domains

cPanel → **Domains/Subdomains**: point `jaipurhandloomia.com` → storefront app and
`admin.jaipurhandloomia.com` → backend app. cPanel → **SSL/TLS Status** → run **AutoSSL** for
both. Make sure your `*_CORS` values in `.env` use the `https://` domains.

## 8. Razorpay (go live)

1. In the **Razorpay dashboard**, get your **Key ID** + **Key Secret** (live).
2. Add them to backend `.env` (`RAZORPAY_KEY_ID`, `RAZORPAY_KEY_SECRET`), then re-run
   `npx medusa exec ./src/scripts/seed.ts` is **not** needed if the store already exists —
   instead enable Razorpay on each region in the admin (Settings → Regions → Payment
   providers → add **razorpay**). Restart the backend app.
3. Create a **webhook** in Razorpay → URL
   `https://admin.jaipurhandloomia.com/hooks/payment/razorpay_razorpay`, events
   `payment.captured` + `payment.authorized`; put the webhook secret in
   `RAZORPAY_WEBHOOK_SECRET` and restart.
4. Test a small live order. (Until keys are set, the **Manual** method works for testing.)

> The Razorpay storefront flow (Checkout popup → place order) is wired but can only be fully
> verified with live keys on the HTTPS site. The Manual/test method is fully working today.

## 9. Hardening on cPanel (recommended)

- **Upstash Redis (free) from day 1** — set `REDIS_URL=rediss://...` so the event bus/queues
  survive Passenger recycling. See `docs/platform/07-architecture-hardening.md §14`.
- **Keep-alive cron** — cPanel → Cron Jobs, every 5 min:
  `curl -s https://admin.jaipurhandloomia.com/health > /dev/null; curl -s https://jaipurhandloomia.com > /dev/null`
- **Backups** — schedule a daily `pg_dump` of `jh_medusa` and download weekly.

## 10. Updates later (zero manual upload)

Once `.github/workflows/deploy.yml` secrets are set (`CPANEL_HOST`, `CPANEL_USER`,
`CPANEL_SSH_KEY`) and repo variable `DEPLOY_ENABLED=true`, pushing to the `release` branch
auto-deploys (pull → install → migrate → build → restart). See
`docs/platform/05-deployment-cpanel.md §3a`.

---

### Quick reference — the commands that were verified

```bash
# backend
cd platform/backend && npm install && npx medusa db:migrate \
  && npx medusa exec ./src/scripts/import-agent-runs.ts \
  && npx medusa exec ./src/scripts/seed.ts && npm run build
cd .medusa/server && npm install --omit=dev && npx medusa start   # /health -> OK

# storefront
cd platform/storefront && npm install && npm run build && npm run start
```
