Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

Building SP Layers: Exploring São Paulo Through Photography and Cloudinary

São Paulo has many rhythms: busy avenues, street art, food markets, historic buildings, and green spaces tucked between the concrete. I built SP Layers — São Paulo in Layers as an interactive way to explore those differ

Building SP Layers: Exploring São Paulo Through Photography and Cloudinary

São Paulo has many rhythms: busy avenues, street art, food markets, historic buildings, and green spaces tucked between the concrete.

I built SP Layers — São Paulo in Layers as an interactive way to explore those different sides of the city.

Created for the Cloudinary November Mini-Hack: Celebrate Where You're From, the project combines photo stories, small discoveries, and personalized postcards.

🌎 Explore the live app

💻 View the source on GitHub

Cover of the project

Exploring the city through its layers

The experience brings together 20 photo stories across four categories:

  • Flavors: food and the encounters around it.
  • Street Art: color and expression in public spaces.
  • Breathing Spaces: places to slow down.
  • City & Memory: architecture and urban history.

Visitors can open stories, choose three places, reorder their selection, and open an outing in Google Maps for walking, driving, or cycling.

The app supports Brazilian Portuguese, English, and Spanish, along with light and dark themes.

Gallery

Where Cloudinary fits in

Photography is central to the experience. The same image needs to work in a gallery, a portrait comparison, and a postcard.

I used Cloudinary’s URL-based transformations to prepare different versions of each photograph.

For the newer images, the gallery recipe looks like this:

f_jpg,q_auto,c_fill,g_auto,w_720,h_518

This produces a 720 × 518 JPEG crop with automatic quality and gravity.

The treated portrait uses:

f_jpg,q_auto,c_fill,g_auto,w_720,h_960/e_saturation:25/e_tint:12:df9a65

This creates a taller crop, increases saturation, and applies a warm tint.

The app includes a before-and-after comparison so visitors can see how cropping and color treatment change the presentation. The reference image is also resized and compressed; it is a baseline without the additional color treatment.

Cloudinary Comparison

You can find the actual recipes and preparation details in the Cloudinary integration documentation.

Preparing media separately from visits

One architectural decision was to separate image preparation from the browsing experience.

The workflow is:

  1. Upload the photographs to Cloudinary.
  2. Generate the required transformations.
  3. Download and validate the prepared files.
  4. Publish those files with the static app.

The collection contains 61 prepared media files: three versions of each of the 20 photographs, plus the cover image.

Visits do not make Cloudinary requests. Browsing, comparisons, quizzes, and postcard generation use the bundled assets. Preparing or updating those assets still consumes Cloudinary quota.

This approach suits a curated collection with a known set of image variants. Adding new photographs requires an explicit preparation step.

For traceability, the project includes a provenance manifest with transformation URLs, MIME types, file sizes, and SHA-256 hashes.

Turning exploration into a postcard

Visitors can select three photos, add a personal message, and export a postcard as a PNG.

The postcard is composed locally in the browser using Canvas. On supported devices, visitors can share the file through native sharing; downloading provides a fallback.

Photo attribution travels with the exported postcards, and the original sources and licenses remain available in the project.

There is also a discovery mechanic: each story includes an observation question. Answering eight questions correctly unlocks a special postcard featuring all 20 photographs.

Keeping the implementation small

SP Layers uses HTML, CSS, and vanilla JavaScript, with no package dependencies or build step. Vercel serves the static dist/ directory.

The implementation also includes:

  • Lazy loading for comparison images.
  • Reserved image dimensions to reduce layout shifts.
  • Keyboard navigation support and a skip link.
  • Reduced-motion support.
  • Browser storage for preferences and discovery progress.
  • An optional map embed that loads after an explicit click.

No account is required. Personal postcard messages are not saved or included in shared selection links.

What this project brings together

SP Layers connects image processing with something visitors can explore and take away.

Cloudinary prepares the visual variations, the static app presents the stories, and Canvas turns a visitor’s selection into a personal postcard.

The project is also a chance to present São Paulo through smaller details: a meal, a mural, a park, or a building that makes someone stop and look.

Try SP Layers and let me know: which three places would you put on your São Paulo postcard?

Photography belongs to the credited authors. Sources and licenses are available in the app and in the photo credits.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.