photos

Photography portfolio featuring albums, galleries, and globes. 🔧 Built with Next.js, Three.js, and Tailwind. 🌎 Hosted on Contentful and Pages.

contentful · gallery · nextjs · photo · photo-gallery
入门
GitHub在线演示
Stars:44
License:未知
更新:2025/12/25

README

photos.agarun.com

My photography portfolio with galleries, tags, folders, and a globe 🌎

Setup

Development Server

The prerequisites are Node >= 20 and pnpm >= 8.

First, install the dependencies:

pnpm install

Run the development server:

pnpm dev

Open http://localhost:3000 to see the app!

Photos Backend

This project uses Contentful to upload photos and manage photo albums. No other CMS are currently supported.

Beginning April 30, 2025, Contentful has made changes to the Free plan entitlements by reducing the monthly asset bandwidth from 800GB to 50GB. If you expect to exceed 50GB in CDN bandwidth a month, you may consider replacing it with another CMS and update the GraphQL queries and environment variables as necessary.

To start, you'll need to create a Contentful space. Once created, head to Settings -> API Keys -> Add API Key.

Here, you'll see a space ID and two tokens. You can then populate an .env.local file with these:

CONTENTFUL_SPACE_ID=abcdefghijkl
CONTENTFUL_PREVIEW_ACCESS_TOKEN=roughly40randomcharacters
CONTENTFUL_ACCESS_TOKEN=roughly40randomcharacters

Then, head to Content model -> Create content type. Create the Photo Albums model using the schema below. Once made, you can add entries on the Content tab, and upload images to each entry's media field.

This project does not make use of the Contentful Image API to optimize photos. Instead, we optimize images beforehand by converting them to .webp in a script using cwebp and ImageMagick:

bash scripts/webp.sh <some directory of image files>

Technologies

Development

The project is written in TypeScript, using Zod, Tailwind, and Next.js.

Visualization

Globe.GL for the homepage globe and cobe for the about page globe

d3-geo for globe data

three for scene creation

Images

PhotoSwipe for image lightboxes

Masonic for masonry layouts

Pig for image grid layouts

cwebp for compressing .jpg to .webp images. See scripts/webp.sh for details regarding image optimization.

Hosting

The Next site is statically exported and hosted on a GitHub Pages site using GitHub Actions.

All assets are stored on Contentful and fetched from their GraphQL endpoint.

Contentful Schema

Photo Albums

This model refers to the albums featured on the front page.

When asked, the Contentful model should be created with the API identifier photoGallery. You can pick any ID, just be sure to then update photoGalleryCollection where needed in the codebase.

FieldContentful Type
titleShort text
photosMedia, many files
colorShort text - Hexadecimal color code
typeShort text - Enum['location', 'custom']¹
descriptionLong text
dateShort text (optional)
latDecimal
lngDecimal
locationsJSON (optional)²
orderDecimal

¹ type: 'location' refers to albums on the front page with coordinate data. type: 'custom' has a fancy animation and no coordinate data, e.g. the Music album on my site.

² This is an array of objects, each with lat, lng, and description; e.g. [{"lat": 40.00, "lng": 70.00, "description": "narnia"}, ...]

For more information, see the album Zod schemas.

Photo Folders

This model refers to the folders feature available at the /folders route.

When asked, the Contentful model should be created with the API identifier photoFolders. You can pick any ID, just be sure to then update photoFoldersCollection where needed in the codebase.

This feature is optional.

FieldContentful Type
titleShort text
parent_titleShort text
photosMedia, many files
descriptionLong text
dateShort text
orderDecimal