Site icon Filestack Blog

Creating a Photography Portfolio With Filestack

Creating a Photography Portfolio With Filestack

Creating a photography portfolio comes down to four problems, and Filestack solves each one with a task in a URL. Mixed aspect ratios have to become a tidy grid. Phone photographs arrive rotated. The full size view has to load fast on a phone. And the work usually wants a signature on it.

You upload each photograph once. Every version below is produced from that one file at request time, so nothing is exported, resized in an editor or stored twice.

Key takeaways

Getting the shoot uploaded

One POST per photograph, or the picker if you want a drag and drop interface:

curl -X POST -F "fileUpload=@dsc_0142.jpg" \
  "https://www.filestackapi.com/api/store/S3?key=YOUR_API_KEY"

What comes back is a 20 character handle. Keep those in whatever holds your portfolio metadata, next to the caption and the shoot date. Handles never change, so they survive every redesign, while URLs do not.

Every URL below ends in a handle, shown as HANDLE. Drop your own in at the end and the same URL runs against your photograph, and the images beside each one show what comes back.

A grid that stays a grid

Portfolios look wrong the moment one thumbnail is portrait and the next is landscape. Fixing that in an editor means exporting a second copy of everything. Fixing it in the URL means one task:

https://cdn.filestackcontent.com/resize=width:280,height:280,fit:crop/output=format:webp/HANDLE

fit:crop fills the square and discards the overflow, so a portrait, a landscape and a square all come out at exactly 280 by 280. The four photographs below are different shapes in the archive and identical in the grid:

A lighthouse, cropped square from a portrait original

 

A tabby cat, cropped square from a square original

 

A boardwalk portrait, cropped square from a portrait original

 

The fourth photograph, cropped square from a landscape original

 

Measured on 6 August 2026, four photographs at that size weighed between 9,452 and 33,968 bytes each, so a page of thirty thumbnails is under a megabyte. The other fit values are worth knowing before you settle on crop, since clip and max preserve the aspect ratio and leave you with the ragged grid you were trying to avoid, and scale distorts to fill. The full set of options is in the image editing api guide.

When the crop cuts the subject out, reach for crop=dim:[x,y,width,height] on that one photograph and go back to the template for the rest.

The one that catches phone photographs

A photograph shot in portrait on a phone is usually stored landscape, with an EXIF orientation tag telling the viewer to turn it. Some software reads that tag and some does not, which is why a gallery ends up with one image on its side.

There is a task for it, and the parameter is not a number:

https://cdn.filestackcontent.com/rotate=deg:exif/HANDLE

That handle is a phone photograph carrying orientation tag 6, and here it is with the tag baked into the pixels:

The same phone photograph after rotate=deg:exif, upright in every viewer because the orientation tag is reset to 1

 

Measured on that file:

Request Pixels returned Orientation tag
The stored original 1536 by 1024 6
rotate=deg:exif 1024 by 1536 1
rotate=deg:90 1024 by 1536 6

 

deg:exif reads the tag, turns the actual pixels, and resets the tag to 1. The image is then upright everywhere, because there is no instruction left for anything to act on.

deg:90 is the trap. It turns the pixels the same way but leaves the tag at 6, so any viewer that honours EXIF turns it a second time and you are back where you started. Put rotate=deg:exif in front of every photograph coming off a phone and the problem disappears for good.

Signing the work

watermark composites one stored file over another, so upload your signature or logo as a transparent PNG once and reference its handle. The first handle in this URL is the signature, the last is the photograph:

https://cdn.filestackcontent.com/watermark=file:SIGNATURE_HANDLE,size:35,position:[bottom,right]/resize=width:800/HANDLE
The photograph at 800 pixels wide with the signature composited into the bottom right corner

 

size is a percentage of the base image width, so the mark scales with whatever size you serve rather than looming over the thumbnails. Percent encode the square brackets around position as %5B and %5D when you send this from curl; a browser does it for you.

Put the watermark before the resize in the chain and it is applied to the full size image, then scaled down with it. That is usually what you want, since the alternative composites a fixed size mark onto an already small image.

The original stays unmarked. Serve the clean version to yourself and the marked version to the public, from the same handle, by changing the URL.

The full size view

The lightbox wants the largest sensible width and nothing more:

https://cdn.filestackcontent.com/resize=width:1600/output=format:webp/HANDLE

Adding the format conversion after the resize is worth roughly a fifth of the bytes. The reasoning behind picking a format at all is in the guide on when to convert to webp.

One rule matters more than the rest here. Never ask for a width larger than the file you uploaded. A 500 pixel wide photograph requested at 1200 pixels came back at 363,715 bytes against the 107,013 byte original, which is a file three times the size and no extra detail in it. Cap the requested width at your smallest original, or serve the untouched handle when you are not sure.

A contact sheet in one URL

collage composites several handles into one image, which is the fastest way to build a proof sheet or a social preview:

https://cdn.filestackcontent.com/collage=files:[HANDLE_B,HANDLE_C,HANDLE_D],margin:10,width:900,height:600,color:white,fit:crop/HANDLE_A
Four photographs composited into one 900 by 600 contact sheet, generated from a single URL

 

The handle at the end is the first image in the sheet and the rest go in files, in order. zip works the same way, zip/[HANDLE_A,HANDLE_B], which gives a client gallery a download button without any server code behind it.

Faces, when the portfolio is street or event work

Face detection runs on the free plan, which matters when you shoot in public and somebody asks to be taken out. blur_faces, pixelate_faces and crop_faces are tasks like any other, so you can mask a face in the published version and keep the original untouched. There is a walkthrough of building on that in the guide to blur faces with Node and React.

The operations that read and interpret an image, such as tagging, captioning and text recognition, run on the higher plans. Automatic keywords for a searchable archive is a Start feature rather than a free one, so plan that in when your catalogue outgrows manual captions.

What a portfolio costs on the free plan

The quotas are 500 uploads, 1 GB of storage, 1,000 transformations and 1 GB of bandwidth a month, checked on the free plan page on 6 August 2026.

For a portfolio, three of those are comfortable and one needs thought.

The Filestack CDN caches each variant after the first request, with a default cache-control: public, max-age=2667950 on the response, so repeat viewers cost you bandwidth but not transformations. How the edges hold those files is covered in the guide to global delivery from the edge.

A portfolio that starts getting real traffic hits the bandwidth line first, and Start raises it to 75 GB. Until then the highest value change is capping your lightbox width, which is a single number in a URL you already have, and folding the whole gallery into a considered file delivery workflow.

 

 

Exit mobile version