Image Gallery with NextJS

Image Gallery with NextJS

Around the holidays I created an image gallery with NextJS. It turned out I had to handle a lot of images (almost 1000!).

I wanted to avoid any existing bloated image gallery with a lot of configuration options. A simple three-column gallery for desktops and a single column for the mobile view.

When the user clicks an image it should be opened and when clicked again, it should close – simple.

But how do I process the images?
– Do I store them along with the source code?
– Should I have them on a CDN like cloudinary?
– Are there any limits in file size, amount of pictures or anything else that could come up?

The best thing is probably just to dwelve into it and start coding! :)

The Tech Stack

The software stack is supposed to be simple. As my rule of thumb, I try to avoid using too many libraries.

Each library is a dependency is a liability.

I wanted to move fast, so I chose:
– NextJS as the React Framework
– Tailwind CSS for the styling

Reading images from disk

My first naïve approach was to simply load the images from a folder public/images which I set to .gitignore for first.

I started with a handful of images which I read with the function getStaticProps which is handled by NextJS in order to get data for the page. This function will be evaluated at build time, so it´s not run each time a request hits the server.

The images´ file names are then passed along to the page Home which houses the gallery.

Problems with this approach

As long as you only want to store a few images (10, 20, maybe 100) you could even think about providing them along the code and storing them next to your source code.

The recommendation given by GitHub is to have a maximum size of 3 GB, definetely not higher than 5 GB for a repository.

When I had realised that my picture selection grew to almost 1000 pictures I needed a different approach:
cloud delivery on a CDN.

Moving images towards the cloud

There is a free service cloudinary with which you can manage your assets (images, videos). You just upload them and cloudinary offers you a generous storage size (25 GB).

Cloudinary Limits:
25k Monthly Transformations or
25GB Managed Storage or
25GB Monthly Net Viewing Bandwidth

Set up a cloudinary account

I created a simple, free account on cloudinary. Once logged in, I uploaded all my pictures by bulk sizes of around 100 images each time. This went quite fast.

The next thing was to figure out how to get a list of all my images from cloudinary, so that I can list them on my gallery.


Three data items are needed in my NextJS code later on:
– The Cloud Name (which you can set individually)
– The API Key
– The API Secret

This is __sensitive__ data which needs to be treated as such.

You don´t want this information committed in your source code on GitHub.

That´s why I use environment variables which will later be read by the source code.

So I take these pieces and create a file in my repository called .env.local with the following content:

Now comes the fun part – connecting the API.

Connect to the cloudinary API

With the connection settings at hand it is now possible to talk to the cloudinary API.

  • How do I get a list of all the images for my gallery?
  • Will that be a simple fetch call or is there a more elegant, simpler solution?

It turns out that cloudinary offers several SDKs for different programming languages.

I simply installed the cloudinary SDK for nodeJS.

Once the module is installed, the connection can be made.

As you can see, I extracted the function which holds the logic for the API call.


Hitting a limit of maximum provided images

“But I have around 1000 images”, and I am only allowed to fetch up to 500 images!

There is a simple solution to that.

The first call delivers a pointer or cursor to the next 500 images. So I will just do another call and join all the images together. These are resources as JSON data provided by the API.

Fine, now I get almost 1000 pictures returned which I can pass to my NextJS page, again.

Rendering 1000 images with the <Image> component

Once all the pictures are passed into my page I loop over them for showing them on my gallery.
It looks similar to this:

The reference to the image, which is now on the cloudinary CDN, is held in the property image.secure_url.

A great advantage when you deal with (a lot of) images in NextJS is that all pictures are lazy loaded. More pictures will be loaded when the user scrolls down the page — not all at once!

The first 12 pictures should be prepared and loaded though. That´s why I give them the priority flag (index < 12).

Deploying on Vercel

Hitting the Image Optimzation limit (on the free tier)

Every image that is used with the <Image> component is processed by Vercel.
This is for providing several image sizes to users, depending on which device they use.
Smaller devices get small images, desktop computers will receive full resolution images.

I hit the limit with almost 1000 images on Vercel.

This is also something, cloudinary can clearly provide for us.

In these cases NextJS offers a loader function which can be utilized to provide the optimal image sources.

Thus, I see two options right now to move on:

– Implement a loader function to offload the image optimization to cloudinary
– Use a library (next-cloudinary) which provides a wrapper component to NextJS´s own <Image> component

I will dive into that in another blog post. For now, the gallery is displayed but I am not able to add many more pictures ?

How would you proceed from here on?