Skip to main content

Photo Gallery Part 5: Fussel

Today, I am trying out Fussel, a static photo gallery generator. I ran across it during my initial search, and it looked promising. Looking into it further now, I discovered that it does not have support for videos, unfortunately. I would like to try it out anyway, mostly because it will allow me to test react-photo-gallery.

Impressions

Installation

The static photo gallery generator part of Fussel is implemented in Python, and the client-side part is implemented using React (JavaScript), using react-photo-gallery. The Fussel code is quite small, so I imagine that it would be pretty easy to hack on.

Since it is a static generator, there is no need to worry about the security of a web application. I prefer to run the generator in a container anyway, however, because doing so helps organize and maintain the software and dependencies. A cbenning/fussel image is available on Docker Hub, but it is not maintained. I confirmed that many packages are out-of-date using lsupg.

$ lsupg --docker cbenning/fussel:latest
apk  busybox                 1.31.1-r19        1.31.1-r21
apk  alpine-keys             2.2-r0            2.4-r0
apk  libcrypto1.1            1.1.1i-r0         1.1.1l-r0
apk  libssl1.1               1.1.1i-r0         1.1.1l-r0
apk  ca-certificates-bundle  20191127-r4       20211220-r0
apk  ssl_client              1.31.1-r19        1.31.1-r21
apk  apk-tools               2.10.5-r1         2.10.8-r0
apk  ncurses-terminfo-base   6.2_p20200523-r0  6.2_p20200523-r1
apk  ncurses-libs            6.2_p20200523-r0  6.2_p20200523-r1
apk  libjpeg-turbo           2.0.5-r0          2.1.0-r0
apk  ca-certificates         20191127-r4       20211220-r0
apk  c-ares                  1.16.1-r0         1.17.2-r0
apk  nodejs                  12.20.1-r0        12.22.10-r0
apk  expat                   2.2.9-r1          2.2.10-r0
apk  sqlite-libs             3.32.1-r0         3.32.1-r1
apk  python3                 3.8.5-r0          3.8.10-r0

If I were to use this software, I would definitely create and maintain my own Docker image, but I will use the provided image for my tests.

Configuration

Fussel is configured using environment variables, so all of the configuration is passed as arguments to the docker run command. In the interest of time, I will just use a simple shell script for my tests. I created a build.sh file along with some empty directories in a test directory.

$ ls -d *
build  build.sh  src

The build script turns off features that I do not want as well as configures a custom site name. The container script uses PUID and GUID environment variables to set the UID and GID, like Lychee. It simply fixes the UID and GID of generated files using chown -R.

#!/usr/bin/env bash

hr -t
docker run --rm -it \
  -v "$(pwd)/src:/input:ro" \
  -v "$(pwd)/build:/fussel/web/build" \
  -e PEOPLE_ENABLE=false \
  -e PGID=$(id -g) \
  -e PUID=$(id -u) \
  -e RECURSIVE_ALBUMS=false \
  -e SITE_NAME="Gallery" \
  -e WATERMARK_ENABLE=false \
  cbenning/fussel:latest
hr -t

I use hr to output a horizontal rule with a timestamp before and after the build. This helps me quickly determine the bounds of the log, as well as see how long builds take.

Note that there is a HTTP_ROOT option which allows you to set a URL prefix. I am not using it in my tests, but this is a feature that I definitely want!

Since Fussel is a static photo gallery generator, there is no web application for gallery administration. Galleries are created by saving images in directories on the filesystem and running the program to create/update the static files. In production, I would need to figure out a way to make that work for my wife, using a network mount or perhaps an SFTP client. I could even prepare a staging service that runs Fussel within my LAN, using rsync to synchronize changes to production.

I copied a month of photos and videos to a subdirectory under src and ran the build script. Many things were logged to the terminal, and the build finished without error. Fussel scales each photo to various sizes, and it simply ignores files that it does not support (such as videos). The static site for a single test album containing 50 photos was built in 29 seconds on my laptop.

Accessing the static site, 10 requests are made, transferring a total of 1.85MB. Note that this includes a 36.74KB thumbnail image for the test album. I consider that to be pretty heavy, but not a deal breaker.

