# Deploy RimBoo on cPanel and keep the Vercel site

The cPanel Node.js app is the production server. It serves the pages and the `/api` routes, and it is the only process that can reach the cPanel MySQL database (`localhost` on that server).

The Vercel site is an extra frontend. It does not talk to MySQL itself. After you set `NEXT_PUBLIC_API_BASE_URL` on Vercel to the public cPanel URL, the browser calls the cPanel API.

## 1. Export the XAMPP database

On this PC, from PowerShell:

```powershell
& "C:\xampp\mysql\bin\mysqldump.exe" -u root --single-transaction rimboo_inventory > "$env:USERPROFILE\Desktop\rimboo_inventory.sql"
```

The local root account has an empty password, so there is no `-p`. The file on the Desktop is the full database: tables and the rows you have now, including products and the admin user.

Keep that file private. It contains password hashes.

## 2. Create the cPanel MySQL database

1. In cPanel, open **MySQL Databases**.
2. Create a database. cPanel prefixes the name, for example `cpaneluser_rimboo`.
3. Create a database user and a strong password.
4. Add the user to the database with **ALL PRIVILEGES**.
5. Open **phpMyAdmin**, click the new database in the left column, then **Import**.
6. Choose `rimboo_inventory.sql` from the Desktop and import it.

If phpMyAdmin reports an error on `CREATE DATABASE` or `USE`, the dump was created with a database name your cPanel user cannot create. Delete those two statements from the top of the file and import again while the new database is selected.

For an empty database, import `database/schema.sql` from the `deploy` folder instead. That copy has no `CREATE DATABASE` and no `USE`. The first sign-in creates the administrator `abbarimbo@gmail.com` when the users table is empty. An existing user named `admin` is renamed to that email.

## 3. Build the upload folder on this PC

From the project folder:

```powershell
npx --yes pnpm@12.3.4 run build:cpanel
```

This writes a `deploy` folder:

| Path | What it is |
| --- | --- |
| `app.js` | cPanel startup file. Loads `.env.production`, then starts Next.js. |
| `server.js` | Next.js production server. |
| `package.json` | Production dependencies. `npm start` runs `node app.js`. |
| `package-lock.json` | Lockfile for npm, used only if cPanel has to install dependencies. |
| `node_modules/` | The modules the server needs. Upload this folder. |
| `.next/` | Compiled pages, API routes, and static files. |
| `public/` | Public assets. |
| `next.config.mjs` | The build configuration used for this bundle. |
| `source/app/api/` | The API route source, for reference. The running server uses the compiled files in `.next`. |
| `source/lib/db/pool.ts` | The MySQL pool source. It reads the environment variables at the first query. |
| `database/schema.sql` | Schema ready to import into the selected cPanel database. |
| `.env.production` | Placeholder environment file. Fill it in before upload, or set the same names in cPanel. |
| `DEPLOYMENT.md` | This guide. |

The bundle installs dependencies with npm, including `@swc/helpers`. Upload `node_modules` with the rest of the folder. If the host removes `node_modules`, open the Node.js app and click **Run NPM Install**, then restart.

Zip the contents of `deploy` (the files inside it, not an extra parent folder) and upload that zip.

## 4. Create the Node.js application in cPanel

1. Open **Setup Node.js App** (or **Application Manager**).
2. Create an application:
   - Node.js version: **22** or **24**. Next.js 16 needs **20.9 or newer**.
   - Application mode: **Production**.
   - Application root: the folder where you extracted the zip.
   - Application URL: the domain or subdomain you want, for example `app.yourdomain.com`.
   - Application startup file: `app.js`.
3. Add the environment variables from the table below. Values entered here override `.env.production`.
4. Do not click **Run NPM Install** when `node_modules` uploaded successfully. Use it only if the host stripped `node_modules` during upload.
5. Click **Restart**.

Open the application URL. The sign-in page should load. Sign in and confirm a product list loads. That proves the app reached the cPanel database.

| Name | Value |
| --- | --- |
| `DATABASE_URL` | `mysql://database-user:database-password@127.0.0.1:3306/database-name` |
| `SESSION_SECRET` | A long random string, different from the one on this PC |
| `FRONTEND_ORIGINS` | The Vercel URL, no trailing slash. Example: `https://rimboo-ltd.vercel.app` |

If `DATABASE_URL` is set, it is used instead of the separate `MYSQL_HOST`, `MYSQL_PORT`, `MYSQL_USER`, `MYSQL_PASSWORD`, and `MYSQL_DATABASE` values. Encode `@` in a password as `%40`. Leave `NEXT_PUBLIC_API_BASE_URL` empty on cPanel.

Use the `https://` application URL. The sign-in cookie is marked secure in production, so a plain `http://` URL will not keep you signed in.

## 5. Point the Vercel site at cPanel

In the Vercel project, **Settings → Environment Variables**:

| Name | Value |
| --- | --- |
| `NEXT_PUBLIC_API_BASE_URL` | The public cPanel URL, no trailing slash. Example: `https://app.yourdomain.com` |
| `MYSQL_HOST`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_DATABASE`, `SESSION_SECRET` | You can remove these from Vercel. The Vercel site does not open MySQL. |

Redeploy Vercel after saving. `NEXT_PUBLIC_API_BASE_URL` is copied into the browser bundle at build time, so a new deployment is required.

On cPanel, `FRONTEND_ORIGINS` must be exactly the Vercel origin the browser uses (the `https://….vercel.app` address, or your custom domain). Restart the Node.js app after changing it.

Then open the Vercel URL, sign in, and open Inventory. The browser should call `https://app.yourdomain.com/api/...`. If the list fails, the host or the origin does not match.

## 6. What each address does

- `https://app.yourdomain.com` serves the full app and the API, next to MySQL.
- `https://….vercel.app` serves the pages only, and the browser sends API calls to the cPanel URL.
- The XAMPP database on this PC stays local. The cPanel app cannot use `localhost` to mean this PC.
