# Deploy the CMS on cPanel (unlimited.rs OPTIMUM+) — runbook

> This **replaces** the VPS/systemd/Caddy steps in `CMS Integration Plan.md §5`. Those
> assume root on a VPS; you're on shared cPanel, so the path is different: cPanel's
> **Setup Node.js App** (Passenger) + **PostgreSQL Databases** + a **subdomain**.

**Target:** studio at `https://studio.your-domain.rs/admin`, API at `…/api`, front-end
(Deliverable #1) on the main domain reading from it.

---

## 0 · Honest caveats (read once)

- Payload v3 is a **Next.js** app; on shared cPanel it runs under **Passenger**, which is
  workable but more finicky than a VPS. The two things that bite are **build memory** and
  the **startup file** — both handled below.
- `next build` can exceed a shared account's RAM cap. **Build on your own machine** and
  upload the result (covered in §4), or build over SSH with a memory cap. Don't build in
  the cPanel UI.
- If Passenger fights you, the clean fallback is the **VPS KVM** unlimited.rs sells, or any
  $5/mo Node host — the app is identical, only §3–§5 change. Say the word and I'll write
  that variant.

---

## 1 · Create the database (cPanel → PostgreSQL Databases)

1. Create database `epc_cms`, a user `epc_user` with a strong password, and **add the user
   to the database with ALL privileges**.
2. Note the full name cPanel prefixes (often `cpaneluser_epc_cms` / `cpaneluser_epc_user`).
   Your `DATABASE_URI` host is `127.0.0.1:5432`.

## 2 · Create the subdomain (cPanel → Domains → Subdomains)

Create `studio.your-domain.rs`. Note its document root (e.g. `/home/cpaneluser/studio`).
TLS: cPanel's AutoSSL covers it automatically (LiteSpeed), no Caddy needed.

## 3 · Register the Node app (cPanel → Setup Node.js App)

- **Node version:** 20 or 22 (must be ≥ 20.9).
- **Application root:** the subdomain doc root from §2.
- **Application URL:** `studio.your-domain.rs`.
- **Application startup file:** `server.js`.
- Create it. cPanel gives you the **"Enter to the virtual environment"** command — keep it;
  it's how you run npm/seed in this app's context.

## 4 · Get the code onto the server

On your machine, in the assembled project (see CMS `README.md`):

```bash
echo 'DATABASE_URI=postgres://epc_user:PASS@127.0.0.1:5432/cpaneluser_epc_cms' > .env
echo "PAYLOAD_SECRET=$(openssl rand -hex 32)" >> .env
echo 'PAYLOAD_PUBLIC_SERVER_URL=https://studio.your-domain.rs' >> .env
echo 'CORS_ORIGINS=https://your-domain.rs,https://www.your-domain.rs' >> .env
npm install
npm run build            # builds .next (standalone output)
```

Upload the project to the subdomain root **including `.next`, `package.json`, `server.js`,
`src`, `scripts`, `.env`** (cPanel File Manager upload-zip-extract, or Git — cPanel has a
Git Version Control panel; clone your private repo, then build over SSH if you have RAM).
Exclude `node_modules` from the upload.

Then in the app's virtual environment (from §3) over SSH:

```bash
npm ci --omit=dev        # or `npm install` if ci complains about lockfile
npm run seed             # loads your real content into Postgres (run once)
```

If building over SSH instead of locally: `NODE_OPTIONS=--max-old-space-size=1024 npm run build`.

## 5 · Start it

In cPanel → Setup Node.js App → your app → **Restart**. Passenger runs `server.js` on the
port it injects and proxies `studio.your-domain.rs` to it. Visit
`https://studio.your-domain.rs/admin`, create the first **Admin** user.

Smoke test the API: open `https://studio.your-domain.rs/api/epc-content` → full JSON.

## 6 · Point the front-end at it

In the live front-end's `js/config.js` (Deliverable #1, in `public_html`):

```js
CMS_BASE: "https://studio.your-domain.rs/api",
```

Reload the site. It now hydrates from the CMS on every load, with the baked content as the
instant-paint + outage fallback. Edit something in the studio → reload the site → it's live.

## 7 · Brand the studio (optional, 2 min)

In the project's generated `src/app/(payload)/layout.tsx`, add one import near the top:

```ts
import '../../styles/admin.css'
```

Rebuild + restart. The studio now wears EPCO ink/yellow/cyan. (Logo swap is a further
step via Payload's `admin.components.graphics` + importmap regen — ask if you want it.)

## 8 · Editors

Studio → Users → Create → set role **Editor** or **Admin**. Editors get everything except
Markets, Pricing, and user management (Admin-only).

## 9 · Backups

cPanel already takes **daily off-box backups (40-day retention)** on your plan — that
covers Postgres + the `uploads/` media dir. Nothing else required. For an extra belt, the
`pg_dump`/`tar` cron in `CMS Integration Plan.md §9` still works if you have SSH cron.

---

## Rollback (per-document, instant)

Drafts + version history are enabled on every collection/global. In the studio, open a
document → **Versions** → restore. No server action needed. For a full DB restore, use
cPanel's backup restore (§9).