The list of albums looks really nice. The album name and the number of photos is displayed underneath the album thumbnail. It looks like the first image in the album is used as the thumbnail image for the album.

Clicking on an album thumbnail image loads that album. It loads quickly on my laptop. The layout shows thumbnail images in rows, maintaining the aspect ratio of each image yet fully justifying each row by adjusting the height of the images in each row. It looks quite similar to the layout of Google Photos. No information about photos is displayed, even when you hover the mouse over a thumbnail.

Clicking on a thumbnail image opens the photo in a full-page “lightbox” with a semi-transparent dark background. The album is still quite visible in the background. The browser scroll bar can still be used to scroll the album behind the lightbox, which is not very good design.

When the mouse is active, various things are displayed. When the mouse stops moving, these things are hidden after a timeout. Two control icons are displayed at the top right of the page. One puts the browser in full screen mode. The other closes the lightbox and returns to the album. The word “undefined” is displayed at the bottom left of the page. I do not know what this is, though it might be a JavaScript error. The index of the current photo in the gallery, in “1 of 50” format, is displayed at the bottom right of the page.

Oddly, there are no control icons for navigating to the previous or next image in the album. The demo GIF shows such icons, so perhaps there is a bug. I was able to navigate using the keyboard, however, to test it out. The current photo disappears, there is a delay, and then the next photo slides in from the side of the page. This is unfortunately an awkward transition that does not look good. Checking the demo GIF, the current photo should slide off the page as the next photo slides in. This looks much better! I do not know why my test is so different from the demo…

The user interface does not support zooming. I do not even see a way to view the original image. There is no link to download the original image.

Next, I tried out the user interface on a tablet. The album list shows quite large thumbnails that are the full width of my tablet. It does not look good. Opening an album, the album view looks somewhat okay, but the thumbnails are too large, resulting in many rows with only a single photo. It looks a little better in landscape orientation, where many rows have two photos. The touch interface works fine, and the photos can be navigated by swiping. The transition is the same that I saw on my laptop, where the current photo disappears before the next slides in. The controls require a tap to display. For some reason, the full screen mode icon is not displayed. The lightbox prevents pinching to zoom, while pinching the album page causes the browser to zoom.

Next, I tried out the user interface on a phone. It behaved exactly like it did on the tablet.

Since Fussel generates static content, I figured that it would use URLs that reflect the hierarchy of content. It does not! The gallery is accessed using a single index.html file, and query strings are used to specify what to show.

  • Albums list: /?collectionType=albums
  • Album view: /?collectionType=album&collection=NAME
  • Photo view: /?collectionType=album&collection=NAME&photo=FILENAME

This makes sense, as React is used to make single-page applications. Unfortunately, the browser history becomes a total mess. Navigating back changes the URL, but the page usually does not change. This results in having pages where the URL does not match what is shown, and it can make it feel like the page is no longer responsive. It is especially frustrating on Android, where the back functionality is often used.

Evaluation

How does Fussel measure up to my requirements?

The installation and usage of the program is still what I call prototype-level. This is not a problem, as I would be the only person to use it. Gallery administration is done via the filesystem, so it is mostly outside of the scope of the software.

The list of albums looks really nice on a desktop/laptop browser, but it does not look very good on a tablet or phone. Similarly, the album view looks pretty good on a desktop/laptop browser but not a tablet or phone. The photo view looks okay, but there are various issues. There is no zoom functionality, no way to view the original photo, no download functionality, no photo information, and no slideshow functionality. There is full screen functionality on the desktop, but not on Android. Control icons for transitioning to the previous or next photo are now shown, perhaps due to a bug. When transitioning between photos using the keyboard or by swiping, the transition is quite ugly. The browser history is not useful, and the page does not even update to reflect the current URL.

The software is pretty heavy, but not so much that I would not consider it. It has support for building with a URL prefix. I would need to use basic authentication for access control.

The software does not support video. There is no comment functionality. Resource usage is not an issue because the server only serves static files.

I will not consider using this software. In additional to not supporting video, the user interface is much worse than that of the other software that I have tried. I will definitely not even bother to test other gallery software that uses react-photo-gallery.