A minimal photo gallery mimicking Google Photos' style and intended for use with static websites.
axel.leroy.sh/blog/the-making-of-photo-gallery
When working on this project, my goals were to make this photo gallery
- Embeddable in a static website hosted on AWS (S3 & Cloudfront).
- Functionaly minimal: it should just display albums and pictures with relevant EXIF data.
- (relatively) Lightweight with minimal dependancies, with notably no CSS framework involved.
- Efficient, with small thumbnails and HTTP requests caching.
- Look like Google Photo's album grid.
- Being user friendly: there's no GUI to manage albums and pictures.
- Handle everyone's use-cases. My main goal was to make a custom solution for my own portfolio, not to anwser a broad userbase's needs.
PhotoGallery fetches all of its data from static JSON files meant to be stored allongside the app or pictures.
There are two types of JSON files:
- Album List: describes the albums shown by the app
[
{
id: "string",
name: "string",
thumbnail: {
default : {
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
webp: [
{
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
{
url: "string",
height: 600, // in pixels
width: 800 // in pixels
}
],
jpeg: [
{
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
{
url: "string",
height: 600, // in pixels
width: 800 // in pixels
}
]
}
},
{
id: "string",
name: "string",
thumbnail: {
...
}
}
]
- Album Content: describes an album and the pictures it contains
{
id: "string",
name: "string",
pictures: [
{
id: "string",
thumbnail: {
default : {
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
webp: [
{
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
{
url: "string",
height: 600, // in pixels
width: 800 // in pixels
}
],
jpeg: [
{
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
{
url: "string",
height: 600, // in pixels
width: 800 // in pixels
}
]
},
fullsize: {
default : {
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
webp: [
{
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
{
url: "string",
height: 600, // in pixels
width: 800 // in pixels
}
],
jpeg: [
{
url: "string",
height: 300, // in pixels
width: 400 // in pixels
},
{
url: "string",
height: 600, // in pixels
width: 800 // in pixels
}
]
},
exif: {
'Tag': "value"
}
},
{
id: "string",
thumbnail: {
...
},
fullsize: {
...
}
}
]
}
These JSONs are mapped to TypeScript classes you can find in src/app/types
and are generated by the Python script in scripts/
.
Speaking of Python script…
In order to easily upload pictures and create the JSONs, I created a Python script taking care of everything.
Given a folder containing pictures you want to add to an album, it
- parses the relevant EXIF data from each picture
- generates thumbnails and different sizes of the pictures
- generates a JSON file describing the album's content (see How it Works)
- uploads the JSON, pictures and the thumbnails to the given S3 bucket (all under
s3://bucket-name/albumname/
) - updates the albums list JSON with the new album on top
It is located in scripts/ and requires
- Python 3.6+
libjpeg
andlibwebp
installed- a few dependencies you have to install using
pip install -r requirements.txt
- and to set up your AWS credentials
Finally, to list its parameters, just type python add-album.py -h
.
Once it had run, take the created/updated albums.json
and upload it wherever you want (in a bucket, on your website
allongside the gallery, etc.)
Note to users of previous version: Since the album structure has changed to handle different sizes and WebP, I made a migration script named migrate-albums.py to migrate existing albums.
First, install everything using npm install
. Then modify src/environments/environment.ts
or copy it to src/environments/environment.prod.ts
and make the modifications you need
(refer to AppConfig.ts).
The most important attributes to set are
albumListUrl
: the URL to the albums list JSONalbumBaseUrl
: the URL to the folder containing the albums to displayalbumFileNameUrl
: Name of the album JSON file, with file extension.
Set the last two variables so that the app fetches the JSON at albumBaseUrl + albumId + albumFileNameUrl
.
For example, given this configuration
{
albumListUrl: 'https://my-wonderful-website.com/assets/albums.json',
albumBaseUrl: 'https://my-bucket.s3.eu-central-1.amazonaws.com/',
albumFileNameUrl: '/album.json'
}
The app will fetch the albums list at https://my-wonderful-website.com/assets/albums.json
and for an album with the ID
fantastic-album
will fetch its content at https://my-bucket.s3.eu-central-1.amazonaws.com/fantastic-album/album.json
.
Once everything is all set, build the app
npm build [--prod] --baseHref=/base-folder [--deployUrl=/assets/]
Then take everything in /dist/photo-gallery
and deploy anywhere you want !
Note: make sure the assets
folder containing the icons is at the root of you website.
Edit the code if you want the icons to be stored somewhere else.
Here are some CSS styles to apply to the page containing the app in order to customize its look to your liking:
Style h1
and .thumbnail-legend
to change the look of the page title and thumbnails' legend.
You can also style the links using the a
and a:hover
selectors.
To widen or tighten the gap between thumbnails, change .thumbnail-list-item
's margin
properties.
To change the color of loading pictures, change the .thumbnail-bg
's background-color
.
Use border
properties to customize the style and color of the .loader
component.
You can find multiple examples here.
Just set the following:
.thumbnail-list-end {
flex-grow: 0 !important;
}