Visitors walk published tours in a 3D hall with stop notes; curators edit drafts via Tour editor. All galleries (artist, movement, tour) place the first work left of the entrance view and the last on the right.
Co-authored-by: Cursor <cursoragent@cursor.com>
@@ -136,6 +136,33 @@ Short art-history notes shown on painting detail (`PaintingAnnotations.tsx`).
Applied by `npm run dev:migrate:painting-annotations` (`db/migrate-painting-annotations.sql`). Load data with `npm run dev:update-painting-annotations` (curated entries in `scripts/painting-annotations-data.js`; add `--wikipedia` for intro sentences from each work’s `wikipedia_title`).
@@ -6,5 +6,5 @@ this file contains draft for future releases and features
4. ~~tool to sync prod /env resources (both ways), db structure, db data, images, users etc~~ — done for catalog DB + images: `npm run harmonize` (schema dev→prod only; users/audit excluded) — [harmonize-dev-prod.md](harmonize-dev-prod.md)
5. ~~curator_audit_log should contain log of actions like fixit, checked, upload etc with details for which entity it was made and details what was the action and outcome~~ — done: table + `logCuratorAction` on fix/clear/upload/delete/checkup flags (and translation upsert/publish); see [DB_structure.md](DB_structure.md#curator_audit_log). (UI to browse logs is still item 3.)
7. create guided tours (with text/extra infor, set of entities)
7. ~~create guided tours (with text/extra infor, set of entities)~~ — done: `tours` / `tour_stops`, public Tours popup + 3D tour hall, curator Tour editor — [tours.md](tours.md)
@@ -8,7 +8,7 @@ The app is organised as a **drill-down hierarchy**:
1. **Timeline** — historical eras (Ancient → Contemporary) with definite or fuzzy date boundaries.
2. **Movement flow** — art movements as curved SVG streams on the same year axis; documented predecessor→successor branches; portrait thumbnails placed along each stream.
3. **3D gallery** — one personal hall per artist*or* a **movement gallery** (click a movement name on the flow diagram): period-themed interiors, chronological wings of up to ~55 works, side-wall hang only.
3. **3D gallery** — one personal hall per artist, a **movement gallery** (click a movement name), or a **guided tour** hall (timeline → **Tours**): period-themed or tour wings of up to ~55 works, side-wall hang, visit order left→right.
4. **Painting detail** — full work in the centre, *Influenced By* on the left, *Influenced* on the right (paintings, artists, or movements), optional **art-history notes** with image markers, prev/next catalog browsing, optional fullscreen, link to artist biography.
5. **Artist biography** — portrait, lifespan, movement, and Wikipedia-sourced intro text (`bio_short` / `bio_full`). With debug mode on, the same image-audit panel as painting detail (portrait search, **Checked** / **Fix it** / **More** / **Clear** / **Upload**).
@@ -279,7 +281,9 @@ Only **mousedown** on portraits and movement labels stops propagation (so drag-t
## Virtual gallery (3D halls)
The 3D scene supports two modes in `VirtualGallery.tsx`: **artist halls** (personal catalog) and**movement galleries** (full movement collection, chronological).
The 3D scene supports three modes in `VirtualGallery.tsx`: **artist halls** (personal catalog),**movement galleries** (full movement collection, chronological), and **guided tours** (curator-ordered stops — [tours.md](tours.md)).
**Shared wall hang (all modes):** visit order fills the **left wall first**, then the **right**. The **first** work hangs near the entrance on the left (immediately left of the opening view); the **last** hangs near the entrance on the right. Artist halls use chronological order; movement wings use chronological order within each wing; tours use stop order.
### Artist halls
@@ -289,9 +293,8 @@ Each artist has **exactly one hall**. The hall is a rectangular room sized to fi
|------|----------------|
| One hall per artist | `VirtualGallery.tsx` builds a single room from that artist’s paintings |
| Catalog depth | Most artists target **≥ 6** notable works via `npm run dev:expand-catalog` and `famous-paintings-data.js`; some masters have larger museum dumps |
| Paintings on walls | Works hang on the **back, left, and right** walls in **one row per wall**; room **depth grows** when the catalog is large |
| Corridor layout | **15+ paintings:** short back wall (up to 8 works), remaining works on extended **left/right** side walls — a long gallery corridor |
| Wall order | On each wall, left → right: **later works on the left**, **earlier works on the right**; undated works sort toward the left |
| Paintings on walls | Works hang on the **left and right** walls in **one row per wall**; room **depth grows** when the catalog is large (back wall is for the exit only) |
| Wall order | Chronological visit order: first half on the **left** (entrance → back), second half on the **right** (back → entrance); first work left of the opening view, last on the right |
| Period interior | Each of the 26 seeded movements maps to a unique style in `movement-interior-styles.ts` (Italian palazzo, Baroque palace, NYC loft, white cube, etc.) |
| Wall materials | Hi-res **procedural textures** with normal maps (`galleryProceduralTextures.ts`): real-world stone, marble, wood panelling, brick, velvet, stucco — plus **single-colour painted walls** (`painted-lime`, `painted-oil-matte`, `painted-oil-satin`, `painted-emulsion`, `painted-flat`) tinted per movement for Renaissance salons through modern white cubes |
@@ -351,6 +354,20 @@ Enter from the home page by clicking a **movement name** on the movement flow (`
Movement galleries do **not** use the predecessor/successor influence picker — that remains artist-hall only.
### Guided tour halls
Enter from the home page **Tours** popup (`GET /api/tours/:id`). Layout reuses the movement winged hall (`mode: 'tour'` in `VirtualGallery.tsx`).
| Rule | Implementation |
|------|----------------|
| Visit order | Curator `sort_order` on `tour_stops` (not chronological) |
| Wings | Same ~55-per-wing split as movements; order preserved across wings |
| Wall hang | Same left-then-right rule as other halls |
| Detail | Tour stop text panel; ‹› walks tour stops |
| Exit | Wing navigator / **Exit to Timeline** (no influence picker) |
Full guide: [tours.md](tours.md).
### Shared 3D behaviour
**3D images** use locally cached files only (`galleryImageUrl` in `client/src/api/client.ts`). Remote fetches are too slow for realtime WebGL textures; the client calls `POST /api/artists/:id/preload-images` automatically when entering an **artist** hall (public route — links disk files only). Movement galleries load painting lists from the API without a separate preload step. While a texture is loading, the frame shows the canvas cover instead of a white placeholder. The center of the hall shows **“Loading gallery…”** until the WebGL canvas is ready, then **“Loading paintings…”** until every wall texture has resolved (tracked through `GalleryTextureLoadContext`). The 3D hall stays mounted while painting detail or bio overlays are open; returning remounts the canvas when the hall becomes active again.
@@ -359,11 +376,12 @@ Movement galleries do **not** use the predecessor/successor influence picker —
## Painting detail view
Opened from the 3D hall (artist or movement wing — click a frame) or from influence thumbnails on another work’s detail page.
Opened from the 3D hall (artist, movement, or tour wing — click a frame) or from influence thumbnails on another work’s detail page.
| Layer | What you see |
|-------|----------------|
| **Detail** | Centre image, *Influenced By* (left) and *Influenced* (right) — painting thumbnails (full work visible, letterboxed), artist portraits, or movement swatches — position in catalog (e.g. `3 of 12`) |
| **Tour notes** | When opened from a guided tour: stop text panel under the image (English body from `tour_stops`) |
| **Art history notes** | Numbered markers on the image (when positioned) plus a note list below — short citations from Gombrich, museum catalogs, Wikipedia, etc. (`painting_annotations` table) |
| **Fullscreen** | Click the centre image; `Escape` or click anywhere to return to detail only |
@@ -371,7 +389,7 @@ Opened from the 3D hall (artist or movement wing — click a frame) or from infl
| Input | Action |
|-------|--------|
| `‹` / `›` beside image | Previous / next work by the **same artist** (chronological order) |
| `‹` / `›` beside image | Previous / next in the **current catalog** — artist chronology, movement chronology, or **tour stop order** |
| `←` / `→` | Same as prev / next (disabled while fullscreen is open) |
| Click centre image | Open fullscreen lightbox |
| Click influence thumbnail | Open that work’s detail (different artist allowed) |
@@ -382,7 +400,7 @@ Opened from the 3D hall (artist or movement wing — click a frame) or from infl
**Navigation rules:**
- **Catalog browsing** (‹› / arrow keys) walks the current artist’s works earliest → latest. It does **not** change the back target: after browsing several works, **Back to Gallery** still returns directly to the hall.
- **Catalog browsing** (‹› / arrow keys) walks the active catalog (artist / movement chronology, or tour stops). It does **not** change the back target: after browsing several works, **Back to Gallery** still returns directly to the hall.
- **Influence links** push a new detail layer; **Back** from an influenced work returns to the painting you came from (and from there back to the gallery if applicable).
- Side-panel influence images use **`object-fit: contain`** so tall or wide works are not cropped (dark letterbox background).
- The 3D hall stays mounted in the background while detail is open so nothing is lost on return.
@@ -404,6 +422,8 @@ Next to the toggle, **Show more** (checkbox, persisted in `localStorage`) opens
- **Movement lineage** (`movement-lineage.ts`) documents art-historical predecessor→successor links for the flow diagram; extend that file to add or correct branches.
- **One hall per artist** keeps navigation predictable: enter from the timeline or bio, leave via the single exit or back button.
- **Movement galleries** complement artist halls: full movement corpus in period-themed wings, entered from the flow diagram.
- **Guided tours** add curator-ordered winged halls with stop text on painting detail — [tours.md](tours.md).
- **Wall hang** is shared: first work on the left at the entrance, last on the right.
- **Influence-based hall links** connect artists through documented painting relationships, grouped by movement at the exit.
- **3D gallery images** use locally cached files only; slow remote fetches would break realtime rendering. The client calls `POST /api/artists/:id/preload-images` automatically when entering an **artist** hall (public route — links disk files only).
- **3D gallery session** stays mounted while painting detail or bio overlays are open; returning to the hall remounts the WebGL canvas when it becomes active again.
@@ -416,7 +436,7 @@ Next to the toggle, **Show more** (checkbox, persisted in `localStorage`) opens
| Role | Who | Can do |
|------|-----|--------|
| **`user`** | Anonymous visitor (default) | Browse timeline, movement flow, 3D artist/movement halls, painting detail, artist bios, images |
| **`curator`** | Named account (`users` table) | Everything above + **Debug mode**, **Checkup**, **Translations**, **Influences**, debug API mutations |
Curators sign in via **Curator login** in the site header. Sessions use an HTTP-only cookie (`gallery.sid`). The UI hides debug controls from guests; the server enforces the same rules on debug/checkup API routes (`401` without a valid session).
@@ -435,6 +455,8 @@ Curator-only workflow for reviewing and fixing local image files — not part of
| **Debug panel** | Painting detail or artist bio (bottom-left, when debug mode on) | Search preview + action buttons (six on painting detail, five on artist bio) |
@@ -481,5 +503,6 @@ See [API.md](API.md#authentication) and [data-and-images.md](data-and-images.md#
| [DB_structure.md](DB_structure.md) | Tables and relationships |
@@ -265,7 +265,7 @@ To add or fix a branch, edit `MOVEMENT_LINEAGE` in that file and rebuild the cli
Separate from movement lineage layout, `client/src/data/movement-interior-styles.ts` defines a **unique 3D interior** for each seeded art movement (26 styles): wall/floor/ceiling textures, trim colours, window style, and architectural details (columns, coffered ceilings, etc.). Textures are generated procedurally in `client/src/utils/galleryProceduralTextures.ts`.
Wing layout (up to 55 works per wing, side-wall-only hang, window gap placement) lives in `client/src/utils/movementHallLayout.ts`. To change a movement’s look, edit its entry in `movement-interior-styles.ts` and rebuild the client.
Wing layout (up to 55 works per wing, side-wall-only hang, window gap placement) lives in `client/src/utils/movementHallLayout.ts`. Visit order fills the **left wall** (first work at the entrance), then the **right** (last work at the entrance). The same hang applies to artist halls and guided tours. To change a movement’s look, edit its entry in `movement-interior-styles.ts` and rebuild the client.
@@ -72,7 +72,7 @@ If migration fails with permission errors, grant schema rights to the app user f
`npm run dev:migrate` applies `db/migrate-auth.sql` (`users`, `curator_audit_log`, `session` tables). When the `users` table is empty and `CURATOR_USERNAME` / `CURATOR_PASSWORD` are set in `.env`, the first curator account is created automatically.
After migrate, sign in from the site header (**Curator login**). Debug mode, Checkup, Translations, Influences, and all mutating debug APIs require an active curator session. Anonymous visitors browse the timeline and 3D halls without logging in.
After migrate, sign in from the site header (**Curator login**). Debug mode, Checkup, Translations, Influences, Tour editor, and all mutating debug APIs require an active curator session. Anonymous visitors browse the timeline, published Tours, and 3D halls without logging in.
See [API.md — Authentication](API.md#authentication) and [basics.md — Developer tools](basics.md#developer-tools-image-audit).
Curated walkthroughs of selected paintings. Visitors open **Tours** on the timeline, pick a published tour, and walk a 3D hall (`VirtualGallery` mode `tour`). Opening a frame shows stop notes on painting detail; prev/next follow tour order.
## Status
| Status | Who sees it |
|--------|-------------|
| `draft` | Curators only (Tour editor + `GET /api/tours/:id` when signed in) |
| `published` | Everyone via Tours popup + public API |
Tour stop **body** text is English-only in v1 (stored on `tour_stops.body`). UI chrome is EN/RU via i18n.
## Data model
Migration: `db/migrate-tours.sql` (applied by `npm run dev:migrate`).
Included in `scripts/harmonize-db.js` catalog sync.
## Curator editor
Home header → **Tour editor** (curators). Create tours, set draft/published, search-add paintings, reorder, edit stop text, save.
## Visitor flow
1. Timeline → **Tours** → modal of published tours
2. Select tour → `GET /api/tours/:id` → winged 3D hall (left wall first → right wall last, stop order preserved)
3. Click frame → painting detail with tour notes + stop-ordered navigation
4. Back / hall exit → timeline
Hall hang rules match artist and movement galleries — see [basics.md — Virtual gallery](basics.md#virtual-gallery-3d-halls).
## API
See [API.md](API.md#tours). Audit actions: `tour.create`, `tour.update`, `tour.delete`, `tour.stops`.
## Out of scope (v1)
- Russian tour body translations
- Auto-generated / AI tours
- Audio or timed slideshow
- Editing tours from painting detail
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.