Covers architecture, setup, database schema, API reference, and image pipeline; link from README. Co-authored-by: Cursor <cursoragent@cursor.com>
5.0 KiB
5.0 KiB
Art Gallery — database structure
PostgreSQL schema for the virtual gallery. Canonical DDL is intended to live in db/schema.sql when checked in; this document describes the logical model either way.
Connection settings come from .env (see setup.md).
Overview
| Item | Typical value |
|---|---|
| Engine | PostgreSQL 14+ |
| Database | Gallery |
| App user | gallery |
| Time fields | Integer years (negative = BCE) |
Entity relationship
erDiagram
historical_eras ||--o{ art_movements : contains
art_movements ||--o{ artists : groups
artists ||--o{ artist_periods : has
artists ||--o{ paintings : created
artist_periods ||--o{ paintings : groups
paintings ||--o{ painting_influences : influenced_by
paintings ||--o{ painting_influences : influences
Tables
historical_eras
Broad chronological buckets (Ancient, Medieval, Renaissance, …).
| Column | Type | Notes |
|---|---|---|
id |
SERIAL PK | |
name |
VARCHAR(100) | Display label |
start_year, end_year |
INTEGER | Inclusive range |
start_definite, end_definite |
BOOLEAN | false → render as gradient edge on timeline |
description |
TEXT | Tooltip / sidebar copy |
sort_order |
INTEGER | Display order |
art_movements
Finer-grained styles (Impressionism, Cubism, Suprematism, …).
| Column | Type | Notes |
|---|---|---|
id |
SERIAL PK | |
name |
VARCHAR(150) | |
start_year, end_year |
INTEGER | |
start_definite, end_definite |
BOOLEAN | Same visual semantics as eras |
era_id |
FK → historical_eras |
Optional parent era |
description |
TEXT | |
color |
VARCHAR(20) | Hex colour for movement band |
artists
| Column | Type | Notes |
|---|---|---|
id |
SERIAL PK | |
name |
VARCHAR(200) | |
birth_year, death_year |
INTEGER | Nullable; used for timeline portrait placement |
movement_id |
FK → art_movements |
Primary movement |
portrait_path |
VARCHAR(500) | Relative to data/images/ |
bio_short, bio_full |
TEXT | From Wikipedia extracts |
wikipedia_title |
VARCHAR(300) | Source page title |
century |
INTEGER | Rounded century bucket for seeding limits |
artist_periods
Phases within an artist’s career (e.g. “Blue Period”, “Roman Period”).
| Column | Type | Notes |
|---|---|---|
id |
SERIAL PK | |
artist_id |
FK → artists |
ON DELETE CASCADE |
name |
VARCHAR(200) | |
start_year, end_year |
INTEGER | |
description |
TEXT | |
sort_order |
INTEGER | Wall order in 3D gallery |
paintings
| Column | Type | Notes |
|---|---|---|
id |
SERIAL PK | |
artist_id |
FK → artists |
ON DELETE CASCADE |
period_id |
FK → artist_periods |
Optional grouping |
title |
VARCHAR(300) | |
year, year_end |
INTEGER | Creation date(s) |
description |
TEXT | |
image_path |
VARCHAR(500) | Full-size local file |
thumbnail_path |
VARCHAR(500) | Smaller variant for lists / 3D |
wikipedia_title |
VARCHAR(300) | Used by image fetcher |
sort_order |
INTEGER |
painting_influences
Directed edges: this painting was influenced by that painting.
| Column | Type | Notes |
|---|---|---|
id |
SERIAL PK | |
painting_id |
FK → paintings |
The work being explained |
influenced_by_painting_id |
FK → paintings |
The earlier / source work |
notes |
TEXT | Curator summary |
source |
VARCHAR(500) | General attribution |
aspects |
TEXT | What was borrowed (composition, colour, …) |
quote |
TEXT | Short citation |
source_author |
VARCHAR(200) | e.g. Gombrich, Janson |
source_url |
VARCHAR(500) | Reference link |
Unique constraint on (painting_id, influenced_by_painting_id).
Indexes
artists(movement_id),artists(century)paintings(artist_id),paintings(period_id)art_movements(era_id),art_movements(start_year, end_year)painting_influences(painting_id),painting_influences(influenced_by_painting_id)
First-time setup
The gallery database user needs CREATE on schema public for migrations. If tables cannot be created, run admin grants as PostgreSQL superuser before npm run migrate:
GRANT CREATE ON SCHEMA public TO gallery;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO gallery;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO gallery;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO gallery;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO gallery;
Then:
npm run migrate
npm run seed
Data conventions
- Year zero is not used; BCE years are negative integers.
- Image paths are relative to
IMAGE_DIR(default./data/images), e.g.portraits/Claude_Monet.jpg,paintings/thumbs/Raphael_The_School_of_Athens_thumb.jpg. - Seeding cap: curated ingest targets at most ~100 artists per century to keep the catalog manageable.