Sometimes you need to touch grass. Other times, you want to commemorate the beautiful Fall foliage that you peep outside your window and create a crowdsourced way for other folks to share their trees too! This app celebrates the second kind of day.
Local Leaf is an Astro app that ranks neighborhood tree photos by fall color. It uses Cloudinary for moderated uploads, tags, and predominant-color detection, and this post shows how to build it. The source code is on GitHub.
In the tradition of creating somewhat pointless - but highly aesthetic - software, you too can build an app to celebrate nature.
What you'll build
- How to add the Cloudinary upload widget to an Astro app
- How to set up an upload preset that sends photos to a moderation queue
- How to store simple data as Cloudinary tags and context metadata instead of a database
- How to read Cloudinary’s predominant-color data for each photo
- How to turn that color data into leaderboard scores for yellow, orange, and crimson trees
Leaf Peeping Needs a Leaderboard
Everywhere in New England there are leaf-peeping forays at this time of year. People drive for hours to surround themselves in forest colors, driving to Western Massachusetts, Vermont, and New Hampshire to look at the deciduous trees as they change colors in the Fall. Depending on the summer and fall weather patterns, colors can vary dramatically from fire-engine red, to soft oranges, bright yellows, or simple browns.
Leaf peeping is a real thing, and a big tourist draw. Check out these live web cams showing realtime foliage.
Maybe leaf peeping could become a bit more competitive. What if you could rank locally-sourced trees by color, classifying them according to how close they are to a pure yellow, crimson, or orange hex color? Because Cloudinary gives you a way to quickly upload and moderate UGC (user-generated content) via its upload widget, analyzing color and gathering tags for each uploaded image, it seemed like a good way to signal that your neighborhood fall foliage is at its peak, right now, so come and peep!
Easy Moderated Uploading with a Widget
This app is built using Astro, and includes a handy upload widget, which you include by adding it to your index.astro file. This widget allows you to quickly upload batches of photos, great when you're walking and snapping pics.
<script src="https://upload-widget.cloudinary.com/latest/global/all.js" is:inline></script>
Add a few data points in your form, and upload your photos using an upload preset that's set to send photos to moderation queues. Admins can approve the pics to keep the data clean.
function openUploadWidget(treeType, neighborhood) {
return window.cloudinary.createUploadWidget(
...
form?.addEventListener('submit', (event) => {
event.preventDefault();
if (!form || !submitButton || !status || !treeTypeInput || !neighborhoodInput) return;
if (!form.reportValidity()) return;
if (!cloudName || !uploadPreset) {
status.textContent = 'Image uploads are not configured yet.';
return;
}
uploadedCount = 0;
failedCount = 0;
pendingFinalizations = [];
submitButton.disabled = true;
submitButton.textContent = 'Opening photo picker…';
status.textContent = '';
const widget = openUploadWidget(treeTypeInput.value.trim(), neighborhoodInput.value.trim());
widget.open();
});
The upload widget looks like this:
Those photos are fed to your upload preset, a prerequisite for an app built for image uploading. Set your upload preset, which functions as a 'landing slot' for your images in your account, to support moderation:
Then you can quickly set your images to go live by approving them in the moderation workflow:
Tags as Metadata
The images are uploaded via an upload preset that dumps all images into a /foliage folder with their tags. Leveraging tags in Cloudinary allows you to bypass the creation of a custom database, for simple data - a great technique when you want to add some context to your images for simple apps.
Color Us Beautiful: Scoring Trees with Cloudinary Predominant Color Detection
Cloudinary's predominant-color detection system is meant to power e-commerce apps so that your catalogue can be represented truthfully. But we can also use it to power our custom foliage scoring algorithm.
Each photo's palette comes back from Cloudinary as a list of hex colors found in a photo.
Rubric.mjs turns Cloudinary's predominant-color data into leaderboard scores. It has four parts.
- TARGETS defines the three leaderboards:
Each has a label, a display hex, and a list of Cloudinary color buckets it counts.
The
serializePredominant(predominant)function infinalize-upload.tsis used at upload time, turning Cloudinary's [['red', 50], ['pink', 9.8], ...] into a compact string like red:50.0,pink:9.8, which is stored in the asset's context metadata.The
parsePredominant(value)function inrubric.mjsis used when the gallery loads, infoliage.ts. It reverses the serialization and returns [] for missing or malformed values.The
scorePredominant(predominant, targetKey)function inrubric.mjsdoes the scoring.
Try Local Leaf and Upload Your Own Foliage
In a short time, you've built a nature-friendly app that allows all of us to admire your local foliage. I invite you to visit https://local-leaf.netlify.app/ and upload your foliage! Can you beat the glorious sugar maple from Commonwealth Avenue in Newton, MA? Let's see!
This app was inspired both by the glorious colors outside my window in October in New England, but also by this simple poem by Joyce Kilmer from 1913:
I think that I shall never see
A poem lovely as a tree.
A tree whose hungry mouth is prest
Against the earth's sweet flowing breast;
A tree that looks at God all day,
And lifts her leafy arms to pray;
A tree that may in Summer wear
A nest of robins in her hair;
Upon whose bosom snow has lain;
Who intimately lives with rain.
Poems are made by fools like me,
But only God can make a tree.
| Cloudinary ❤️ developers |
|---|
| Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today. |
| 👉 Create your free account |






Top comments (0)