Files
Art-gallery/Documentation/FAC.md
T
Danila Khodjaef bdddadc4d6 Document development-first workflow with weekly prod releases.
Default all day-to-day work to gallery_dev and devgallery; add Cursor rule and update docs, env examples, and deploy guide for scheduled prod promotion.
2026-07-06 09:58:01 +03:00

337 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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, `docker:publish`) is for **scheduled releases** (~weekly) — see [Promote dev → prod](#promote-dev--prod-scheduled-release) below.
**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 start:prod # build client + serve on PORT from .env
# or:
npm run build
npm run 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 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 migrate # schema + incremental SQL (+ auth tables, bootstrap curator)
npm run setup # migrate + seed (fresh empty DB only)
```
**Curator auth (after migrate):** set in `.env` before first `npm run 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 migrate` against prod DB after first deploy with auth vars set (creates tables + bootstrap curator if `users` is empty).
---
## Database
| Command | Description |
|---------|-------------|
| `npm run migrate` | Apply `db/schema.sql` + incremental migrations (safe to re-run) |
| `npm run setup` | `migrate` + `seed` — fresh catalog from Wikipedia data |
| `npm run db:split-databases` | One-time: legacy `Gallery``gallery_prod` + `gallery_dev` (needs `PGUSER=postgres`) |
| `npm run db:sync-from-prod` | Clone `gallery_prod``gallery_dev` (TEMPLATE); also runs image sync from prod |
| `npm run db:backup` | Dev data-only backup → `db/DataBackup/*.txt` + `.zip` |
| `npm run db:backup:prod` | Prod backup (reads `infra/docker/.env.prod`) |
| `npm run db:restore -- --file <path>` | Restore backup into **dev** (truncates tables first; prompts `yes`) |
| `npm run db:restore:prod -- --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 seed` | Eras, movements, artists, one flagship painting per artist |
| 2 | `npm run sync-image-paths` | Import paintings from `data/images/paintings/`; link paths in DB |
| 3 | `npm run fetch-artist-images` | Portraits → `data/images/portraits/`, set `portrait_path` |
| 4 | `npm run fetch-artist-bios` | Wikipedia bios → `bio_short` / `bio_full` |
| 5 | `npm run expand-catalog` | Add famous works per artist (below `MIN_PAINTINGS`) |
| 6 | `npm run update-influences` | Influence graph (detail panels, 3D hall lamps) |
| 7 | `npm run fetch-images -- --limit=50` | Download missing painting files (batch) |
**One-shot bootstrap:** `npm run setup` = steps 1 + migrate only; still run 27 for a full catalog.
### Useful flags
```powershell
npm run sync-image-paths -- --dry-run
npm run fetch-artist-images -- --force
npm run fetch-artist-bios -- --force
npm run expand-catalog -- --fetch-images
npm run fetch-images -- --artist="Claude Monet"
npm run fetch-images -- --limit=50 --max-wait=120
npm run update-influences -- --discover
npm run discover-influences # discovery only, no curated insert
```
### Optional migrations / imports
| Command | Description |
|---------|-------------|
| `npm run migrate:thumbnails` | Add thumbnail columns |
| `npm run migrate:influence-sources` | `painting_influence_sources` table + backfill |
| `npm run migrate:checkup-flags` | Review flags on `paintings` |
| `npm run migrate:artist-checkup-flags` | Review flags on `artists` |
| `npm run migrate:painting-annotations` | Art-history notes table |
| `npm run migrate:artist-palette` | `palette_metadata` JSONB on artists |
| `npm run import-painter-palette` | Enrich from `Inputs/PainterPalette.csv` |
| `npm run update-painting-annotations` | Load curated notes |
| `npm run update-painting-annotations -- --wikipedia` | Add Wikipedia intro sentences |
### Audit / export
| Command | Description |
|---------|-------------|
| `npm run audit-painting-images` | Thumb vs full aspect-ratio mismatches |
| `npm run find-duplicates` | Duplicate / near-duplicate painting rows |
| `npm run audit-influence-duplicates` | Duplicate influence edges |
| `npm run analyze-painter-palette` | CSV ↔ artist name match report |
| `npm run export-paintings` | Write `Output/paintings.csv` |
---
## Images (local files)
| Command | Description |
|---------|-------------|
| `npm run fetch-images` | Search/download missing painting files (alias: `search-missing-paintings`) |
| `npm run fetch-artist-images` | Download or link artist portraits |
| `npm run sync-image-paths` | Align DB paths with files on disk; import new rows |
| `npm run regenerate-thumbnails` | Rebuild all thumbs from full images |
**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 images:sync-to-prod # dev repo → TrueNAS (promote / first deploy)
npm run images:sync-from-prod # TrueNAS → dev repo
```
Type `yes` when prompted. Robocopy exit codes **07** = success.
---
## Docker and production deploy
| Command | Where | Description |
|---------|-------|-------------|
| `npm run docker:publish` | Dev PC, **Admin** PowerShell, Docker Desktop running | Build + push `gallery-web:latest` to Gitea |
| `npm run docker:publish: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 docker:publish` → TrueNAS Custom App from `infra/docker/compose.truenas.yaml`.
**After code changes:** `npm run docker:publish` → restart **gallery-web** on TrueNAS.
```powershell
docker login gitea.mysuperlab.netcraze.pro
```
---
## Build frontend
```powershell
npm run 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.
1. Test on https://devgallery.mysuperlab.netcraze.pro
2. `npm run db:backup`
3. `npm run db:restore:prod -- --file db/DataBackup/gallery_dev_data_....txt` (if DB/catalog changed)
4. `npm run images:sync-to-prod` (if images changed)
5. `npm run docker:publish` (if code changed)
6. Restart **gallery-web** on TrueNAS
7. 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 |
|----------|----------|
| [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 |