Introduce devtoprod:release orchestrator, config file, CLI result footers on deploy scripts, auto-thumb regeneration on curator fixes, and updated deploy documentation. Co-authored-by: Cursor <cursoragent@cursor.com>
357 lines
13 KiB
Markdown
357 lines
13 KiB
Markdown
# Gallery — command reference (FAC)
|
||
|
||
Quick cheat sheet for daily operations. All `npm` commands run from the **repository root** unless noted.
|
||
|
||
**Default target: dev.** Day-to-day commands use `gallery_dev`, repo `data/images/`, and https://devgallery.mysuperlab.netcraze.pro. Prod (`gallery_prod`, Docker, `prod:docker:publish`) is for **scheduled releases** (~weekly) — see [Promote dev → prod](#promote-dev--prod-scheduled-release) below.
|
||
|
||
**Script prefixes:** `dev:` → `gallery_dev` / dev PC · `prod:` → production / TrueNAS · `devtoprod:` → promote dev → prod · `prodto:dev:` → refresh dev from prod · `infra:` → one-time setup
|
||
|
||
**Environments:**
|
||
|
||
| | Dev | Prod |
|
||
|---|-----|------|
|
||
| URL | https://devgallery.mysuperlab.netcraze.pro | https://gallery.mysuperlab.netcraze.pro |
|
||
| Host | Dev PC `192.168.10.70:5173` | TrueNAS `192.168.10.122:5173` |
|
||
| Database | `gallery_dev` | `gallery_prod` |
|
||
|
||
Details: [environments.md](environments.md) · Deploy: [../infra/docker/DEPLOY-truenas.md](../infra/docker/DEPLOY-truenas.md)
|
||
|
||
---
|
||
|
||
## Start and stop servers
|
||
|
||
### Start — public dev (Keenetic URL)
|
||
|
||
```powershell
|
||
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
|
||
npm run dev:web
|
||
```
|
||
|
||
Vite on **:5173**, API on **:3451**. Open https://devgallery.mysuperlab.netcraze.pro or http://localhost:5173.
|
||
|
||
### Start — local HMR (no Keenetic)
|
||
|
||
Two terminals:
|
||
|
||
```powershell
|
||
npm run dev:server # API — PORT from .env (default 3451)
|
||
npm run dev:client # Vite on :5173
|
||
```
|
||
|
||
### Start — production-style (single Node process, built SPA)
|
||
|
||
```powershell
|
||
npm run prod:start # build client + serve on PORT from .env
|
||
# or:
|
||
npm run prod:build
|
||
npm run dev:start
|
||
```
|
||
|
||
### Stop dev servers
|
||
|
||
| Method | When |
|
||
|--------|------|
|
||
| **Ctrl+C** in the terminal running `dev:web` / `dev:server` / `dev:client` | Normal stop |
|
||
| Close the terminal tab | Same effect |
|
||
|
||
Free ports **5173**, **3451**, **3520** before DB maintenance or if “port in use” errors appear.
|
||
|
||
**Find what holds a port (PowerShell):**
|
||
|
||
```powershell
|
||
netstat -ano | findstr ":5173 :3451"
|
||
# Stop by PID:
|
||
Stop-Process -Id <PID> -Force
|
||
```
|
||
|
||
### Stop / restart production (TrueNAS)
|
||
|
||
| Action | Where |
|
||
|--------|-------|
|
||
| **Stop** | TrueNAS Web UI → Apps → **gallery-web** → Stop |
|
||
| **Restart** | Same → Restart (after `docker:publish` or config change) |
|
||
| **Update image** | Dev PC: `npm run prod:docker:publish` → restart app on TrueNAS |
|
||
|
||
---
|
||
|
||
## First-time install
|
||
|
||
```powershell
|
||
cd C:\Users\SNAP\Nextcloud\Personal\Repo\Gallery
|
||
copy .env.example .env # edit DB credentials, PUBLIC_URL
|
||
npm install
|
||
cd client; npm install; cd ..
|
||
|
||
npm run dev:migrate # schema + incremental SQL (+ auth tables, bootstrap curator)
|
||
npm run dev:setup # migrate + seed (fresh empty DB only)
|
||
```
|
||
|
||
**Curator auth (after migrate):** set in `.env` before first `npm run dev:migrate` if the DB has no curator yet:
|
||
|
||
```env
|
||
SESSION_SECRET=your-long-random-secret
|
||
CURATOR_USERNAME=curator
|
||
CURATOR_PASSWORD=your-secure-password
|
||
```
|
||
|
||
Then open the gallery → **Curator login** (top-right) → use debug mode / Checkup. Mutations are logged in `curator_audit_log` (view in pgAdmin).
|
||
|
||
**Roles:**
|
||
|
||
| Role | Access |
|
||
|------|--------|
|
||
| Guest (`user`) | Timeline, movement flow, 3D halls, painting detail, bios |
|
||
| Curator | Above + debug mode, Checkup, image fix/upload/delete APIs |
|
||
|
||
**Audit log (pgAdmin on `gallery_dev` or `gallery_prod`):**
|
||
|
||
```sql
|
||
SELECT l.created_at, u.username, l.action, l.resource_type, l.resource_id
|
||
FROM curator_audit_log l
|
||
JOIN users u ON u.id = l.user_id
|
||
ORDER BY l.created_at DESC
|
||
LIMIT 30;
|
||
```
|
||
|
||
**Prod auth env** (TrueNAS app or `infra/docker/.env.prod`):
|
||
|
||
```env
|
||
SESSION_SECRET=long-random-secret
|
||
SESSION_COOKIE_SECURE=true
|
||
CURATOR_USERNAME=curator
|
||
CURATOR_PASSWORD=your-secure-password
|
||
```
|
||
|
||
Run `npm run dev:migrate` against prod DB after first deploy with auth vars set (creates tables + bootstrap curator if `users` is empty).
|
||
|
||
---
|
||
|
||
## Database
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `npm run dev:migrate` | Apply `db/schema.sql` + incremental migrations (safe to re-run) |
|
||
| `npm run dev:setup` | `migrate` + `seed` — fresh catalog from Wikipedia data |
|
||
| `npm run infra:db:split-dev-prod` | One-time: legacy `Gallery` → `gallery_prod` + `gallery_dev` (needs `PGUSER=postgres`) |
|
||
| `npm run prodto:dev:db` | Clone `gallery_prod` → `gallery_dev` (TEMPLATE); also runs image sync from prod |
|
||
| `npm run dev:db:backup` | Dev data-only backup → `db/DataBackup/*.txt` + `.zip` |
|
||
| `npm run prod:db:backup` | Prod backup (reads `infra/docker/.env.prod`) |
|
||
| `npm run dev:db:restore -- --file <path>` | Restore backup into **dev** (truncates tables first; prompts `yes`) |
|
||
| `npm run devtoprod:db:restore -- --file <path>` | Restore into **prod** (requires confirmation) |
|
||
|
||
**One-time split (recommended):** pgAdmin on dev PC → open [`db/split-dev-prod-pgadmin.sql`](../db/split-dev-prod-pgadmin.sql) → run each STEP on database `postgres`, then verify on `gallery_dev`.
|
||
|
||
**Dev `.env` essentials:**
|
||
|
||
```env
|
||
DB_NAME=gallery_dev
|
||
PORT=3451
|
||
PUBLIC_URL=https://devgallery.mysuperlab.netcraze.pro
|
||
SESSION_SECRET=your-long-random-secret
|
||
SESSION_COOKIE_SECURE=false
|
||
CURATOR_USERNAME=curator
|
||
CURATOR_PASSWORD=your-secure-password
|
||
```
|
||
|
||
---
|
||
|
||
## Import and enrich catalog data
|
||
|
||
Run in this order on a **new** or **re-seeded** database:
|
||
|
||
| # | Command | What it does |
|
||
|---|---------|----------------|
|
||
| 1 | `npm run dev:seed` | Eras, movements, artists, one flagship painting per artist |
|
||
| 2 | `npm run dev:sync-image-paths` | Import paintings from `data/images/paintings/`; link paths in DB |
|
||
| 3 | `npm run dev:fetch-artist-images` | Portraits → `data/images/portraits/`, set `portrait_path` |
|
||
| 4 | `npm run dev:fetch-artist-bios` | Wikipedia bios → `bio_short` / `bio_full` |
|
||
| 5 | `npm run dev:expand-catalog` | Add famous works per artist (below `MIN_PAINTINGS`) |
|
||
| 6 | `npm run dev:update-influences` | Influence graph (detail panels, 3D hall lamps) |
|
||
| 7 | `npm run dev:fetch-images -- --limit=50` | Download missing painting files (batch) |
|
||
|
||
**One-shot bootstrap:** `npm run dev:setup` = steps 1 + migrate only; still run 2–7 for a full catalog.
|
||
|
||
### Useful flags
|
||
|
||
```powershell
|
||
npm run dev:sync-image-paths -- --dry-run
|
||
npm run dev:fetch-artist-images -- --force
|
||
npm run dev:fetch-artist-bios -- --force
|
||
npm run dev:expand-catalog -- --fetch-images
|
||
npm run dev:fetch-images -- --artist="Claude Monet"
|
||
npm run dev:fetch-images -- --limit=50 --max-wait=120
|
||
npm run dev:update-influences -- --discover
|
||
npm run dev:discover-influences # discovery only, no curated insert
|
||
```
|
||
|
||
### Optional migrations / imports
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `npm run dev:migrate:thumbnails` | Add thumbnail columns |
|
||
| `npm run dev:migrate:influence-sources` | `painting_influence_sources` table + backfill |
|
||
| `npm run dev:migrate:checkup-flags` | Review flags on `paintings` |
|
||
| `npm run dev:migrate:artist-checkup-flags` | Review flags on `artists` |
|
||
| `npm run dev:migrate:painting-annotations` | Art-history notes table |
|
||
| `npm run dev:migrate:artist-palette` | `palette_metadata` JSONB on artists |
|
||
| `npm run dev:import-painter-palette` | Enrich from `Inputs/PainterPalette.csv` |
|
||
| `npm run dev:update-painting-annotations` | Load curated notes |
|
||
| `npm run dev:update-painting-annotations -- --wikipedia` | Add Wikipedia intro sentences |
|
||
|
||
### Audit / export
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `npm run dev:audit-painting-images` | Thumb vs full aspect-ratio mismatches |
|
||
| `npm run dev:find-duplicates` | Duplicate / near-duplicate painting rows |
|
||
| `npm run dev:audit-influence-duplicates` | Duplicate influence edges |
|
||
| `npm run dev:analyze-painter-palette` | CSV ↔ artist name match report |
|
||
| `npm run dev:export-paintings` | Write `Output/paintings.csv` |
|
||
|
||
---
|
||
|
||
## Images (local files)
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `npm run dev:fetch-images` | Search/download missing painting files (alias: `search-missing-paintings`) |
|
||
| `npm run dev:fetch-artist-images` | Download or link artist portraits |
|
||
| `npm run dev:sync-image-paths` | Align DB paths with files on disk; import new rows |
|
||
| `npm run dev:regenerate-thumbnails` | Rebuild painting thumbs from full images |
|
||
| `npm run dev:regenerate-portrait-thumbs` | Rebuild timeline portrait thumbs (~256px) |
|
||
| `npm run devtoprod:thumbnails` | Both of the above — run on dev before promote backup/sync |
|
||
| `npm run devtoprod:release` | Config-driven full promote (see [deploy-dev-to-prod.md](deploy-dev-to-prod.md#one-command-release-automated)) |
|
||
|
||
**Local paths:** `data/images/portraits/`, `data/images/paintings/`, `data/images/paintings/thumbs/`
|
||
|
||
---
|
||
|
||
## Dev ↔ prod image sync (SMB)
|
||
|
||
SMB share **`Gallery`** → `/mnt/BasePool/Applications/Gallery` on TrueNAS.
|
||
|
||
```powershell
|
||
net use \\192.168.10.122\Gallery /user:YOUR_TRUENAS_USER
|
||
|
||
npm run devtoprod:release # full promote from infra/deploy/devtoprod.config.json
|
||
npm run devtoprod:thumbnails # rebuild thumb files + DB paths on dev (before backup)
|
||
npm run devtoprod:images # dev repo → TrueNAS (promote / first deploy)
|
||
npm run prodto:dev:images # TrueNAS → dev repo
|
||
```
|
||
|
||
Type `yes` when prompted (or set `autoConfirm: true` in release config). Robocopy exit codes **0–7** = success. Deploy scripts print a final **`===== SUCCESS =====`** or **`===== FAILED =====`** banner.
|
||
|
||
---
|
||
|
||
## Docker and production deploy
|
||
|
||
| Command | Where | Description |
|
||
|---------|-------|-------------|
|
||
| `npm run prod:docker:publish` | Dev PC, **Admin** PowerShell, Docker Desktop running | Build + push `gallery-web:latest` to Gitea |
|
||
| `npm run prod:docker:push-only` | Same | Push only (skip rebuild) |
|
||
| `.\infra\docker\save-for-truenas.ps1` | Dev PC | Save image to `gallery-web.tar` (offline deploy) |
|
||
|
||
**Before first deploy:** `npm run prod:docker:publish` → TrueNAS Custom App from `infra/docker/compose.truenas.yaml`.
|
||
|
||
**After code changes:** `npm run prod:docker:publish` → restart **gallery-web** on TrueNAS.
|
||
|
||
```powershell
|
||
docker login gitea.mysuperlab.netcraze.pro
|
||
```
|
||
|
||
---
|
||
|
||
## Build frontend
|
||
|
||
```powershell
|
||
npm run prod:build # client → client/dist/
|
||
cd client && npm run build && cd ..
|
||
```
|
||
|
||
Prod container serves `client/dist/` from the Docker image (rebuild image after UI changes).
|
||
|
||
---
|
||
|
||
## Verify (health checks)
|
||
|
||
```powershell
|
||
# Dev (servers running)
|
||
curl.exe -sk https://devgallery.mysuperlab.netcraze.pro/api/bounds
|
||
curl.exe -s http://192.168.10.70:5173/api/bounds
|
||
|
||
# Prod (bypass Keenetic)
|
||
curl.exe -s http://192.168.10.122:5173/api/bounds
|
||
|
||
# Prod (public)
|
||
curl.exe -sk https://gallery.mysuperlab.netcraze.pro/api/bounds
|
||
```
|
||
|
||
Expect JSON with `min_year` / `max_year`. HTML shell only from `curl` on `/` is normal (Vite dev).
|
||
|
||
**PowerShell note:** use `curl.exe`, not `curl` — PowerShell aliases `curl` to `Invoke-WebRequest` (no `-k` flag).
|
||
|
||
---
|
||
|
||
## Promote dev → prod (scheduled release)
|
||
|
||
~Weekly (or when explicitly releasing to prod). Not part of daily dev. Full runbook with per-change decision matrix and rollback: [deploy-dev-to-prod.md](deploy-dev-to-prod.md).
|
||
|
||
**One command (recommended):** copy `infra/deploy/devtoprod.config.example.json` → `infra/deploy/devtoprod.config.json`, edit SMB/git settings, then:
|
||
|
||
```powershell
|
||
npm run devtoprod:release
|
||
# or: deploy-dev-to-prod.cmd
|
||
```
|
||
|
||
Dry-run: `npm run devtoprod:release -- -DryRun`. The script pauses for a manual **gallery-web** restart on TrueNAS before verify.
|
||
|
||
**Manual steps** (partial releases):
|
||
|
||
1. Test on https://devgallery.mysuperlab.netcraze.pro
|
||
2. `npm run devtoprod:thumbnails` (if paintings/portraits changed — rebuild thumb files + DB paths on dev)
|
||
3. `npm run dev:db:backup`
|
||
4. `npm run devtoprod:db:restore -- --file db/DataBackup/gallery_dev_data_....txt` (if DB/catalog changed)
|
||
5. `npm run devtoprod:images` (if images changed)
|
||
6. `npm run prod:docker:publish` (if code changed)
|
||
7. Restart **gallery-web** on TrueNAS
|
||
8. Verify https://gallery.mysuperlab.netcraze.pro
|
||
|
||
---
|
||
|
||
## Keenetic (router)
|
||
|
||
Both rules: **protocol to device = `http`**, **Preserve Host = ON**.
|
||
|
||
| Domain | Upstream |
|
||
|--------|----------|
|
||
| `devgallery.mysuperlab.netcraze.pro` | `192.168.10.70:5173` |
|
||
| `gallery.mysuperlab.netcraze.pro` | `192.168.10.122:5173` |
|
||
|
||
Wrong IP or `https` to device → **502 / 504** (`Server: Web server`).
|
||
|
||
---
|
||
|
||
## Git (Gitea)
|
||
|
||
```powershell
|
||
git status
|
||
git add .
|
||
git commit -m "Your message"
|
||
git push origin main
|
||
```
|
||
|
||
Remote: https://gitea.mysuperlab.netcraze.pro/Danilka/Art-gallery
|
||
|
||
---
|
||
|
||
## Related docs
|
||
|
||
| Document | Contents |
|
||
|----------|----------|
|
||
| [deploy-dev-to-prod.md](deploy-dev-to-prod.md) | Step-by-step release runbook (code, DB, data, images) |
|
||
| [environments.md](environments.md) | Full dev/prod walkthrough |
|
||
| [setup.md](setup.md) | Install, env vars, troubleshooting |
|
||
| [data-and-images.md](data-and-images.md) | Catalog and image pipeline |
|
||
| [API.md](API.md) | REST endpoints |
|
||
| [DB_structure.md](DB_structure.md) | PostgreSQL schema |
|