Aperture is a simple photo gallery webstack. Created to serve my needs but it may be useful for others.
This document should have everything you need to start.
See a working instance here.
- Uses folder structure to layout content into categories and albums.
- Define information such as: location, dates, description etc. within each album's
config.yml
file. - The API serves image metadata on the fly and displays that information when a thumbnail is expanded.
- Thumbnail lazy loading and once clicked, displays the full image, with zoom and grab capabilities.
- Gallery masonary to display landscape and portait images together cleanly.
- Create "hidden" categories by prefixing a categories folder name with an underscore. Example
_my-hidden-category
. These will not be displayed on the frontend but can still be shared with other users. - Some SEO support.
.png
support and.mp4
support.- Cache image metadata instead of processing each image, everytime.
- Add comprehensive logging to the API.
- Dark theme.
- Frontend
- Backend
- Containerisation
Not only can it be used in conjunction with the Aperture UI - you may use it for your own projects. Build your own photoframe with a Raspberry Pi? A two-way mirror with a screen behind it displaying your photos? Build your own web interface that will most likely look better than mine? Go crazy 🤙
git clone git@github.com:pogacic/aperture.git
cd aperture
- Configure variables within
aperature-ui/nuxt.config.ts
(underruntimeConfig->public
) - Configure CORS variable within
docker-compose.yml
(under the API service). This value is the URL of your UI. For example:https://pogacic.com
. docker-compose up
cd aperture-api
docker build -t aperture-api .
docker run -dp 8080:8080 aperture-api
- http://localhost:8080/categories
The default API Dockerfile will mount /photos
to /opt/aperture_photos
.
Look inside docker-compose.yml
to change this volume mount under the aperture-api
service.
You may also need to chown the user and docker group for the API to read the files within.
sudo mkdir /opt/aperture_photos
sudo chown <user>:docker /opt/aperture_photos
Just bring everything down, git pull, and docker compose everything back up! Though for a sitemap to generate properly, bring up the API separately before starting the UI.
cd aperture
git pull
docker-compose down && docker-compose up --build -d aperture-api && docker-compose build --no-cache aperture-ui && docker-compose up -d aperture-ui
It is recommended to change the values within the nuxt.config.ts
file under the aperture-ui/
folder before building. This is where you'll be able to change the:
- Site name
- Site description
- Site URL
- What header image will be displayed behind the
Site name
- Where the API is being served from
- The sitemap hostname
If you wish to change the theme of the website then change line 23 of aperture-ui/tailwind.config.js
. You can find the list of themes within the DaisyUI documentation.
/albums
/categories
/<category>/<album>
/photos/<category>/<album>/header.jpg
/photos/<category>/<album>/album.jpg
/photos/<category>/<album>/large/large-1.jpg
/photos/<category>/<album>/thumbnail/thumbnail-1.jpg
Example:
{
"categories": {
"adventures": {
"randomAlbumCover": "photos/adventures/andorra-2022/album.jpg"
},
"automotive": {
"randomAlbumCover": "photos/automotive/salone-events-podium-place-2023/album.jpg"
}
}
}
Example:
{
"albums": {
"adventures": {
"andorra-2022": {
"name": "Andorra 2022",
"subtitle": "Some ski slope",
"description": "Photos containing snow",
"placeURL": "google.com/andorra_something_something",
"placeName": "Andorra",
"startDate": "2022-03-03T00:00:00Z",
"endDate": "2022-03-08T00:00:00Z",
"images": null
}
},
"automotive": {
"salone-events-podium-place-2023": {
"name": "Salone Events Podium Place 2023",
"subtitle": "Cars and coffee",
"description": "Supercars and classics",
"placeURL": "https://saloneevents.co.uk/buy/podium-place-car-meet-march",
"placeName": "Newbury, UK",
"startDate": "2023-03-04T00:00:00Z",
"endDate": "2023-03-04T00:00:00Z",
"images": null
}
}
}
}
Example:
{
"name": "Salone Events Podium Place 2023",
"subtitle": "Cars and coffee",
"description": "Supercars and classics",
"placeURL": "https://saloneevents.co.uk/buy/podium-place-car-meet-march",
"placeName": "Newbury, UK",
"startDate": "2023-03-04T00:00:00Z",
"endDate": "2023-03-04T00:00:00Z",
"images": {
"large-1.jpg": {
"large": "large-1.jpg",
"thumbnail": "thumbnail-1.jpg",
"metadata": {
"width": 3000,
"height": 2000,
"exposure": "1/800",
"f_stop": "2.8",
"focal_length": "106",
"lens_model": "EF70-200mm f/4L IS USM",
"make": "Canon",
"model": "Canon EOS M50",
"iso": 200
}
},
"large-10.jpg": {
"large": "large-10.jpg",
"thumbnail": "thumbnail-10.jpg",
"metadata": {
"width": 3000,
"height": 2000,
"exposure": "1/1000",
"f_stop": "2.8",
"focal_length": "97",
"lens_model": "EF70-200mm f/4L IS USM",
"make": "Canon",
"model": "Canon EOS M50",
"iso": 200
}
}
}
}
...
The API looks through the the /photo
folder, this folder structure has been setup to allow for categories -> albums
.
Below describes the folder/file layout that has to be adhered to:
photos/ # Root image folder
├─ automotive/ # Category
│ ├─ drift-event-2023 # Album
│ │ ├─ large # Large image folder
│ │ │ ├─ large-1.jpg
│ │ │ ├─ large-2.jpg
│ │ │ ├─ large-3.jpg
│ │ ├─ thumbnail # Thumbnail image folder
│ │ │ ├─ thumbnail-1.jpg
│ │ │ ├─ thumbnail-2.jpg
│ │ │ ├─ thumbnail-3.jpg
│ │ ├─ album.jpg # Album JPG
│ │ ├─ config.yml # Configuration file
An example of this will be within the codebase, see the aperture-api-go/photos
folder.
You may name your images however you wish, but suffix -1
, -2
, -3
, -X
at the end of the filename so full "large" image's can be linked to their respective thumbnail counterparts. (See Folder Structure to get an idea).
This application at the moment only supports the JPG
file type.
The large/
folder can contain fullsized, high quality JPEG's, the thumbnail/
folder contains those exact same images but at a smaller resolution.
Each album can contain a config.yml
file - this file allows the user to define data such as the name, subtitle, description of the album.
name: Andorra 2022
subtitle: Some ski slope
description: Photos containing snow
placeURL: google.com/andorra_something_something
placeName: Andorra
startDate: 2022-03-03
endDate: 2022-03-08
name
: Name of the album (string).subtitle
: Subtitle of the album (string).description
: Description of the album (string).placeURL
: URL of the place or anything relevant (string).placeName
: Location of the albumYYYY-MM-DD
format (string).startDate
: Start date of albumYYYY-MM-DD
format (string).endDate
: End date of album (string).
Image metadata is processed when an album is loaded (You can find metadata functions and structs within aperture-api-go/lib/metadataParser.go
).
I use Lightroom to export my photography. You can find my thumbnail
and large
Lightroom export templates within the misc/
folder.
Below are some NGINX configuration blocks to give you a helping hand setting up.
server {
server_name api.pogacic.com;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass "http://localhost:8080";
}
}
server {
server_name pogacic.com;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass "http://localhost:3000";
}
}