Files
gallery/README.md
Ryan Chou 614a3d1eff
All checks were successful
Deploy on push / deploy (push) Has been skipped
refactor: clean up gallery tooling and document the workflow
2026-03-22 20:33:29 -07:00

4.1 KiB

Gallery

Static photo gallery for logging meals and food memories.

The site is based on the HTML5 UP Lens template and currently ships as a plain static site: HTML, CSS, JavaScript, and local image assets.

Repo Layout

  • templates/index.html: source template for the main gallery page
  • templates/rankings.html: source template for the rankings page
  • index.html: generated static gallery page
  • rankings.html: generated static rankings page
  • assets/: site CSS, JavaScript, fonts, and audio
  • images/fulls/: full-size gallery images
  • images/thumbs/: gallery thumbnails
  • data/meals.json: source of truth for gallery entries
  • data/elo.json: Elo ratings, record totals, and ranking settings
  • scripts/build.js: renders static pages from templates and data
  • scripts/check.js: validates data, image assets, and generated pages
  • scripts/generate-thumbnails.js: regenerates thumbnails from the full-size images
  • scripts/ingest-meal.js: ingests a new meal image and metadata in one command
  • scripts/serve.js: serves the generated site locally with a small static file server
  • scripts/lib/elo.js: validates and syncs Elo data against the meal list
  • package.json: minimal Node build entrypoint

Run Locally

Install dependencies:

npm install

Build the site and validate the generated output:

npm run build

Serve it locally:

npm run serve

Then open http://127.0.0.1:4321.

If you want a single command that builds and serves, run:

npm start

To validate the repo state without rebuilding thumbnails or pages, run:

npm run check

Content Workflow

Gallery entries live in data/meals.json, and the build generates both index.html and rankings.html from the template and data files.

After editing content or templates, rebuild the site with:

npm run build

The gallery build keeps the existing Lens thumbnail markup intact, so the current client-side viewer code continues to work.

To ingest a new meal image and update the site in one command, run:

npm run ingest -- --image /path/to/photo.jpg --title "meal title" --description "notes"

Optional ingestion flags:

  • --position "left center" sets the viewer image alignment
  • --focus-x 0.35 --focus-y 0.45 sets the thumbnail crop focal point

If you only need to regenerate thumbnails, run:

npm run build:thumbs

To force a full thumbnail rebuild, run:

npm run build:thumbs:force

Rankings Data

data/elo.json stores the seed rating, Elo kFactor, and a win-loss record for each meal. The page build keeps this file aligned with data/meals.json, so new meals automatically appear in rankings.html with the default seed rating.

The interactive voting flow on rankings.html uses browser localStorage for persistence. That means Elo votes persist across reloads on the same browser and device, but they do not sync automatically across devices. Use the reset button on the rankings page if you want to clear the local vote history and go back to the seeded board.

Image Conventions

  • Full-size images and thumbnails share the same numeric ID
  • Full-size images live at images/fulls/<id>.jpg
  • Thumbnails live at images/thumbs/<id>.jpg
  • position controls the full-screen viewer image alignment
  • thumbnail.focus optionally overrides the default center crop for generated thumbnails

Thumbnail Focus

Thumbnails are generated from images/fulls with sharp at 240x320. The generator auto-rotates images using EXIF orientation, skips unchanged files by default, and removes stale thumbnail .jpg files that no longer map to a meal entry.

For images that should crop away from the center, add optional thumbnail focus metadata to the meal entry:

{
  "id": "34",
  "title": "example",
  "description": "example",
  "thumbnail": {
    "focus": {
      "x": 0.35,
      "y": 0.45
    }
  }
}

The x and y values are normalized from 0 to 1, where 0.5, 0.5 is the center of the image.

Planned Features

  1. Optional shared sync or export/import for rankings if browser-local persistence becomes too limiting.