A configurable art gallery with 3D gallery features
  • JavaScript 84.8%
  • CSS 10.8%
  • Python 2.9%
  • Dockerfile 0.8%
  • Shell 0.5%
  • Other 0.2%
Find a file
2025-10-25 23:33:39 +02:00
.idea change venv name 2025-10-25 15:32:30 +02:00
backend add newlines between json events when telemetry is written to file 2025-10-18 03:17:14 +02:00
docker simplify and fix supervisor config 2025-10-18 03:16:54 +02:00
docs update screenshots and embed them in readme 2025-10-25 23:33:39 +02:00
frontend more reliable mobile device checks for showing/not showing mobile controls 2025-10-21 00:52:46 +02:00
scripts fix BACKEND_ENABLED env var 2025-10-18 03:04:22 +02:00
.gitignore gitignore deployment assets 2025-10-17 00:00:36 +02:00
docker-compose.yml merge api and web containers into one container to simplify setup 2025-10-17 21:18:15 +02:00
LICENSE license 2025-10-12 20:21:31 +02:00
README.md update screenshots and embed them in readme 2025-10-25 23:33:39 +02:00

Art Gallery

Bilingual art gallery featuring a grid view, immersive 3D and AR gallery, and an artist spotlight that renders markdown bios.

Screenshots

Screenshot of the gallery view Screenshot of the artist spotlight Screenshot of the 3d gallery Screenshot of the ar artwork view

Configure Your Own Dataset

Content is split between two directories:

  • frontend/public/<dataset> holds images, favicons, and any other static assets that should be served as-is.
  • frontend/config/<dataset> contains JSON and Markdown that drive the gallery UI.

The Vite dev server (npm run dev) loads test, while production builds (npm run build) inline everything from deploy. Copy the bundled sample and then edit it:

  • Bash: cp -r frontend/public/test frontend/public/deploy and cp -r frontend/config/test frontend/config/deploy
  • PowerShell: Copy-Item -Recurse frontend/public/test frontend/public/deploy and Copy-Item -Recurse frontend/config/test frontend/config/deploy

After editing the deploy variant, run npm run build and those resources will be embedded in the production bundle. You can keep tweaking test for fast dev reloads.

Directory Layout

frontend/
  public/
    deploy/
      images/             # artwork photography, portraits, etc.
      favicon.ico         # optional dataset-specific icon
  config/
    deploy/
      content/
        en_profile.md
        de_profile.md
      data/
        artist.json
        artworks.json
        gallery_map.json
        materials.json

data/artworks.json

Array of artworks. Provide either a numeric id or a unique slug, plus localized strings and optional metadata.

[
  {
    "id": 1,
    "slug": "aurora-dreams",
    "title": { "en": "Aurora Dreams", "de": "Aurora Traeume" },
    "description": {
      "en": "An ethereal blend of cool tones inspired by polar lights.",
      "de": "Eine luftige Mischung kuehler Toene, inspiriert vom Polarlicht."
    },
    "imageUrl": "/deploy/images/aurora.jpg",
    "contactEmail": "studio@example.com",
    "price": {
      "en": "EUR 1,800",
      "de": "1.800 EUR"
    },
    "materialId": 1,
    "sold": false
  }
]

Key fields:

  • title / description: locale-keyed objects (en, de by default).
  • imageUrl: absolute path that points inside public/<dataset>/images.
  • contactEmail: optional; adds the "Inquire" mail link.
  • price: optional localized pricing block.
  • materialId: optional link into materials.json.
  • sold: optional boolean; sold pieces render in a dedicated section.

data/materials.json

Materials tune the 3D rendering of each artwork frame.

[
  {
    "id": 1,
    "name": "Gallery Gloss",
    "normalMap": "/assets/brush_strokes_normal_map.jpg",
    "properties": {
      "roughness": 0.3,
      "metalness": 0.0,
      "clearcoat": 0.7
    }
  }
]

Every material is referenced from artworks via materialId. All properties are optional; omit anything you want to fall back to defaults.

data/artist.json

Controls the artist spotlight. profileUrl accepts either a single Markdown file or a locale map.

{
  "lastName": "Mustermann",
  "imageUrl": "/deploy/images/artist.jpg",
  "profileUrl": {
    "en": "/config/deploy/content/en_profile.md",
    "de": "/config/deploy/content/de_profile.md"
  }
}

content/*.md

Markdown files are rendered with react-markdown. Headings, lists, emphasis, and links are supported.

Drives the immersive gallery layout.

  • tileSize, dimension, wallHeight, wallThickness: overall room scale.
  • pillars: list of { "tile": [x, y], "rotation": degrees }.
  • lights: array of ceiling lights (currently type "point").
  • spawn: starting position { "tile": [x, y], "yawDegrees": number }.
  • paintings: placements such as { "tile": [x, y], "facing": "north", "artworkId": 1 }.
  • sun: optional environment light.
  • showLightIndicators: toggles debug helpers.

Use frontend/config/test/data/gallery_map.json as a template and adjust tiles to match your space.

Quick Checklist

  • Add or replace images inside frontend/public/<dataset>/images.
  • Update copy in JSON/Markdown under frontend/config/<dataset>.
  • Keep locale keys consistent across JSON documents.
  • Run npm run build to bake deploy assets into the production bundle.

Local Development

  • cd frontend && npm install
  • npm run dev serves the app at http://localhost:5173 using the test dataset.
  • Copy any assets you are editing into frontend/public/test (and matching config) for instant reloads.
  • If you need to preview the production bundle locally, run npm run build && npm run preview.

Telemetry Backend (optional)

The frontend only sends telemetry when VITE_ENABLE_TELEMETRY is true. Set the variable before starting Vite:

  • PowerShell (session-scoped): $env:VITE_ENABLE_TELEMETRY='true'; npm run dev
  • Bash: VITE_ENABLE_TELEMETRY=true npm run dev

Steps to run the backend locally:

  1. python -m venv .venv && .\.venv\Scripts\activate
  2. pip install -r backend/requirements.txt
  3. Copy backend/.example.env to backend/.env and set TELEMETRY_PATH if you want to persist events.
  4. Start the API on http://127.0.0.1:5100 with python backend/app.py
  5. (Recommended) Run the development proxy so /api/* hits the backend while static assets come from Vite: python backend/dev_proxy.py and open http://localhost:5000

When telemetry is disabled, events are dropped client-side and the UI hides the privacy notice banner.

Building & Deployment

  • npm run build outputs the static bundle to frontend/dist. When telemetry is required in production, run VITE_ENABLE_TELEMETRY=true npm run build.
  • Docker helpers live in scripts/:
    • scripts/up-without-backend.sh builds and serves the static site only.
    • scripts/up-with-backend.sh builds with telemetry enabled and starts Gunicorn behind Nginx. BACKEND_ENABLED=true controls whether /api/* is routed to Gunicorn.
    • scripts/down.sh stops whichever stack is running.
  • Adjust ART_GALLERY_WEB_PORT (default 8000) if the published port should change.
  • Provide your deploy dataset before building the container so the assets are available at runtime.

License

This project is GPLv3 Licensed.