# Deploying to cPanel (Node.js App Manager)

This guide is for cPanel hosts with **Setup Node.js App** (Passenger-based —
common on Truehost, HostPinnacle, Namecheap, Hostinger, and most modern
shared hosting). No code changes are required; the app already reads
`process.env.PORT`, which is what Passenger needs.

`package.json` and `server.js` sit at the top level of this project on
purpose — most hosting panels require the Application Root to directly
contain `package.json`, and won't let you point it at a subfolder. Upload
the whole project as one folder and you're done; there's no nested
"point at the backend subfolder" step.

---

## 1. Upload

Upload the whole project folder (zip upload + extract via File Manager, or
FTP/SFTP) anywhere under your home directory, e.g. `~/meal-mate/`. Don't
upload `node_modules/` — cPanel installs it for you in step 3.

```
meal-mate/             ← this becomes "Application root"
├── server.js           ← this is the "Application startup file"
├── db.js
├── planner.js
├── analytics.js
├── package.json
├── data/
├── frontend/
└── pilot-kit/
```

## 2. Create the Node.js app

cPanel → **Setup Node.js App** → **Create Application**

| Field | Value |
|---|---|
| Node.js version | Latest available (18.x or 20.x) |
| Application mode | Production |
| Application root | `meal-mate` (path relative to your home directory) |
| Application URL | Your domain or subdomain (e.g. `mealmate.yourdomain.ac.ke`) |
| Application startup file | `server.js` |

If you're deploying to a subdomain, create it first under cPanel →
**Domains**, then select it here.

Click **Create**.

## 3. Install dependencies

On the application's page, click **Run NPM Install**. This reads
`package.json` at the application root and installs Express — the only
dependency, with no native build step, so it installs cleanly even on hosts
without compiler access.

## 4. Start it

Click **Restart**. Visit the Application URL — you should see the Meal Mate
login screen, and `https://your-url/api/health` should return:

```json
{"status":"ok","phase":2,"meals":86,"ingredients":177}
```

## 5. Enable HTTPS

cPanel → **SSL/TLS Status** → run **AutoSSL** for the domain/subdomain if it
isn't already covered. Free, takes a couple of minutes.

---

## Updating the app later

1. Upload changed files (overwrite in File Manager, or re-upload via FTP).
2. If `package.json` changed, click **Run NPM Install** again.
3. Click **Restart** on the Node.js app page.

That's it — no build step, no container, no separate deploy pipeline.

---

## Data & backups

The 7 mutable tables are plain JSON files in `data/db/`. There's no
external database to provision, which is exactly why this fits shared
hosting — but it also means **that folder is your entire dataset**. Back it
up the same way you'd back up any uploaded files:

- cPanel → **Backup** → schedule a regular full or partial backup, or
- a weekly cron job (cPanel → **Cron Jobs**) that zips `data/db/`
  to a dated file, e.g.:
  ```bash
  cd ~/meal-mate/data && zip -r ~/backups/db-$(date +\%F).zip db/
  ```

## A note on concurrency

Every database operation in `db.js` is synchronous (`fs.readFileSync` /
`writeFileSync`) and none of the request handlers use `await` between
reading and writing. Node's single-threaded, run-to-completion model means
each read-modify-write is atomic — concurrent requests can't interleave and
corrupt a file. Under heavy simultaneous load, requests queue and process
one at a time rather than overlapping (a throughput tradeoff, not a
correctness one). This is fine for a 100–500-user pilot; if usage ever grows
well past that, the natural next step is swapping `db.js`'s storage layer
for a real database — every other file only talks to `db.js`, so that's a
contained change, not a rewrite.

## Resetting demo/test data before a real pilot launch

Before inviting real participants, wipe whatever test accounts you created
while setting this up:

```bash
cd ~/meal-mate/data/db
for f in users households mealplans nutritiondata preferences; do echo "[]" > $f.json; done
```

Then **Restart** the app in cPanel so it re-seeds a fresh demo account.
