Add project documentation under Documentation/.

Covers architecture, setup, database schema, API reference, and image pipeline; link from README.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Danila Khodjaef
2026-06-19 09:46:44 +03:00
co-authored by Cursor
parent 40db99d734
commit 44d3d4359a
6 changed files with 577 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
# Art Gallery — data and images
How catalog content and artwork files enter the system.
## Principles
1. **No runtime hot-linking** — the UI reads from `/images/…` (local disk). External URLs are used only during ingest.
2. **No AI-generated art or text** — biographies and descriptions come from Wikipedia; influence notes from curated art-history sources.
3. **Local copies** — every displayed image should exist under `data/images/` after seeding or fetch.
## Directory layout
```text
data/images/
├── portraits/ # Artist headshots
│ └── Claude_Monet.jpg
└── paintings/
├── Claude_Monet_Water_Lilies.jpg
└── thumbs/
└── Claude_Monet_Water_Lilies_thumb.jpg
```
File names are sanitised `{Artist}_{Title}.{ext}`. The image service can rediscover files on disk even when DB paths are empty (`server/image-service.js``syncPaintingFromDisk`).
## Seeding pipeline
`npm run seed` runs `scripts/seed-wikipedia.js`, which:
1. Inserts **historical eras** and **art movements** (curated date ranges and colours).
2. For each curated **artist**:
- Fetches Wikipedia intro text for `bio_short` / `bio_full`.
- Downloads a Commons portrait into `portraits/`.
- Creates **artist periods** and **paintings**.
- Downloads painting images into `paintings/`.
3. Writes **painting_influences** edges from curated scholarship references.
Artists are grouped by movement and century; the seed list targets at most ~100 artists per century.
## On-demand image resolution
When a painting has no local file, `GET /api/paintings/:id/image` triggers `ensurePaintingImages()`:
1. Check DB paths → verify file on disk.
2. Scan disk by `{artist}_{title}` pattern.
3. If still missing and `wikipedia_title` is set, call `scripts/image-fetcher.js`:
- Wikidata → Wikimedia Commons → Wikipedia page image
- Fallbacks: Met Museum, Art Institute of Chicago, Rijksmuseum APIs
4. Save full + thumbnail, update DB, serve file.
Requests are deduplicated (`inflight` map) and timeout after 15 seconds. A 2.5 s delay between external requests reduces rate-limit risk.
## Preload before 3D gallery
`POST /api/artists/:id/preload-images` runs **local-only** linking — no network. Call this when entering an artists 3D hall so textures use files already on disk.
The 3D scene uses `galleryImageUrl()`, which never hits the on-demand API (remote latency breaks WebGL texture loading).
## Placeholders
When no image is available:
- `/placeholder-portrait.svg` — timeline / movement band portraits
- `/placeholder-art.svg` — paintings in lists and detail view
These live in `client/public/` (and `client/dist/` after build).
## Adding new artists manually
1. Insert rows into `artists`, `artist_periods`, `paintings` (or extend the `ARTISTS` array in the seed script).
2. Place image files under `data/images/` using the naming convention.
3. Run `npm run sync-image-paths` if that script is available, or rely on preload / on-demand sync.
4. Add influence rows to `painting_influences` with citation fields where possible.
## Image fetcher overrides
`scripts/image-fetcher.js` includes hand-maintained overrides for ambiguous Wikipedia titles and direct URLs (e.g. works whose Commons name does not match the article title). Extend `PAINTING_WIKI_OVERRIDES` and `DIRECT_IMAGE_OVERRIDES` when automated resolution fails.