PhotoSite

PhotoSite

A gallery website that generates dynamic masonry layout and photo view from folders of images.

Motivation

I do some photography as a hobby and wanted a simple way to share my photos online in a photo portfolio.

Existing solutions all seem to have some drawbacks:

  • Photos need to be manually imported
  • No control over the layout or information display (based on EXIF data)
  • No support for image transformation based on preview and lightbox view
  • No support for mobile gestures
  • The solution becomes too complex for my needs
  • ...

I've checked services like Format and self-hosted solutions like Lychee, Piwigo, and Photoview.

PhotoSite

I decided to make a simple photo portfolio and gallery website that generates dynamic masonry layout and photo view from folders of images.

No manual configuration

Ideally, the server should be able to parse the folder structure and EXIF data of each image to generate gallery layout along with photo views.

Since all data is contained in local folders and photos, the album structure cache and transformed images can be automatically generated from them.

The project was developed in two days using Next.js, Tailwind CSS, and the sharp image library.

Implementation

  • Exif data display
  • Mobile swipe gestures
  • Adaptive preview
  • Folder based album generation
  • Folder based navbar generation
  • Dynamic and responsive masonry layout
  • Fade in and out transition

Installation

docker-compose.yml:

services:
  photosite:
    image: meinya/photosite:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - RAW=/raw
      - PREVIEW=/preview
    volumes:
      - ./raw:/raw
      - ./preview:/preview

Folder Structure

Place your images in a separate album folder with any name inside preview and raw folders. For instance:

  • /raw/Toronto/IMG_1.jpg
  • /preview/Toronto/IMG_1.jpg

The same image should have the same name in both folders.

This will generate an album called Toronto with its own navbar link. All images inside the Toronto folder will be displayed in the album. The EXIF data will be displayed in the corresponding photo view if it exists.

Toronto AlbumToronto Album
Toronto Album
Bear Photo ViewBear Photo View
Bear Photo View

To set a cover page for HTML embeds, place a cover.jpg in the preview album folder: /preview/Toronto/cover.jpg

To set a cover page for the root page, place a cover.jpg in the preview root folder: /preview/cover.jpg

Discord EmbedDiscord Embed
Discord Embed

Photo View

The photo view popup will initially display a preview image, followed by the full-resolution raw image once it has finished loading.

A fade in and out animation is applied to transition from the previous image to the next one when the user swipes.

AVIF/WebP Optimization

By default, the project will NOT generate AVIF/WebP images due to the fact that users may want to download the images and share them. It's not ideal to share the image in AVIF format since Apps like Discord do not support AVIF. The project will use the original image format.

Conversion to AVIF/WebP can be enabled by injecting a procedure to the startup scanning pipeline.

For information on image transformation, you may refer to a script I wrote.

Tags:

Next.js,

TypeScript,

Tailwind CSS,

shadcn,

EXIF,

sharp

Previous
A tour on layout animation with 3D scenes
Next
Centipede Game