<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jen Looper</title>
    <description>The latest articles on DEV Community by Jen Looper (@jenlooper).</description>
    <link>https://dev.to/jenlooper</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F9819%2Fd0d0dc5d-031b-43fe-85a4-469def492123.jpg</url>
      <title>DEV Community: Jen Looper</title>
      <link>https://dev.to/jenlooper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jenlooper"/>
    <language>en</language>
    <item>
      <title>Say It With Flowers: BouqAIs with the Tussie-Mussie Generator</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Sat, 09 May 2026 17:19:01 +0000</pubDate>
      <link>https://dev.to/cloudinary/say-it-with-flowers-bouqais-with-the-tussie-mussie-generator-3do0</link>
      <guid>https://dev.to/cloudinary/say-it-with-flowers-bouqais-with-the-tussie-mussie-generator-3do0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;&lt;a href="https://tussie-mussies.netlify.app" rel="noopener noreferrer"&gt;Tussie-Mussie Generator&lt;/a&gt;&lt;/strong&gt; is a web app for anyone who wants to send a meaningful floral e-card with an AI-generated "tussie mussie", a type of small nosegay. It uses the Victorian language of flowers to compose a bouquet, generates an image with Gemini, and sends it via Resend. This post covers &lt;br&gt;
a Mother's Day relaunch: fixing a broken email integration and swapping the AI image model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What changed in this relaunch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Migrated email sending from Mailgun to Resend, including a Cloudflare serverless function&lt;/li&gt;
&lt;li&gt;Fixed DNS configuration across Porkbun, Netlify, and Resend for a custom subdomain&lt;/li&gt;
&lt;li&gt;Replaced the previous image generator with Gemini for accurate tussie mussie generation&lt;/li&gt;
&lt;li&gt;Refactored the UI with Astro + Vue and impeccable.style for AI-assisted critique&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Have you ever wanted to build an e-card system that would allow you to send little ai-generated bouquets to your friends? No? Yes? Read on, gentle reader!&lt;/p&gt;

&lt;p&gt;Last year, I onboarded to my new job by building this sample app that lets you use the Victorian language of flowers to compose a bouquet. An image-heavy app like this is a great candidate for hosting and optimizing via Cloudinary, so all the flower images are stored there. An image of the composed bouquet is generated by Gemini, and then sent via Resend to the recipient of your choice. The app looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3w0zh47qr8wxul07kfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3w0zh47qr8wxul07kfk.png" alt="Tussie Mussie Generator" width="800" height="722"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the generated e-card looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hl2hu7bcummpftq8k7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hl2hu7bcummpftq8k7x.png" alt="demo" width="800" height="1245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I launched this app a year ago, and it's had an interesting lifespan. I wanted to relaunch it for Mother's Day and realized there was some refactoring to do! &lt;/p&gt;

&lt;p&gt;Here are a few of the gotchas I dealt with:&lt;/p&gt;

&lt;p&gt;Keeping the core: The basis of this app is its dataset, which I created a while ago on &lt;a href="https://www.kaggle.com/datasets/jenlooper/language-of-flowers" rel="noopener noreferrer"&gt;Kaggle&lt;/a&gt; as a useful version of the Victorian "Language of Flowers", scraped from the &lt;a href="https://www.almanac.com/flower-meanings-language-flowers#flower-meanings" rel="noopener noreferrer"&gt;Farmer's Almanac&lt;/a&gt;. Here's an example of what that looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5l8fjmwlta0yy1trhoa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5l8fjmwlta0yy1trhoa.jpg" alt="Almanac version of florilege" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your idea is centered around a solid dataset, you can't go wrong. Once I had the list, it took me a while to scrape images of the flowers in question and store them, optimized, on Cloudinary. But that work was done a year ago. So two things remained for the relaunch: refactoring the UI and fixing the bits that stopped working, namely the e-card generator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring the UI
&lt;/h2&gt;

&lt;p&gt;This app is built using my preferred stack, namely Astro + Vue. After a year, it was definitely time to upgrade, including fixing the tailwind integration which relied on an outdated package. Cursor made short work of that - it's one of the best uses of AI software agents.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: periodically ask your AI to plan the removal of any redundant files or code while you complete refactors. There are usually vestiges that can be deleted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used a wildly useful AI skill to refactor my admittedly basic UI: &lt;a href="https://impeccable.style/" rel="noopener noreferrer"&gt;impeccable.style&lt;/a&gt;. Install these skills on your machine and as you work with any AI generated UI suggestions, run &lt;code&gt;/impeccable critique&lt;/code&gt; to reality-check your work for taste and style. I'm now using impeccable on all my UIs - it also helped me tidy &lt;a href="https://jenlooper.com" rel="noopener noreferrer"&gt;my portfolio&lt;/a&gt;. The UI went from this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6luq0346nkg7qkrvbv2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6luq0346nkg7qkrvbv2.webp" alt="old UI" width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...to the UI shown above. I like it a lot. &lt;/p&gt;




&lt;h2&gt;
  
  
  Fixing the E-Card functionality
&lt;/h2&gt;

&lt;p&gt;This app caused me a horrible panic after launch last year, ruining an anniversary dinner, due to a kerfuffle with Mailgun, the original e-card sending mechanism. I was shocked by an enormous overage charge due to hacking of their systems, and I shut the entire thing down as fast as I could. To relaunch, I needed to find a new service to send email via API. Once again, Cursor to the rescue. &lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://resend.com/" rel="noopener noreferrer"&gt;Resend&lt;/a&gt;, a new email service that is much more solid than my previous choice. Let us hope that we have smooth sailing from now on! The integration includes a serverless function that you can host on Cloudflare, and works well as soon as you verify a domain. That last part took me the longest time - the gotcha is that since I bought the domain on Porkbun, I had to edit DNS records there to serve emails from a subdomain. The site is hosted on Netlify, so I had to build the subdomain there, and then the DNS verified on Resend. It's the kind of task that you don't do often, so it's easy to miss a step. But all is set now, and the emails are sending!&lt;/p&gt;

&lt;p&gt;I also had to reconsider how to build the AI generated bouquets. I'm out of credits on the service I previously chose to generate the bouquets, and they were never quite right anyway (generated as standard bouquets rather than true tussie mussies which have a silver filigree holder). It's crazy to see how AI has evolved for this esoteric imagery over the past year - now Gemini can accurately compose a tussie mussie in its holder, given a specific prompt.&lt;/p&gt;

&lt;p&gt;Enjoy these little bouquets! &lt;a href="https://tussie-mussies.netlify.app/" rel="noopener noreferrer"&gt;Send one to your Mom today&lt;/a&gt;!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://link.cloudinary.com/uoTiK" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>ai</category>
      <category>gemini</category>
      <category>astro</category>
      <category>vue</category>
    </item>
    <item>
      <title>How to Win a Hackathon</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Sun, 03 May 2026 03:43:08 +0000</pubDate>
      <link>https://dev.to/cloudinary/how-to-win-a-hackathon-1377</link>
      <guid>https://dev.to/cloudinary/how-to-win-a-hackathon-1377</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A sponsor’s perspective&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This blogpost is written on the heels of a few amazing weekends spent knee-deep in students in Toronto and Los Angeles at Hack Canada and LA Hacks, engaging almost 2000 students in person in total. Managing a sponsor track, I have some thoughts on good ways to present yourselves when angling your project towards a sponsor prize.&lt;/p&gt;

&lt;p&gt;For those not as familiar with how student hackathons work, they are usually comprised of an organized weekend populated by college undergrads (or older, or younger! high schoolers are increasingly getting into the mix). Over about 36 hours, students form teams and try to build software that meets a need, solves a problem, or proves a point. Some hackathons focus on themes around social good, like Hack Canada which challenged students to build something of special interest to Canada. Others have several themes and a full roster of sponsored options. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hackathons are a bastion of the cozy web! It’s a delight to see students embracing the freedom to create weird, useless, and wildly creative apps like AeroMaxx, a way to gauge influencers’ aerodynamic-maxxing (Taylor Swift is more aerodynamic than Clavicular, did you know?). LA Hacks even had a track embracing the “most questionable” hack, won by “Yes? Or Yes!”, a hack that had literal goldfish helping make decisions and trigger AI agents to do things like break up with a girl friend, quit a job, and post to social media. Great projects. Please keep building this kind of weird stuff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgn9ghxj1wt5pctpuhve0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgn9ghxj1wt5pctpuhve0.png" alt="MagByte" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a cozy interface for roommates to manage their shopping lists: &lt;a href="https://devpost.com/software/magbite?_gl=1*1nkfo64*_gcl_au*MjA0ODI2ODI1OC4xNzcyOTAyNTc4*_ga*Mzk1NTQ4NjAwLjE3NzI5MDI1Nzk.*_ga_0YHJK3Y10M*czE3Nzc3Nzc1MDMkbzM4JGcxJHQxNzc3Nzc3NjM5JGo0OCRsMCRoMA.." rel="noopener noreferrer"&gt;MagByte&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s a great moment to let your creativity run wild:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi55ce5tfipfpjajllj59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi55ce5tfipfpjajllj59.png" alt="goldfish q&amp;amp;a" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://devpost.com/software/yes-or-yes?_gl=1*nv0asj*_gcl_au*MjA0ODI2ODI1OC4xNzcyOTAyNTc4*_ga*Mzk1NTQ4NjAwLjE3NzI5MDI1Nzk.*_ga_0YHJK3Y10M*czE3Nzc3Nzc1MDMkbzM4JGcxJHQxNzc3Nzc4MTA2JGo1NiRsMCRoMA.." rel="noopener noreferrer"&gt;Yes? Or Yes!&lt;/a&gt; LA Hacks most unhinged hack winner - goldfish help you make decisions and then trigger agentic workflows. Good luck!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve been working the hackathon circuit as a developer advocate for at least ten years, including the mess during COVID, and the major difference nowadays between the earlier events is, unsurprisingly, the heavy use of AI tooling that both speeds up delivery, polishes the final product, and gets more software shipped, way faster. Instead of watching demo videos, judges can actively interact with an almost production-ready app, shockingly quickly.&lt;/p&gt;

&lt;p&gt;Still, there are some tips and tricks that I’d like to share based on a few recent observations of these very fun events. Here are five things to keep in mind as you go for a win!&lt;/p&gt;

&lt;h2&gt;
  
  
  Who’s it for?
&lt;/h2&gt;

&lt;p&gt;A lot of folks are attracted to social-good type projects, and that’s very laudable. I love them, personally, and tend to mark them highly in my judging rubric. I just want to caution hackathon participants against going after this vector with a “tech savior complex”. It’s easy to think that tech can solve all the things. And tech has made great strides on devices such as most smart phones to help people with various accessibility issues such as those who are blind, color blind, experience hearing loss, or are mobility-challenged. &lt;/p&gt;

&lt;p&gt;But if you are going to create a project for a given sector of users, it’s critical to come at these projects with an open mindset and humility, and to work with people who have these actual challenges. Working on an app for older people? Call your Grandma or Grandpa before you start building. It’s likely they can guide you to refining your app to make it much more useful.&lt;/p&gt;

&lt;p&gt;At Hack Canada, teams succeeded who spent time talking to local security guards as they built, to ensure that their safety-oriented hack would be useful. It’s all about finding your customer and/or user, and building backwards from that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power to the People
&lt;/h2&gt;

&lt;p&gt;Sponsors and mentors are often available to help you all the way through the event, so make use of them! Take some time before you start working to talk to sponsors and see if they can help you start to ideate. Learn about the various sponsors and what they are looking for. Some are looking for product feedback, some are hiring, others may have another agenda. &lt;/p&gt;

&lt;p&gt;Maybe you’ll find a product that you never heard of and will make a nice professional connection. Get your LinkedIn app ready to scan codes! This is a great moment to network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82424uizvh1gzcbpfr3z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82424uizvh1gzcbpfr3z.jpg" alt="Jen and Raya" width="582" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At your service at the booth!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Skill Up
&lt;/h2&gt;

&lt;p&gt;The use of AI tools has accelerated the build phase of a hackathon almost beyond recognition. When I was judging hackathons around 2016 or so, the projects produced were super shaky - often the hacker created a video at the moment that the app worked, and showed that to a judge as it was highly unlikely they could ever get it working again! This has all changed when AI has become such an important build partner.&lt;/p&gt;

&lt;p&gt;The use of AI, however, shifts the focus of a hackathon away from the software engineering tasks that now can be offloaded to agents (with supervision, of course!). Now, you need to spend a good amount of time getting set up to make your AI as successful and efficient as you can. Many vendors have created tools to help; we at Cloudinary produced a Skills Pack for this purpose: &lt;a href="https://github.com/cloudinary-devs/skills" rel="noopener noreferrer"&gt;https://github.com/cloudinary-devs/skills&lt;/a&gt;. Using tools such as these will effectively give official context to your app, preventing hallucinations and other wasting of time. &lt;/p&gt;

&lt;h2&gt;
  
  
  Sponsormaxxing and platformmaxxing
&lt;/h2&gt;

&lt;p&gt;There’s a trend towards “sponsormaxxing” - LA Hacks even had a track for this. The term refers to the incorporation of as many sponsors’ platforms as possible in a given hack. I think it’s a fun challenge, but there’s a risk: if you want to win a sponsor track, you’ll likely be judged on deep integration with their platform. &lt;/p&gt;

&lt;p&gt;In our case at Cloudinary, I’m looking for not just the use of the platform as a place to dump images and video, but a deep use of the APIs, for example optimizing and transforming images in an AI pipeline with the goal of constructing videos (as you can do with our winning hack from LA Hacks, StudyO!). Going for a sponsor track prize? Focus on deep integrations.&lt;/p&gt;

&lt;p&gt;Going deep, however, can also be risky! There’s the risk of “platformmaxxing” - using every bell and whistle of a platform to try it out. You may need to be a bit strategic here, as you might max out your credits by piling on as many platform aspects as you can. Watch out for signs of maxing out your credits and plan accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folgg9609kdf96demfwx8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folgg9609kdf96demfwx8.png" alt="AeroMaxx" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Speaking of maxxing: &lt;a href="https://devpost.com/software/aeromaxx?_gl=1*vb7ib8*_gcl_au*MjA0ODI2ODI1OC4xNzcyOTAyNTc4*_ga*Mzk1NTQ4NjAwLjE3NzI5MDI1Nzk.*_ga_0YHJK3Y10M*czE3Nzc3Nzc1MDMkbzM4JGcxJHQxNzc3Nzc3OTE0JGoxNiRsMCRoMA.." rel="noopener noreferrer"&gt;AeroMaxx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Perfect the Pitch
&lt;/h2&gt;

&lt;p&gt;Judges have only a few minutes per team so you need to make your best impression right away. Come ready to demo with your storytelling skills well in hand. Do some trial runs prior, and get feedback on your presentation skills. Lead with the use case, show the demo, and field questions. A good strategy for a 2-3 minute hackathon pitch is to focus on the problem you see, the solution you propose, and the impact you predict. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hook (15 seconds): Introduce yourself, state the problem you are solving, and share a relatable scenario or story.&lt;/li&gt;
&lt;li&gt;Demo (60-90 seconds): Walk the audience through your core feature&lt;/li&gt;
&lt;li&gt;Tech (30 seconds): Briefly explain the most impressive technical hurdle you overcame or the tech stack that powers the hack.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: Consider recording a video of your demo just in case there’s a horrible glitch, and practice getting over a glitchy demo. You can do it!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfusg6w07felvou9vje9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfusg6w07felvou9vje9.jpg" alt="pitch me" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pitching can be intense!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Winning a hackathon is a great goal, but don’t forget that being accepted into some of these selective hackathons, participating, and building a piece of software that you can be proud of is very laudable as well. Wishing you the best of luck! And maybe we will see you there.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://link.cloudinary.com/uoBac" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>career</category>
      <category>community</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>6 Free Cloudinary Courses That Teach You to Build Media-Optimized Apps</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Thu, 30 Apr 2026 18:33:51 +0000</pubDate>
      <link>https://dev.to/cloudinary/6-free-cloudinary-courses-that-teach-you-to-build-media-optimized-apps-51m2</link>
      <guid>https://dev.to/cloudinary/6-free-cloudinary-courses-that-teach-you-to-build-media-optimized-apps-51m2</guid>
      <description>&lt;p&gt;The Cloud to Crowd (C2C) curriculum is Cloudinary's free 6-course learning suite for developers who want to build and ship applications with production-quality image and video handling. It covers everything from Cloudinary basics to AI-powered transformations paired with hands-on projects at every step and a free certificate when you complete each course.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun fact: community member Jerome Hardaway of Vets Who Code, one of our nonprofit partners in the Creators Community program, coined the "Cloud to Crowd" term!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What You'll Be Able to Build After This Curriculum
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Upload, manage, and transform media assets using the Cloudinary API&lt;/li&gt;
&lt;li&gt;Optimize images and video for performance in a Next.js app&lt;/li&gt;
&lt;li&gt;Apply AI-powered features: background removal, generative fill, auto-tagging&lt;/li&gt;
&lt;li&gt;Use the Python SDK to automate media workflows on the backend&lt;/li&gt;
&lt;li&gt;Deliver video efficiently with format and quality auto-selection&lt;/li&gt;
&lt;li&gt;Ship a real portfolio project that demonstrates all of the above&lt;/li&gt;
&lt;li&gt;Earn a Cloudinary certificate and qualify for the Creators Community&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevy6pbfnmkb347ezgdgs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevy6pbfnmkb347ezgdgs.png" alt="Cloudinary Academy Courseware" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Built This
&lt;/h2&gt;

&lt;p&gt;Getting images and video right in a production app is harder than most tutorials suggest. Resize, format, optimize, deliver — each step has tradeoffs, and most learning resources skip the messy middle. The C2C courses are designed to fill that gap: structured, project-driven, and free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 6 Free Courses
&lt;/h2&gt;

&lt;p&gt;All courses are self-paced and free at &lt;a href="https://training.cloudinary.com/pages/c2c" rel="noopener noreferrer"&gt;https://training.cloudinary.com/pages/c2c&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Course 1: Media IQ for Developers
&lt;/h3&gt;

&lt;p&gt;Enroll: &lt;a href="https://training.cloudinary.com/learn/course/devrel-c2c-intro" rel="noopener noreferrer"&gt;https://training.cloudinary.com/learn/course/devrel-c2c-intro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The starting point for the first three courses in this suite. This course covers the core Cloudinary concepts: cloud name, API keys, the Media Library, and your first upload and transformation. No prior Cloudinary experience needed. By the end, you'll have a free account set up and understand how assets move through the Cloudinary pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose the right image formats for your use case, understanding when to use JPEG, PNG, WebP, AVIF, or SVG based on content type, browser support, and performance trade-offs&lt;/li&gt;
&lt;li&gt;Apply strategic optimization techniques including responsive images with automatic format/quality selection and intelligent cropping with gravity detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry0mgv63008yznpxadxa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry0mgv63008yznpxadxa.png" alt="Heavy Watch image" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Course 2: Media IQ for Developers with Next.js
&lt;/h3&gt;

&lt;p&gt;Enroll: &lt;a href="https://training.cloudinary.com/learn/course/devrel-c2c-next" rel="noopener noreferrer"&gt;https://training.cloudinary.com/learn/course/devrel-c2c-next&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The flagship course of the C2C curriculum. You'll build a storefront application (the "CapZone" e-commerce store) using Next.js and the Cloudinary Next.js SDK, applying real-world image optimization patterns throughout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build an image-optimized web application using Cloudinary to upload, store, transform, and deliver images on-the-fly through URL-based transformations and CDN delivery&lt;/li&gt;
&lt;li&gt;Apply strategic optimization techniques including responsive images with automatic format/quality selection and intelligent cropping with gravity detection&lt;/li&gt;
&lt;li&gt;Create Next.js components that handle image uploading, display optimized images with overlays and watermarks, and serve different sizes for different contexts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhpe6j2tmei2fq4ao40v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhpe6j2tmei2fq4ao40v.png" alt="CapZone store" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The kind of component you'll be writing by the end of this course:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CldImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next-cloudinary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductImage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;publicId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CldImage&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;publicId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;crop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"fill"&lt;/span&gt;
      &lt;span class="na"&gt;gravity&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt;
      &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt;
      &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Course 3: Media IQ for Developers with AI
&lt;/h3&gt;

&lt;p&gt;Enroll: &lt;a href="https://training.cloudinary.com/learn/course/devrel-c2c-ai" rel="noopener noreferrer"&gt;https://training.cloudinary.com/learn/course/devrel-c2c-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloudinary's AI-powered transformation features are some of its most practical and useful. This course covers the tools that save the most time in real projects: background removal, generative fill, object-aware cropping, and auto-tagging. This course follows the Next.js course, building AI into the CapZone store by adding a color picker to colorize the hats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove or replace backgrounds using e_background_removal&lt;/li&gt;
&lt;li&gt;Use generative fill to extend or recompose images&lt;/li&gt;
&lt;li&gt;Apply smart cropping with gravity: "auto" for face- and object-aware results&lt;/li&gt;
&lt;li&gt;Auto-tag assets using AI analysis to make large libraries searchable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4ryvwuokux6f54ai35k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4ryvwuokux6f54ai35k.png" alt="AI CapZone" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Course 4: Media IQ for Developers with Video
&lt;/h3&gt;

&lt;p&gt;Enroll: &lt;a href="https://training.cloudinary.com/learn/course/devrel-c2c-video" rel="noopener noreferrer"&gt;https://training.cloudinary.com/learn/course/devrel-c2c-video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Video is a different beast from images; you manage larger files, adaptive bitrates, more delivery complexity. This course covers the Cloudinary video pipeline from upload to playback. It's the third and final part of the progressive enhancement of the CapZone e-commerce web app that you started prior. In this course you'll add a video to one of the products.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload and transcode video using the Cloudinary API&lt;/li&gt;
&lt;li&gt;Apply video transformations: trim, resize, overlay, add subtitles&lt;/li&gt;
&lt;li&gt;Build playlists and seekbars with subtitles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xo1znkfbl48ywp9zu6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xo1znkfbl48ywp9zu6d.png" alt="Video with playlist on CapZone" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Course 5: Media IQ for Developers with Python
&lt;/h2&gt;

&lt;p&gt;For less JavaScript-focused developers, this course covers Cloudinary's Python SDK: uploading, managing, and transforming assets from any Python environment.&lt;br&gt;
Enroll: &lt;a href="https://training.cloudinary.com/learn/course/devrel-c2c-python" rel="noopener noreferrer"&gt;https://training.cloudinary.com/learn/course/devrel-c2c-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticate and configure the Python SDK&lt;/li&gt;
&lt;li&gt;Upload and tag assets for organization&lt;/li&gt;
&lt;li&gt;Build a small pet store app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq1f7brwa80h9bjk2p7yy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq1f7brwa80h9bjk2p7yy.png" alt="pet store app" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Course 6: Building a Developer Portfolio with Cloudinary and Next.js
&lt;/h2&gt;

&lt;p&gt;Enroll: &lt;a href="https://training.cloudinary.com/learn/course/devrel-c2c-portfolio" rel="noopener noreferrer"&gt;https://training.cloudinary.com/learn/course/devrel-c2c-portfolio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The capstone course. You'll apply everything from the earlier modules: upload, transformation, optimization, and AI features — to build a complete portfolio site using React and TypeScript that demonstrates your Cloudinary skills to employers. Focus on your own skills and show them off to the world in a media-rich website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You'll learn to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architect a media-rich portfolio app from scratch&lt;/li&gt;
&lt;li&gt;Combine multiple Cloudinary transformations into a polished UI&lt;/li&gt;
&lt;li&gt;Optimize for performance: lazy loading, responsive breakpoints, format auto-selection&lt;/li&gt;
&lt;li&gt;Deploy a production-ready app you can link from your resume&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4891ntoh6m30xoqdmsvh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4891ntoh6m30xoqdmsvh.png" alt="portfolio" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Who's this for?
&lt;/h2&gt;

&lt;p&gt;The C2C curriculum works for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Early-career developers who want structured, project-based learning beyond "hello world" tutorials&lt;/li&gt;
&lt;li&gt;Career changers building a portfolio they can point to during job interviews&lt;/li&gt;
&lt;li&gt;Frontend developers who've used Cloudinary but want to understand the optimization and AI layers&lt;/li&gt;
&lt;li&gt;Backend developers looking to add media handling to their Python projects&lt;/li&gt;
&lt;li&gt;Bootcamp graduates who want to go from tutorial-follower to someone who can build production media pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Enroll for Free
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to training.cloudinary.com/pages/c2c&lt;/li&gt;
&lt;li&gt;Create a free Cloudinary Academy account — you just need an email address&lt;/li&gt;
&lt;li&gt;Start with Course 1 or jump to the course that matches your current skill level&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All 6 courses are free. Each comes with a completion certificate. Finishing any course and passing its final assessment at 80%+ earns you a credential that qualifies you to apply to the Cloudinary Creators Community, a network with mentorship, Discord access, mini-hack events, and connections to developers worldwide.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Cloudinary Creators Community
&lt;/h2&gt;

&lt;p&gt;The Cloudinary Creators Community (CCC) is a selective, cohort-based program for developers who've completed the C2C curriculum. &lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access to private Discord channels with Cloudinary's Developer Relations team&lt;/li&gt;
&lt;li&gt;Monthly mini-hack challenges to apply and extend your skills&lt;/li&gt;
&lt;li&gt;Peer review and mentorship from a global network of developers&lt;/li&gt;
&lt;li&gt;Badges, certificates, and holopins with social media shout-outs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can join the Discord server now and participate in community activities even while you're working through the curriculum.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ready to start? → &lt;a href="//training.cloudinary.com/pages/c2c"&gt;training.cloudinary.com/pages/c2c&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This blogpost was crafted with the help of Claude. Banner image by Nano Banana.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://link.cloudinary.com/un3am" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Surviving as a Human in the Age of AI</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Tue, 31 Mar 2026 02:43:37 +0000</pubDate>
      <link>https://dev.to/jenlooper/surviving-as-a-human-in-the-age-of-ai-1p1b</link>
      <guid>https://dev.to/jenlooper/surviving-as-a-human-in-the-age-of-ai-1p1b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/wecoded-2026"&gt;2026 WeCoded Challenge&lt;/a&gt;: Echoes of Experience&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's a palpable feeling of anxiety in developer communities right now as concrete programming skills that we have painstakingly built either through study or experience appear to now be ... kaput. Outdated. Irrelevant. Passé. &lt;/p&gt;

&lt;p&gt;Andrej Karpathy described the feeling of watching his manual coding ability "slowly degenerating," as a personal sense of loss as AI tools take over coding work: "I've already noticed that I am slowly starting to atrophy my ability to write code manually".&lt;a href="https://x.com/karpathy/status/2015883857489522876?s=43" rel="noopener noreferrer"&gt;source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxz6l00imz99dsqmmmxfn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxz6l00imz99dsqmmmxfn.png" alt="Karpathy freaking out about coding on X" width="800" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ex-Google CEO Eric Schmitt expresses shock at watching AI zip through programming tasks that he used to have to hand-code: "I've been doing programming for 55 years. To see something something start and end in front of your own life is really profound." &lt;a href="http://timesofindia.indiatimes.com/articleshow/126304028.cms" rel="noopener noreferrer"&gt;source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers of all stripes are coming to the realization that being "just a coder" is no longer enough; new skills of systems thinking and architecture, plus that vague concept of 'taste' are starting to factor heavily in success in this industry. Students, as usual, are quickest to come to this realization, and Computer Science programs are rapidly either evolving or depopulating. Students are also feeling the brunt of this rapid change as narratives they were told as freshmen no longer hold true by the time they reach their senior year.&lt;/p&gt;

&lt;p&gt;It's a tough time to [just] code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo91j4ncgu47ujuuco8m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpo91j4ncgu47ujuuco8m.gif" alt="Kristen Bell laughing and crying" width="160" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Laughs in Humanities PhD. &lt;/p&gt;

&lt;p&gt;Plus ça change, plus c'est la même chose [The more things change, the more they remain the same]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A tale of two pathways
&lt;/h2&gt;

&lt;p&gt;Let me tell you a little story. It's the tale of someone who followed her heart her entire career.&lt;/p&gt;

&lt;p&gt;When I was 16, I went to France, and was swept away while visiting Chartres cathedral. True story. Growing up in a pretty privileged environment, with parents encouraging me to follow my dream, I studied for 6 years post-bachelors degree before achieving my PhD in French literature from Cal Berkeley in 1998. &lt;/p&gt;

&lt;p&gt;Even during my tenure in graduate school in the 90s, it was clear that Silicon Valley was the hub of some really exciting stuff and that a seismic shift was occurring in the dot-com-boom. But we in our ivory tower looked slightly askance at the fellow in Scandinavian Studies who ditched his PhD program to join a hot startup way back then. We were that confident that our skills would be valued. Anyway Scandinavian Studies is far less relevant than French Studies, everybody knows that.&lt;/p&gt;

&lt;p&gt;We of course didn't realize that humanities PhD programs in the languages are primarily designed to ensure a stream of cost-effective [read: crazy cheap] TAs (GSIs - graduate student instructors, as we called ourselves after unionizing). We were on the front lines of language learning, teaching a section of French 1 or 2 every day, coupled with mandatory pedagogy training, so that Cal undergrads could get through their language requirement. With the hope that we'd be able to graduate and land a tenure-track position, we put up with a lot, relying on this scanty income to keep food on the table and rent checks covered for a room in a West Berkeley two-storey.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here is some lore: that house on Roosevelt Ave had a can of peaches that had to have been a decade old, a gift from every successive wave of grad students who rented the house. I wonder if it's still there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most of us were unwilling to understand that the academic job market was weak and getting weaker by the year, although there were signs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijk63im6ql9gx4h13s8e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijk63im6ql9gx4h13s8e.jpg" alt="monk and dragon" width="408" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We &lt;em&gt;really&lt;/em&gt; didn't want to hear the gospel&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One wake-up call to me was watching a colleague and her husband, after graduating, accept &lt;em&gt;one&lt;/em&gt; teaching job between them. Another was watching another colleague getting thinner and thinner as he was quite literally going hungry to cover his family's expenses while part-time teaching.&lt;/p&gt;

&lt;p&gt;Unsurprisingly, given our blinders, the bottom falling out from what was left of the job market, and the other considerable headwinds (I see you, Adjuncting!), the academic job market kicked my rear. Within a few years I threw in the towel and retrained as a web developer, catching that dot-com-boom at its tail end, restarting from scratch. In those days, you could take courses in web design online from Macromedia University, an early training program, and find an entry-level job in a completely new industry.&lt;/p&gt;

&lt;p&gt;I worked my way up the corporate ladder (stories for another day) over the subsequent 25 years, but I won't say that I haven't yearned every day for what I gave up. Mourning the loss of a dream. Wondering "what might have been". Reconsidering the choice to pivot every time I hit a career bump, and being tempted to try to go back to some form of teaching. Coping with accusations of having sold out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ubi Sunt
&lt;/h2&gt;

&lt;p&gt;This long preamble is meant to emphasize that where you come from will most likely have very little relationship to where you are going in your career in the long run, especially in this fast-moving age of dramatic technical change - much faster and probably even more disruptive than the dot-com-boom of the early 2000s.&lt;/p&gt;

&lt;p&gt;The current anxiety and nostalgia permeating the tech discourse boils down to this tweet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdhtngrl4nsuxsny29cy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdhtngrl4nsuxsny29cy.jpg" alt="useless" width="800" height="955"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One benefit of having a background in a field other than where you wind up working is that you can lean on your previous knowledge base to bring insights to your work. Because really, there is nothing new here. The sentiment of loss and nostalgic mourning is explored over and over again in literature - the motif even has a name, 'Ubi sunt'. The 10th century poem The Wanderer expresses this trope with exquisite sadness:&lt;/p&gt;

&lt;p&gt;"Where is the horse gone? Where the rider? Where the giver of treasure?&lt;br&gt;
Where are the seats at the feast? Where are the revels in the hall?&lt;br&gt;
[...] How that time has passed away,&lt;br&gt;
grown dark under cover of night, as if it had never been."&lt;/p&gt;

&lt;p&gt;In a world grown old and dark, where is the greatness of our past? And was the past great at all, if it can disappear without a trace, as if it had never existed? &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8funcc6yxjvnosj6i11.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8funcc6yxjvnosj6i11.jpg" alt="The Wanderer manuscript, from the Exeter Book" width="492" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The 10th century manuscript containing The Wanderer, the &lt;a href="https://en.wikipedia.org/wiki/The_Wanderer_(Old_English_poem)" rel="noopener noreferrer"&gt;Exeter Book&lt;/a&gt;. The word "Eardsteppan" translates to "Wanderer", in the usual Old English "kenning" where two words are put together to refer to one thing. In this case the "earth stepper" is the wanderer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the 15th century in Middle French, François Villon borrows the Ubi Sunt trope to mourn the great ladies of the past, comparing them to those of the present day:&lt;/p&gt;

&lt;p&gt;"Where is the very wise Héloïse,&lt;br&gt;
For whom was castrated, and then made a monk,&lt;br&gt;
Peter Abelard in Saint-Denis?&lt;br&gt;
For his love he suffered this sentence.&lt;br&gt;
Similarly, where is the Queen&lt;br&gt;
Who ordered that Buridan&lt;br&gt;
Be thrown in a sack into the Seine?&lt;br&gt;
Oh, where are the snows of yesteryear!"&lt;/p&gt;

&lt;p&gt;Villon was a slippery character who had several run-ins with the law, and he seems to be not so much mourning the past as reminding us that returning to it might get you chucked into the Seine. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuhtma7pu3x4utwpo42v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuhtma7pu3x4utwpo42v.jpg" alt="print edition of Villon's Testament" width="800" height="1257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Student, poet, housebreaker" - an early print manuscript of Villon's works from 1489, in &lt;a href="https://data.bnf.fr/ark:/12148/cb119284140" rel="noopener noreferrer"&gt;Paris BNF&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Still, if 10th century Anglo Saxon poets dwelling in a much more uncomfortable world felt a profound sense of regret for a (probably) even more uncomfortable past, we in our ergonometric chairs battling Cursor also have the right to feel a degree of loss, a "slow degeneration" à la Karpathy. We can perhaps express ourselves using a literary trope that's over 1000 years old. But &lt;strong&gt;we ought to be able to put this anxiety into perspective&lt;/strong&gt;, as Villon insinuates that we should. This brings me to my second point.&lt;/p&gt;

&lt;h2&gt;
  
  
  All The Feels
&lt;/h2&gt;

&lt;p&gt;We have the right to feel all the feels that AI is making us feel - sad, useless, confused, stressed at its speed-of-light implementations, upset at the instability in the job market as we are threatened with AI-powered [sic] wave after wave of layoffs, worried for the next generation of early-career folks clawing their way up through the ranks in a very different world.&lt;/p&gt;

&lt;p&gt;But I would posit that &lt;strong&gt;we, the dispossessed diaspora of ex-Humanities academics, have something to contribute here&lt;/strong&gt;. We, too, trained for years only to be met with a job market that resolutely turned its back on us. And there isn't a day that I don't mourn that this happened, as I mentioned above. &lt;strong&gt;But I found ways to cope, and that has been to bring the skills of my own lived and learned experience to bear on an ever-evolving professional landscape&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One coping mechanism for me has been to attempt to bridge these two worlds by bringing the humanities into tech, because the lessons I learned there apply universally - such as those lessons around close reading, translating syntax, and &lt;strong&gt;the power of interdisciplinarity&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Interdisciplinarian
&lt;/h2&gt;

&lt;p&gt;Consider your past experience as a way to inform your present situation. In the near future, tech is going to look very different from how it does now. The job of the programmer will lean into more architecture than hand-coding. But your hard-won skills will still resonate in your day to day activities; rather than becoming obsolete, your programming skills will simply be applied in a different context. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You will have to lean into your accumulation of knowledge. Know that parts of it will apply, be ready to learn anew, and accept that the only thing that never changes is the fact that things will change.&lt;/strong&gt; Well, and also death. And probably taxes.&lt;/p&gt;

&lt;p&gt;As Emily Dickinson (whose poetry is well-studied &lt;a href="https://python.plainenglish.io/emily-dickinson-and-the-meter-of-mood-an-experiment-in-text-analysis-ff0f6efae290" rel="noopener noreferrer"&gt;from a data science context&lt;/a&gt;) well knew:&lt;/p&gt;

&lt;p&gt;All but Death can be&lt;br&gt;
Adjusted ;&lt;br&gt;
Dynasties repaired,&lt;br&gt;
Systems settled in their&lt;br&gt;
Sockets,&lt;br&gt;
Centuries removed, —&lt;/p&gt;

&lt;p&gt;Wastes of lives resown&lt;br&gt;
With colors&lt;br&gt;
By superior springs,&lt;br&gt;
Death — unto itself exception —&lt;br&gt;
Is exempt from change.&lt;/p&gt;

&lt;p&gt;-- &lt;a href="https://poets.org/poem/all-death-can-be-89" rel="noopener noreferrer"&gt;89&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To put a corporate stamp on it, the old exhortation to bring your whole self to work applies, now more than ever. The workplace has need of all of us with all of our interesting, strange, diverse, warty, emotional, and overwhelmingly human perspectives as our professions will be shaped increasingly by the collective that is AI. Embrace your interdisciplinarity, lean into it. I wish you great success. And please take care of yourself and each other.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>career</category>
      <category>wecoded</category>
    </item>
    <item>
      <title>Improve Web Performance: Image Formats, Responsive Images, and Core Web Vitals</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Wed, 11 Mar 2026 18:43:45 +0000</pubDate>
      <link>https://dev.to/cloudinary/your-images-are-probably-slowing-down-your-website-heres-how-to-fix-it-23je</link>
      <guid>https://dev.to/cloudinary/your-images-are-probably-slowing-down-your-website-heres-how-to-fix-it-23je</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Because images typically account for the majority of total page weight, this technical guide provides actionable strategies for web performance optimization. It details modern image formats like WebP and AVIF, implements responsive delivery via &lt;code&gt;srcset&lt;/code&gt;, establishes lazy loading best practices, and explains the impact of media on Core Web Vitals (LCP, CLS, and INP) for production-level development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What you’ll get
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;mental model&lt;/strong&gt;: how &lt;strong&gt;bytes&lt;/strong&gt; (file size) relate to what you &lt;em&gt;see&lt;/em&gt; (pixels on screen) and to &lt;strong&gt;LCP&lt;/strong&gt; / &lt;strong&gt;CLS&lt;/strong&gt; / &lt;strong&gt;INP&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;format cheat sheet&lt;/strong&gt; (photos, UI, icons, fallbacks) and when &lt;strong&gt;lossy&lt;/strong&gt; vs &lt;strong&gt;lossless&lt;/strong&gt; makes sense.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to lazy-load&lt;/strong&gt; (and when &lt;strong&gt;not&lt;/strong&gt; to—so you don’t hurt LCP).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three fixes to try first&lt;/strong&gt; on a real page (largest image, format mix, mobile percentiles).
&lt;/li&gt;
&lt;li&gt;How to use &lt;strong&gt;Cloudinary’s Web Speed Test&lt;/strong&gt; to turn gut feel into numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://link.cloudinary.com/umq4j" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The hidden performance problem on most websites
&lt;/h2&gt;

&lt;p&gt;This article explains how &lt;strong&gt;image bytes&lt;/strong&gt; affect &lt;strong&gt;LCP&lt;/strong&gt;, &lt;strong&gt;CLS&lt;/strong&gt;, and &lt;strong&gt;INP&lt;/strong&gt;, and what to change first.&lt;/p&gt;

&lt;p&gt;Open Chrome DevTools on almost any modern site and check the &lt;strong&gt;Network tab&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What you’ll usually see is something surprising:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Images dominate the payload.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The average homepage ships &lt;strong&gt;around 1 MB of images&lt;/strong&gt;, often &lt;strong&gt;more than JavaScript, CSS, and HTML combined&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.thoughtindustries.com%2Fcourse-uploads%2F4338ce4e-f809-4f5a-80f4-1d317c4a390d%2Fj0bb7waszgtt-Screenshot2025-11-25at12.31.09PM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.thoughtindustries.com%2Fcourse-uploads%2F4338ce4e-f809-4f5a-80f4-1d317c4a390d%2Fj0bb7waszgtt-Screenshot2025-11-25at12.31.09PM.png" alt="watches in a web site" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A super heavy page with a lot of big product images. Lazy loading and optimization would help here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That product page with 20 images?&lt;br&gt;
Each one is an opportunity to either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deliver a fast, polished experience&lt;/li&gt;
&lt;li&gt;Or frustrate users with slow loading and layout shifts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you care about &lt;strong&gt;Core Web Vitals, SEO, and user experience&lt;/strong&gt;, image optimization is one of the &lt;strong&gt;highest-impact improvements you can make&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was generated from our &lt;a href="https://link.cloudinary.com/umq4g" rel="noopener noreferrer"&gt;Cloud to Crowd: Media IQ with Next.js&lt;/a&gt; curriculum, built by Cloudinary Developer Relations. Go through this curriculum and pass the certification exam to qualify to become an official &lt;a href="https://link.cloudinary.com/umq4h" rel="noopener noreferrer"&gt;Cloudinary Creator&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Why images matter (and when they don’t)
&lt;/h2&gt;

&lt;p&gt;Humans process images much faster than text.&lt;/p&gt;

&lt;p&gt;A well-chosen image can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explain a product instantly&lt;/li&gt;
&lt;li&gt;Replace paragraphs of documentation&lt;/li&gt;
&lt;li&gt;Capture attention in fast-scrolling feeds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But images can also &lt;strong&gt;hurt your product experience&lt;/strong&gt; when used poorly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many images slow down page loads&lt;/li&gt;
&lt;li&gt;Poor cropping hides important information&lt;/li&gt;
&lt;li&gt;Large files damage &lt;strong&gt;Core Web Vitals&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Undisclosed AI or edited images reduce user trust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you need to follow this simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Right format + right size + smart delivery&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41mtd49vkcucf25n7lid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41mtd49vkcucf25n7lid.png" alt="Images in a correct format" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the way these images are delivered to the browser&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Images and Core Web Vitals
&lt;/h2&gt;

&lt;p&gt;Images heavily influence Google's &lt;strong&gt;Core Web Vitals&lt;/strong&gt;, particularly:&lt;/p&gt;
&lt;h3&gt;
  
  
  Largest Contentful Paint (LCP)
&lt;/h3&gt;

&lt;p&gt;Measures how long it takes for the &lt;strong&gt;largest visible element&lt;/strong&gt; on the page to load.&lt;/p&gt;

&lt;p&gt;This is often your &lt;strong&gt;hero image&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A good LCP target is under 2.5 seconds.&lt;/p&gt;
&lt;h3&gt;
  
  
  Cumulative Layout Shift (CLS)
&lt;/h3&gt;

&lt;p&gt;Images without defined dimensions can cause layout shifts while loading.&lt;/p&gt;
&lt;h3&gt;
  
  
  Interaction to Next Paint (INP)
&lt;/h3&gt;

&lt;p&gt;Heavy pages delay responsiveness.&lt;/p&gt;

&lt;p&gt;Optimizing images can dramatically improve &lt;strong&gt;all three metrics&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  The current state of images on the web
&lt;/h2&gt;

&lt;p&gt;Nearly &lt;strong&gt;every webpage (99.9%) loads at least one image&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Average number of images per page:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Avg Images&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Desktop&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Common formats used across the web:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;32.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;28.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GIF&lt;/td&gt;
&lt;td&gt;16.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;12%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG&lt;/td&gt;
&lt;td&gt;6.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;1%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;But these numbers reflect &lt;strong&gt;habit, not best practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Performance-focused teams are already shifting toward modern formats.&lt;/p&gt;

&lt;p&gt;Example data from optimized platforms shows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WebP&lt;/td&gt;
&lt;td&gt;49.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;td&gt;19.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AVIF&lt;/td&gt;
&lt;td&gt;13.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HEIC / PNG&lt;/td&gt;
&lt;td&gt;8.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The takeaway:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern image formats are replacing JPEG-first strategies.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Choosing the right image format
&lt;/h2&gt;

&lt;p&gt;Different formats solve different problems.&lt;/p&gt;
&lt;h3&gt;
  
  
  Lossy compression
&lt;/h3&gt;

&lt;p&gt;Reduces file size by permanently discarding some data.&lt;/p&gt;

&lt;p&gt;Formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JPEG&lt;/li&gt;
&lt;li&gt;WebP&lt;/li&gt;
&lt;li&gt;AVIF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Much smaller file sizes&lt;/li&gt;
&lt;li&gt;Ideal for photos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slight quality loss&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Lossless compression
&lt;/h3&gt;

&lt;p&gt;Reduces size &lt;strong&gt;without losing data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PNG&lt;/li&gt;
&lt;li&gt;SVG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perfect image quality&lt;/li&gt;
&lt;li&gt;Ideal for UI graphics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Larger file sizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7tu5adjaeuss92qfydpv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7tu5adjaeuss92qfydpv.png" alt="quality varying in images" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the difference between a lower res image vs JPEG XL&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  Quick developer cheat sheet
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;th&gt;Best format&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Photos&lt;/td&gt;
&lt;td&gt;WebP / AVIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graphics&lt;/td&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Icons&lt;/td&gt;
&lt;td&gt;SVG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy fallback&lt;/td&gt;
&lt;td&gt;JPEG&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Modern formats like &lt;strong&gt;WebP and AVIF can reduce file size by 40–60% compared to JPEG&lt;/strong&gt; while keeping similar visual quality.&lt;/p&gt;


&lt;h2&gt;
  
  
  Delivering images efficiently
&lt;/h2&gt;

&lt;p&gt;Choosing the right format is only part of the story.&lt;br&gt;
Delivery strategy matters just as much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloudinary&lt;/strong&gt; can automate &lt;strong&gt;format and size&lt;/strong&gt; selection for delivery so you’re not hand-tuning every URL. It helps you &lt;strong&gt;optimize, transform, and deliver&lt;/strong&gt; images for your users. See how on the &lt;a href="https://link.cloudinary.com/umq4i" rel="noopener noreferrer"&gt;Developers Hub&lt;/a&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  1. Use responsive images
&lt;/h3&gt;

&lt;p&gt;Don't force mobile users to download desktop-sized images.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero.avif"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/avif"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero.webp"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Product hero image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser automatically chooses the &lt;strong&gt;best supported format and size&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Use a CDN
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Content Delivery Network (CDN)&lt;/strong&gt; reduces the physical distance between your users and your images.&lt;/p&gt;

&lt;p&gt;Modern image CDNs can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize images automatically&lt;/li&gt;
&lt;li&gt;Convert formats (WebP / AVIF)&lt;/li&gt;
&lt;li&gt;Adjust compression&lt;/li&gt;
&lt;li&gt;Crop dynamically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows you to store &lt;strong&gt;one high-quality original&lt;/strong&gt; while serving optimized versions.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Lazy-load images (strategically)
&lt;/h3&gt;

&lt;p&gt;Lazy loading delays images until they approach the viewport.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"gallery.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Gallery image"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is one important rule:&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Never lazy-load above-the-fold images.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Doing so hurts &lt;strong&gt;Largest Contentful Paint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lazy loading should only be used for &lt;strong&gt;below-the-fold content&lt;/strong&gt;. Do not lazy-load the &lt;strong&gt;hero&lt;/strong&gt; or other &lt;strong&gt;above-the-fold&lt;/strong&gt; &lt;strong&gt;LCP&lt;/strong&gt; candidates.&lt;/p&gt;




&lt;h2&gt;
  
  
  Responsible image usage
&lt;/h2&gt;

&lt;p&gt;Performance isn't the only consideration.&lt;/p&gt;

&lt;p&gt;Developers should also use images &lt;strong&gt;ethically and accessibly&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Avoid misleading visuals
&lt;/h3&gt;

&lt;p&gt;Don't use edited or cropped images that misrepresent a product.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Disclose AI-generated images
&lt;/h3&gt;

&lt;p&gt;Transparency builds trust with users.&lt;br&gt;
The banner at the top of this article was generated using Nano Banana.&lt;/p&gt;


&lt;h3&gt;
  
  
  3. Make images accessible
&lt;/h3&gt;

&lt;p&gt;Always include descriptive alt text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"dashboard.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Analytics dashboard showing user growth trends"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Respect privacy and licensing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Check image licenses&lt;/li&gt;
&lt;li&gt;Get consent when photographing people&lt;/li&gt;
&lt;li&gt;Remove sensitive EXIF metadata&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. Balance aesthetics and performance
&lt;/h3&gt;

&lt;p&gt;A beautiful image that takes &lt;strong&gt;8 seconds to load&lt;/strong&gt; isn't beautiful.&lt;/p&gt;

&lt;p&gt;It's broken.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common image optimization myths
&lt;/h2&gt;

&lt;h3&gt;
  
  
  “A CDN replaces responsive images”
&lt;/h3&gt;

&lt;p&gt;False.&lt;/p&gt;

&lt;p&gt;Responsive images help the &lt;strong&gt;browser choose the correct size&lt;/strong&gt;, while CDNs deliver optimized assets.&lt;/p&gt;

&lt;p&gt;You need &lt;strong&gt;both&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  “More images mean more engagement”
&lt;/h3&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Images should &lt;strong&gt;help users make decisions&lt;/strong&gt;, not clutter the interface.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three practical tips for developers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start with your largest image
&lt;/h3&gt;

&lt;p&gt;Open &lt;strong&gt;DevTools → Network&lt;/strong&gt; and find the biggest image.&lt;/p&gt;

&lt;p&gt;Check if delivered size == display size.&lt;/p&gt;

&lt;p&gt;A common mistake: 3000px image displayed in a 600px container.&lt;/p&gt;

&lt;p&gt;That’s wasted bandwidth.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Measure your format mix
&lt;/h3&gt;

&lt;p&gt;Check what formats your pipeline actually delivers.&lt;/p&gt;

&lt;p&gt;If you're still mostly serving JPEG, there's likely a &lt;strong&gt;huge optimization opportunity&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Don’t assume mobile is optimized
&lt;/h3&gt;

&lt;p&gt;Mobile networks amplify performance problems.&lt;/p&gt;

&lt;p&gt;Check your &lt;strong&gt;75th and 90th percentile metrics&lt;/strong&gt;, not just averages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try this: Analyze a website’s image performance
&lt;/h2&gt;

&lt;p&gt;You can test any website using &lt;strong&gt;Cloudinary’s Web Speed Test&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="https://webspeedtest.cloudinary.com" rel="noopener noreferrer"&gt;https://webspeedtest.cloudinary.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then analyze:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance score&lt;/li&gt;
&lt;li&gt;Total image weight&lt;/li&gt;
&lt;li&gt;Largest Contentful Paint&lt;/li&gt;
&lt;li&gt;Potential size reductions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll often discover &lt;strong&gt;massive performance gains from simple fixes&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Images are often the &lt;strong&gt;largest performance lever on a webpage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you remember only three things:&lt;/p&gt;

&lt;p&gt;1️⃣ Optimize your &lt;strong&gt;largest image first&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
2️⃣ Use &lt;strong&gt;modern formats like WebP and AVIF&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
3️⃣ Deliver &lt;strong&gt;responsive images with proper sizing&lt;/strong&gt; and explicit dimensions when you can (helps &lt;strong&gt;CLS&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;Small improvements in image delivery can produce &lt;strong&gt;huge gains in performance and user experience&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What’s the biggest image optimization issue you’ve found on a website?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>frontend</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>DRY January: Demotivational Posters with the TanStack or Next.js</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Mon, 26 Jan 2026 18:18:58 +0000</pubDate>
      <link>https://dev.to/cloudinary/dry-january-demotivational-posters-with-the-tanstack-or-nextjs-5164</link>
      <guid>https://dev.to/cloudinary/dry-january-demotivational-posters-with-the-tanstack-or-nextjs-5164</guid>
      <description>&lt;p&gt;January can be a time when we make all the resolutions to do and be better in the shiny new year. We resolve to do more... more exercise, a more rigorous diet, even more mindfulness, doggone it. But what if we (and hear me out) instead thought about doing LESS. Less struggling against those 4PM sugar cravings, less fighting to not take an after-lunch nap, less battling frozen driveways to back the car out so you can make it to pilates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9qsh0vde33s9gh072fx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9qsh0vde33s9gh072fx.png" alt="I don't know if this is creepy or inspiring, but let's build it anyway" width="800" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't know if this is creepy or inspiring, but let's build it anyway&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What if we embraced our inner zen and simply...did the best we could? After all, isn’t all the productivity that AI is bestowing upon us freeing up our time to do less, rather than more? I’m only half-kidding here.&lt;/p&gt;

&lt;p&gt;To encourage us to embrace a reductionist mentality, I did a little experiment to see if I could rethink some popular messaging that I’m sure you encountered if you ever worked in an American corporate office in the early 2000s: motivational posters. &lt;/p&gt;

&lt;p&gt;These little gems were plastered on the walls to exhort us to Bring Our Best Selves To Work, Achieve More, and Be Bold. Here’s an example from the &lt;a href="https://www.successories.com/" rel="noopener noreferrer"&gt;“Successories” company&lt;/a&gt;: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65gl0x461ov0amz2fvpm.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F65gl0x461ov0amz2fvpm.webp" alt="Leadership Wolfs FTW" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, they have a particular format of a black background, an inspiring photo, an uplifting word with a lot of kerning, and a blurb at the bottom to drive the message home. A &lt;strong&gt;Whole Vibe&lt;/strong&gt; was created as you walked down a poster-adorned corridor in order to toss your bag lunch into the office fridge.&lt;/p&gt;

&lt;p&gt;I particularly like this wolf. This is me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gsnex7pigdpp8c2tgds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gsnex7pigdpp8c2tgds.png" alt="skeptical wolf" width="578" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even back in those days, people made fun of these posters, and I remember being employed in one company packed with sarcastic Eastern Europeans that was instead decorated with &lt;strong&gt;&lt;em&gt;demotivational&lt;/em&gt;&lt;/strong&gt; posters such as those crafted by the brilliant &lt;a href="https://despair.com/" rel="noopener noreferrer"&gt;Despair.inc&lt;/a&gt;. Here’s a good one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3htoxtakrayhn6zsyn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3htoxtakrayhn6zsyn0.png" alt="lewwwwwsers" width="790" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem with all of these posters is that, well, you have to buy them, and that’s no fun. So let’s see if we can build something like this ourselves, and actually make it a more surprising experience by connecting two APIs to generate shady messaging like this at random. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74uean0wyf2ne26v842q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74uean0wyf2ne26v842q.png" alt="You Got This fr fr" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;not sure what 'this' is, but you got it!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Temporarily shelve that resolution against unproductive and negative thinking and let’s see what we can build using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Affirmations API &lt;/li&gt;
&lt;li&gt;Unsplash API&lt;/li&gt;
&lt;li&gt;TanStack for a web frontend&lt;/li&gt;
&lt;li&gt;Cloudinary image storage to display the image so you can print off a PDF of your poster&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You'll need two API keys, one for the ever-useful affirmations.dev API and one for Unsplash images. You'll also need a Cloudinary account, so &lt;a href="https://cloudinary.com?utm_campaign=5266-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=dry-january" rel="noopener noreferrer"&gt;create one for free here&lt;/a&gt; if you aren't already setup. You then need to gather your Cloudinary API key, secret, cloud name and build an &lt;strong&gt;upload preset&lt;/strong&gt; so that you can upload images neatly into Cloudinary. Learn how to get credentials &lt;a href="https://cloudinary.com/documentation/developer_onboarding_faq_find_credentials?utm_campaign=5266-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=dry-january#banner" rel="noopener noreferrer"&gt;here&lt;/a&gt; and how to create an upload preset &lt;a href="https://cloudinary.com/documentation/upload_presets?utm_campaign=5266-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=dry-january#creating_and_managing_upload_presets" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’re going to grab one of the pithy affirmations from the API, extract the longest word as the central message to display with plenty of kerning, and then send that word to Unsplash to find a match. Store the image returned in Cloudinary and display the lot a as a printable poster, as a stacked image, word, and affirmation on a black background, like this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F88v2nxoyha0hgf9uywip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F88v2nxoyha0hgf9uywip.png" alt=" " width="800" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The miracle of survival&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Continuing my tradition of building useless things to try new stacks, let’s give &lt;a href="https://tanstack.com/" rel="noopener noreferrer"&gt;TANStack&lt;/a&gt; a whirl. TanStack is a React framework that's pitched as a less 'magical' alternative to Next.js. I also built this same app using Next.js, to compare the two codebases, for learning purposes. Check out the GitHub repo with the two apps &lt;a href="https://github.com/jlooper/affirmation-posters" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure; I used Cursor to help build the two comparable apps in the demo repo. According to Cursor, the difference between the two boils down to your personal dev preference: "Next.js is a full-stack framework with conventions and a large ecosystem. TanStack Router/Start is a type-safe, flexible routing solution that can be extended to full-stack. The choice often comes down to preferring conventions (Next.js) vs. flexibility and type safety (TanStack)."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some differences between these two frameworks in the context of this app include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-side data fetching architecture
&lt;/h3&gt;

&lt;p&gt;Next.js:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses Server Actions ('use server') and async Server Components&lt;/li&gt;
&lt;li&gt;Server actions in actions.ts are callable from both server and client
TanStack:&lt;/li&gt;
&lt;li&gt;Uses route loaders and createServerFn for server functions&lt;/li&gt;
&lt;li&gt;Data fetching happens in the route's loader function&lt;/li&gt;
&lt;li&gt;Loaders run on the server before the component renders&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Environment variable access
&lt;/h3&gt;

&lt;p&gt;Next.js:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses process.env.* for environment variables&lt;/li&gt;
&lt;li&gt;Variables are available on the server by default
TanStack:&lt;/li&gt;
&lt;li&gt;Uses import.meta.env.VITE_* (Vite convention)&lt;/li&gt;
&lt;li&gt;Only variables prefixed with VITE_ are exposed to the client
buildCloudinaryUrl.ts, because this app was built with Vite as its build tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Difference in image handling
&lt;/h3&gt;

&lt;p&gt;Next.js:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images are displayed using the built-in optimized  component 
TanStack:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TanStack doesn't have such a component built-in, so you need to make sure to optimize your images! This is consistent with its 'magic-free' approach.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Guess what! You can easily optimize your images in Cloudinary. While there are &lt;a href="https://cloudinary.com/blog/how-to-build-a-tanstack-start-project-for-image-optimization-and-uploading?utm_campaign=5266-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=dry-january" rel="noopener noreferrer"&gt;other ways to do this&lt;/a&gt;, I decided to just add some URL transformations to the Cloudinary URL returned once the Unsplash image is uploaded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function buildCloudinaryImageUrl(publicId: string): string {
  const cloudName = import.meta.env.VITE_CLOUDINARY_CLOUD_NAME

  if (!cloudName) {
    throw new Error('Cloudinary cloud name not configured')
  }

  const plainPublicId = publicId

  const transformations = [
    `c_fill,w_1200,h_800`, // Fill to 1200x800 for poster feel
    `f_auto`, // Auto format
    `q_auto`, // Auto quality
  ].join('/')

  // Return the complete Cloudinary URL with transformations `https://res.cloudinary.com/${cloudName}/image/upload/${transformations}/${plainPublicId}`
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're able to grab an affirmation from the API and use it to query Unsplash, storing the result into Cloudinary and using it to build your poster. In TANStack it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const fetchNewAffirmationData = createServerFn({
  method: 'GET',
}).handler(async (): Promise&amp;lt;AffirmationData&amp;gt; =&amp;gt; {
  // First fetch the affirmation
  const affirmationData = await getAffirmation()

  // Extract the longest word from the affirmation to use as image search query
  const words = affirmationData.affirmation.split(' ').filter(word =&amp;gt; word.length &amp;gt; 0)
  const longestWord = words.reduce((longest, current) =&amp;gt; 
    current.length &amp;gt; longest.length ? current : longest, ''
  ).toLowerCase()

  // Fetch an image based on the longest word
  const accessKey = import.meta.env.VITE_UNSPLASH_ACCESS_KEY
  if (!accessKey) {
    throw new Error('Unsplash access key not configured')
  }

  const unsplashResponse = await fetch(
    `https://api.unsplash.com/photos/random?client_id=${accessKey}&amp;amp;orientation=landscape&amp;amp;query=${encodeURIComponent(longestWord)}`
  )
  if (!unsplashResponse.ok) {
    throw new Error('Failed to fetch Unsplash photo')
  }
  const unsplashData = await unsplashResponse.json() as { id: string; urls: { full: string } }

  // Upload the Unsplash image to Cloudinary
  const publicId = await uploadToCloudinary(unsplashData.urls.full)

  // Build the Cloudinary URL with transformations
  const cloudinaryUrl = buildCloudinaryImageUrl(publicId)

  return {
    affirmation: affirmationData.affirmation,
    longestWord,
    cloudinaryUrl,
    photoId: unsplashData.id,
    publicId,
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And once you have all your pieces in place, you'll be able to view that matching affirmation, image, and printable styling all in one place so you can build a PDF poster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handlePrint = () =&amp;gt; {
    if (posterRef.current) {
      const printWindow = window.open('', '_blank')
      if (printWindow) {
        printWindow.document.write(`
          &amp;lt;!DOCTYPE html&amp;gt;
          &amp;lt;html&amp;gt;
            &amp;lt;head&amp;gt;
              &amp;lt;title&amp;gt;Affirmation Poster&amp;lt;/title&amp;gt;
              &amp;lt;style&amp;gt;
                ...some fancy styling
              &amp;lt;/style&amp;gt;
            &amp;lt;/head&amp;gt;
            &amp;lt;body&amp;gt;
              &amp;lt;div class="poster-container"&amp;gt;
                &amp;lt;img src="${imageUrl}" alt="${affirmation}" class="poster-image" /&amp;gt;
                &amp;lt;h1&amp;gt;${longestWordWithDots}&amp;lt;/h1&amp;gt;
                &amp;lt;div class="poster-line"&amp;gt;&amp;lt;/div&amp;gt;
                &amp;lt;h2&amp;gt;${affirmation}&amp;lt;/h2&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/body&amp;gt;
          &amp;lt;/html&amp;gt;
        `)
        printWindow.document.close()

        // Wait for image to load before printing
        setTimeout(() =&amp;gt; {
          printWindow.focus()
          printWindow.print()
          printWindow.onafterprint = () =&amp;gt; printWindow.close()
        }, 250)
      }
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So there you have it...you've built a delightfully useless little app that combines a few API calls with optimized image presentation to make you feel a little less seasonally-affected, we hope. &lt;/p&gt;

&lt;p&gt;Happy New Year! If you liked this little app, there are plenty more where it comes from from your friends at Cloudinary Developer Relations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcjllxeu58jo1thwi6z5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcjllxeu58jo1thwi6z5.png" alt="In boca leone" width="800" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=5266-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=dry-january" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>fullstack</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Build Holiday Card Collages with One Line of Code</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Thu, 04 Dec 2025 14:48:59 +0000</pubDate>
      <link>https://dev.to/cloudinary/build-holiday-card-collages-with-one-line-of-code-3cp5</link>
      <guid>https://dev.to/cloudinary/build-holiday-card-collages-with-one-line-of-code-3cp5</guid>
      <description>&lt;p&gt;In this article, I'm not going to show you much code. Instead, I'm going to show you how you can build a holiday card collage, complete with a ribbon footer with text, a background, and 5 styled photos with rounded, colored borders &lt;strong&gt;in &lt;em&gt;one line&lt;/em&gt;&lt;/strong&gt; using the magic of Cloudinary's transformations. &lt;/p&gt;

&lt;p&gt;This is way cool, so buckle up and let me show you how I built this URL-generating app for your holiday card-sending needs. You can try it right now &lt;a href="https://photocardmaker.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;; it generates cards that look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqna10jwiurvmzdb9d5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqna10jwiurvmzdb9d5f.png" alt=" " width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Maybe this tool will even save you some money as printing photo-quality holiday cards can get expensive! &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Build an app, any app
&lt;/h2&gt;

&lt;p&gt;I have been enjoying building Astro apps, and, let's face it, using Cursor makes architecting this sort of thing a real breeze. Use your favorite AI tool to craft an app that will allow you to upload five photos to Cloudinary, rearrange them, and generate a URL to build the holiday card. &lt;/p&gt;

&lt;p&gt;💡 Here's a tip. If you are looking to quickly scaffold an app via prompting in Cursor or your IDE of choice, you can get better results by using two tools: ChatGPT to build the prompt, and Cursor to execute it.&lt;/p&gt;

&lt;p&gt;My initial lazy half-baked idea sent over to ChatGPT:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;what kind of demo could I build to create a holiday photo card maker for cloudinary&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ChatGPT, of course, thought I wanted it to build an app for me, and went straight to scaffolding a Next.js app with code everywhere. A few clarifications later, after requesting Astro for use in Cursor...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;create this as a prompt I can give to cursor&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;...ChatGPT generated a really nice, detailed prompt ready for building which you can read in full &lt;a href="https://gist.github.com/jlooper/cf5e18996ce86d00b5393de25fb0b017" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By having this kind of very detailed prompt, Cursor is able to build a perfectly reasonable app on the first try. Then it's up to the engineer to tweak it, redesign it, and add elements while keeping the core functionality of uploading and URL-building intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add some extras and get ready to upload
&lt;/h2&gt;

&lt;p&gt;I went ahead and changed the app colors for a wintry, cozy look, adding some falling snow, a popup elf with changing holiday messages (can you find him?), glowing lights, and a candy cane border, mostly borrowed from &lt;a href="https://codepen.io/alvaromontoro/pen/xxXrzqj" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt;. Just because we use AI doesn't mean we can't continue to make interesting interfaces! And AI can help you do that, too. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyemqooblxuwb5a5bajg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyemqooblxuwb5a5bajg1.png" alt="The app's top" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After those fun things are complete, you can start making sure that you're set up to use Cloudinary's image upload and image transformation capabilities. To make this work, you need to ensure that you have some environment variables set up. Create an account on &lt;a href="https://cloudinary.com?utm_source=dev-dot-to&amp;amp;utm_content=holiday-card" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; (there's a generous free tier) and grab your API keys from the console by clicking the "⚙️" gear icon in the left nav and selecting 'API Keys':&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fou05wjbtcfrvkec1ctae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fou05wjbtcfrvkec1ctae.png" alt="Finding your API keys in Cloudinary" width="800" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You want to add those keys to your .env file locally, and then make sure they're available on your hosting service when you push your app to the cloud. I use Netlify so I add these keys into the Netlify console before publishing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUBLIC_CLOUDINARY_CLOUD_NAME=&amp;lt;your cloud name&amp;gt;
PUBLIC_CLOUDINARY_UPLOAD_PRESET=christmas-collage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This app also needs what's called an 'Upload Preset', which is essentially a placeholder that helps your app figure out where your uploaded images should go. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up that preset by clicking the 'Uploads' navigation link that's right under the 'API Keys' navigation on the left. This will let you set up an unsigned preset. &lt;/li&gt;
&lt;li&gt;Call it 'christmas-collage' (or something else, and make sure to update your app). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c1jom2vo9t8s849muat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c1jom2vo9t8s849muat.png" alt="Upload Preset area" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you have a folder set up by clicking &lt;code&gt;Assets &amp;gt; folders&lt;/code&gt; on the left nav in the Cloudinary console. Call this folder 'collages'. &lt;/li&gt;
&lt;li&gt;Also create a folder called 'holiday-assets' and add a collage background image and a background image for your ribbon element on the card. I used a white pixel image and a fancy holiday background like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fbeanpot-studio%2Fimage%2Fupload%2Fv1763602104%2Fholiday-assets%2Fcollage-bg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fbeanpot-studio%2Fimage%2Fupload%2Fv1763602104%2Fholiday-assets%2Fcollage-bg.jpg" alt="Background" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jeshoots?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;JESHOOTS.COM&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/assorted-christmas-ornaments-7VOyZ0-iO0o?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Watch the URL builder work
&lt;/h2&gt;

&lt;p&gt;Now here's the interesting bit. Once you're done messing with your interface to make it look cute, take a look at the very clever way that your card is generated. First, you upload a series of 5 photos of your family to the app, and the interface lets you rearrange them into the order in the card that you want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qzl7l1ed0m6jt4m67c6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qzl7l1ed0m6jt4m67c6.png" alt="uploading images for the card" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;True story, my daughter asked me what the difference is between this and PicCollage, the answer being "Mom made it!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The URL that is generated, packed with Cloudinary image transformations, looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://res.cloudinary.com/jen-demos/image/upload/w_1600,h_900,c_fill,q_auto,f_auto
/l_holiday-assets:jhi9cpio4ahxomhagwvs/c_fill,w_473,h_680/r_25,bo_8px_solid_rgb:FFD700/fl_layer_apply,g_north_west,x_50,y_50
/l_holiday-assets:d9njoekpa1zzzepy2y5d/c_fill,w_473,h_426/r_25,bo_8px_solid_rgb:FFD700/fl_layer_apply,g_north_west,x_563,y_50
/l_holiday-assets:nm9i3sjh6c3mkfj0ari1/c_fill,w_473,h_214/r_25,bo_8px_solid_rgb:FFD700/fl_layer_apply,g_north_west,x_563,y_516
/l_holiday-assets:rg0c1ul7ux1gcgl8c2lr/c_fill,w_473,h_214/r_25,bo_8px_solid_rgb:FFD700/fl_layer_apply,g_north_west,x_1076,y_50
/l_holiday-assets:d0brmcfuqfyzwtelsiyt/c_fill,w_473,h_426/r_25,bo_8px_solid_rgb:FFD700/fl_layer_apply,g_north_west,x_1076,y_304
/l_holiday-assets:white-pixel/c_fill,w_1600,h_100/o_70/fl_layer_apply,g_south,y_20
/l_text:Pacifico_70:Our%20Family%20-%20Holiday%202025,co_rgb:000000/fl_layer_apply,g_center,y_380
/holiday-assets/collage-bg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, that one line created this card:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fjen-demos%2Fimage%2Fupload%2Fw_1600%2Ch_900%2Cc_fill%2Cq_auto%2Cf_auto%2Fl_holiday-assets%3Ajhi9cpio4ahxomhagwvs%2Fc_fill%2Cw_473%2Ch_680%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_50%2Cy_50%2Fl_holiday-assets%3Ad9njoekpa1zzzepy2y5d%2Fc_fill%2Cw_473%2Ch_426%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_563%2Cy_50%2Fl_holiday-assets%3Anm9i3sjh6c3mkfj0ari1%2Fc_fill%2Cw_473%2Ch_214%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_563%2Cy_516%2Fl_holiday-assets%3Arg0c1ul7ux1gcgl8c2lr%2Fc_fill%2Cw_473%2Ch_214%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_1076%2Cy_50%2Fl_holiday-assets%3Ad0brmcfuqfyzwtelsiyt%2Fc_fill%2Cw_473%2Ch_426%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_1076%2Cy_304%2Fl_holiday-assets%3Awhite-pixel%2Fc_fill%2Cw_1600%2Ch_100%2Fo_70%2Ffl_layer_apply%2Cg_south%2Cy_20%2Fl_text%3APacifico_70%3AOur%2520Family%2520-%2520Holiday%25202025%2Cco_rgb%3A000000%2Ffl_layer_apply%2Cg_center%2Cy_380%2Fholiday-assets%2Fcollage-bg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fjen-demos%2Fimage%2Fupload%2Fw_1600%2Ch_900%2Cc_fill%2Cq_auto%2Cf_auto%2Fl_holiday-assets%3Ajhi9cpio4ahxomhagwvs%2Fc_fill%2Cw_473%2Ch_680%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_50%2Cy_50%2Fl_holiday-assets%3Ad9njoekpa1zzzepy2y5d%2Fc_fill%2Cw_473%2Ch_426%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_563%2Cy_50%2Fl_holiday-assets%3Anm9i3sjh6c3mkfj0ari1%2Fc_fill%2Cw_473%2Ch_214%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_563%2Cy_516%2Fl_holiday-assets%3Arg0c1ul7ux1gcgl8c2lr%2Fc_fill%2Cw_473%2Ch_214%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_1076%2Cy_50%2Fl_holiday-assets%3Ad0brmcfuqfyzwtelsiyt%2Fc_fill%2Cw_473%2Ch_426%2Fr_25%2Cbo_8px_solid_rgb%3AFFD700%2Ffl_layer_apply%2Cg_north_west%2Cx_1076%2Cy_304%2Fl_holiday-assets%3Awhite-pixel%2Fc_fill%2Cw_1600%2Ch_100%2Fo_70%2Ffl_layer_apply%2Cg_south%2Cy_20%2Fl_text%3APacifico_70%3AOur%2520Family%2520-%2520Holiday%25202025%2Cco_rgb%3A000000%2Ffl_layer_apply%2Cg_center%2Cy_380%2Fholiday-assets%2Fcollage-bg" alt="Photo Card" width="1600" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's break down that one-liner. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Set up the base “card” background:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.../image/upload/w_1600,h_900,c_fill,q_auto,f_auto/ ... /holiday-assets/collage-bg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;w_1600,h_900&lt;/code&gt; – make the final image 1600×900.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c_fill&lt;/code&gt; – crop/resize to fill that aspect ratio.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q_auto,f_auto&lt;/code&gt; – optimize quality and format automatically (WebP/AVIF/etc).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;holiday-assets/collage-bg&lt;/code&gt; – this is the base background image for the card.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Add the first photo (top left)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/l_holiday-assets:uzfzkx8d5xd0jr1jxzyo/c_fill,w_473,h_680
/r_25,bo_8px_solid_rgb:FFD700/fl_layer_apply,g_north_west,x_50,y_50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l_holiday-assets:...&lt;/code&gt; – load this image as a layer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c_fill,w_473,h_680&lt;/code&gt; – size it to 473×680, cropping to fill.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;r_25&lt;/code&gt; – rounded corners (radius 25).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bo_8px_solid_rgb:FFD700&lt;/code&gt; – 8px solid gold (#FFD700) border.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fl_layer_apply,g_north_west,x_50,y_50&lt;/code&gt; – apply the layer at the top-left, offset 50px from the top and left.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the remaining images, some taller than others and placed in different areas of the card.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add a semi-transparent footer bar
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/l_holiday-assets:white-pixel/c_fill,w_1600,h_100/o_70
/fl_layer_apply,g_south,y_20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bar uses a white-pixel asset as a tiny base and stretches it to &lt;code&gt;w_1600,h_100&lt;/code&gt; to form a strip which is &lt;code&gt;o_70&lt;/code&gt; – 70% opacity (semi-transparent). It's then applied at the bottom (&lt;code&gt;g_south&lt;/code&gt;) with a small vertical offset (&lt;code&gt;y_20&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Finally, add the holiday greeting text
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/l_text:Pacifico_70:Our%20Family%20-%20Holiday%202025,co_rgb:000000
/fl_layer_apply,g_center,y_380
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l_text:Pacifico_70:...&lt;/code&gt; – create a text layer with Font: Pacifico in size: 70. Give it the text: &lt;code&gt;Our Family - Holiday 2025&lt;/code&gt; with &lt;code&gt;co_rgb:000000&lt;/code&gt; – black text color.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fl_layer_apply,g_center,y_380&lt;/code&gt; – center the text horizontally and shift it vertically to overlay the footer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, this monster URL &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;starts with a festive background&lt;/li&gt;
&lt;li&gt;lays out five photos in a collage with rounded corners and gold frames&lt;/li&gt;
&lt;li&gt;adds a semi-transparent white bar at the bottom&lt;/li&gt;
&lt;li&gt;and writes “Our Family - Holiday 2025” in a script font on top of that bar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...rendering the whole card on demand in a single Cloudinary transformation URL. Really nice!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: you can make edits right in the URL to change elements on the card - try adding your own family name and changing the border color.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Enjoy the results
&lt;/h2&gt;

&lt;p&gt;You could save this image and print it for snail mail, or send it right away via email to the folks who are eager to hear from you this holiday season. And you did it in one line. That's awesome!&lt;/p&gt;

&lt;p&gt;Try this in &lt;a href="https://cloudinary.com?utm_source=dev-dot-to&amp;amp;utm_content=holiday-card" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; today, and get one more item checked off your holiday to-do list. Learn more about image transformations &lt;a href="https://cloudinary.com/documentation/image_transformations?utm_source=dev-dot-to&amp;amp;utm_content=holiday-card" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Happy holidays from Cloudinary Developer Relations to you.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=holiday-card" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>astro</category>
      <category>react</category>
      <category>codepen</category>
    </item>
    <item>
      <title>Clara Denari: Learn Cloudinary Image Transformations Through a Boston Mystery Game</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Tue, 30 Sep 2025 20:51:16 +0000</pubDate>
      <link>https://dev.to/cloudinary/clara-denari-and-the-mysterious-transformations-a-new-way-to-explore-cloudinary-57od</link>
      <guid>https://dev.to/cloudinary/clara-denari-and-the-mysterious-transformations-a-new-way-to-explore-cloudinary-57od</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Excerpt:&lt;/strong&gt; Clara Denari is a browser game for developers who want hands-on practice with Cloudinary image transforms, C2PA-style provenance, and multi-language support—set in a Boston mystery. It replaces long tutorials with short labs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  At a glance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Five challenges&lt;/strong&gt;—each one forces you to use the transform pipeline, not just read about it.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quizzes and a &lt;a href="https://www.holopin.io/@cloudinary" rel="noopener noreferrer"&gt;Holopin&lt;/a&gt; badge&lt;/strong&gt; when you show you’ve learned the ropes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Four languages&lt;/strong&gt; (English, French, Spanish, and Brazilian Portuguese).
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;free &lt;a href="https://cloudinary.com?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=claradenari" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt;&lt;/strong&gt; account for the embedded labs (add your &lt;strong&gt;cloud name&lt;/strong&gt; and image &lt;strong&gt;public ID&lt;/strong&gt; in the Lab to experiment).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Credentials (C2PA-style)&lt;/strong&gt; so you can inspect an image’s history as it changes through its lifecycle.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tired of plowing through long tutorials? Done with 🔥&lt;strong&gt;Tutorial Hell&lt;/strong&gt;🔥? This is &lt;strong&gt;gamified, hands-on Cloudinary training&lt;/strong&gt;—a mystery first, a lab second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gameplay loop
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Clara Denari&lt;/strong&gt; is a narrative game that teaches &lt;strong&gt;Cloudinary image transformations&lt;/strong&gt;: you solve clues, clean string artifacts, brighten an image to reveal hidden text, and use &lt;strong&gt;image refiners&lt;/strong&gt; in short embedded labs, with quizzes and a Holopin at the end. We built a narrative game you can play at &lt;strong&gt;&lt;a href="https://claradenari.com" rel="noopener noreferrer"&gt;claradenari.com&lt;/a&gt;&lt;/strong&gt;—so you can explore the toolset without another passive screencast.&lt;/p&gt;

&lt;p&gt;Introducing a new heroine for the ages: Clara Denari, Master Detective. Join her as she prowls through Boston, recovering stolen property by solving the mysteries left by the nefarious Dr. Chiaro Obscuro.&lt;/p&gt;

&lt;p&gt;This villain, who is both a meticulous kleptomaniac and someone with considerable long-term memory issues, has done it again. His habit is to hide his ill-gotten gains in obscure places, leaving a trail of clues that only he will understand. This time he’s stolen something valuable and has hidden it—but where?&lt;/p&gt;

&lt;p&gt;It’s up to Clara to save the day. By deciphering each clue, she may be able to find the stolen property—but it’s up to you to help her.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8hrxlhxsjb5m2s1gesl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8hrxlhxsjb5m2s1gesl.png" alt="Homepage of Clara Denari app" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Start your adventure here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Follow the trail in the story, picking up objects and storing them in your inventory. &lt;/p&gt;

&lt;h2&gt;
  
  
  What you practice (transformations, labs, Content Credentials)
&lt;/h2&gt;

&lt;p&gt;You’ll use &lt;strong&gt;Cloudinary transformations&lt;/strong&gt; to clean a piece of string, brighten an image to reveal hidden text, and apply refiners to tidy up lost keys, then discover the secret hiding place of the lost treasure. You’ll also dig into &lt;strong&gt;Content Credentials&lt;/strong&gt;—a C2PA-aligned view of how an image’s provenance and edits appear over its lifecycle:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlg3jwy022i330oiij0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzlg3jwy022i330oiij0i.png" alt="Content Credentials" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Content Credentials using C2PA standards.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You’ll need to get hands-on with these ideas to finish the case. &lt;strong&gt;Solve all 5 challenges&lt;/strong&gt; and reach the end with the key. Try transforms yourself with a &lt;a href="https://cloudinary.com?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=claradenari" rel="noopener noreferrer"&gt;free Cloudinary account&lt;/a&gt;; in the Lab, plug in your &lt;strong&gt;cloud name&lt;/strong&gt; and the image’s &lt;strong&gt;public ID&lt;/strong&gt; and adjust transformations until the clue makes sense.&lt;/p&gt;

&lt;p&gt;Here is one example of a &lt;strong&gt;Cloudinary delivery URL&lt;/strong&gt; (public &lt;code&gt;demo&lt;/code&gt; asset). You change the &lt;strong&gt;transformation chain&lt;/strong&gt; right after &lt;code&gt;upload/&lt;/code&gt;, before the public ID (here, &lt;code&gt;sample&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://res.cloudinary.com/demo/image/upload/c_scale,w_400/sample
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;c_scale,w_400&lt;/code&gt; resizes the delivered image; in the game’s Lab you will swap in brightness, refiner, and other tokens that match each clue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4e9wo5blnh3wzrjlue8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4e9wo5blnh3wzrjlue8.png" alt="Lab screenshot" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Clara’s Lab&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Localization and setting
&lt;/h2&gt;

&lt;p&gt;Préférez-vous le français ? ¿Qué tal el español? Português brasileiro? We have you covered: the app is fully localized in four languages. This first &lt;strong&gt;Clara Denari Adventure&lt;/strong&gt; is set on the gritty underside of &lt;strong&gt;Boston, USA&lt;/strong&gt;—cannoli and all. If you’d like Clara to come to your city to solve a mystery, say the word in the community discussion.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to start
&lt;/h2&gt;

&lt;p&gt;The app is built to teach: short embedded &lt;strong&gt;quizzes&lt;/strong&gt; check what you’ve picked up, and you can earn a custom &lt;strong&gt;&lt;a href="https://www.holopin.io/@cloudinary" rel="noopener noreferrer"&gt;Holopin&lt;/a&gt;&lt;/strong&gt; to show detective mastery on your social profiles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm3dp6no2uffm0fcisbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkm3dp6no2uffm0fcisbu.png" alt="holopin" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Earn your limited edition Holopin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trench coat on, glass polished? Join the inaugural &lt;strong&gt;Clara Denari&lt;/strong&gt; release from &lt;strong&gt;Developer Relations at Cloudinary&lt;/strong&gt;. &lt;strong&gt;Start the game:&lt;/strong&gt; &lt;a href="https://claradenari.com" rel="noopener noreferrer"&gt;claradenari.com&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It is a happy talent to know how to play.” — Ralph Waldo Emerson, 1803–1882&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=claradenari" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>What To Do if Your Web Site Is as Slow as Molasses in January</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Wed, 30 Jul 2025 17:50:00 +0000</pubDate>
      <link>https://dev.to/cloudinary/what-to-do-if-your-web-site-is-as-slow-as-molasses-in-january-2j4f</link>
      <guid>https://dev.to/cloudinary/what-to-do-if-your-web-site-is-as-slow-as-molasses-in-january-2j4f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Image from the 1982 version of the CandyLand board game.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Web performance is one of those topics that simmers on the back burner for some developers; something that, unless well-regulated and occasionally stirred (read: fine-tuned) can easily boil over. It’s a well-worn mantra that for each second of wait time experienced by a user, revenue is lost. Bounce rates, e.g. how quickly a user will leave your site, increase 32% as a page’s load time increases from one second to three seconds &lt;a href="https://www.shopify.com/blog/website-load-time-statistics" rel="noopener noreferrer"&gt;[source]&lt;/a&gt;. Given today’s attention spans, it’s likely that users’ patience is becoming ever shorter.&lt;/p&gt;

&lt;p&gt;Fixing your website’s performance is not a one-time activity. As it grows and changes, performance should always be top of mind for the careful developer. Nor is a slow website repaired by focusing on just one aspect. Slow web speed can be caused by, in general, three elements:  heavy design, clunky server infrastructure, or a user's slow internet connection. These factors can be broadly categorized into issues with the website itself (unoptimized code, huge images, video), server performance, and network conditions. Let’s focus on the first of those problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack of the Mega-Image
&lt;/h2&gt;

&lt;p&gt;The use of giant images is often a culprit in site slow-downs. Even if you’re not a specialist in making your sites blazingly fast, there are a few helpers that can at the very least reduce your image load time to a reasonable level. In this article, I’d like to show how I used a tool developed by Cloudinary to measurably speed up an image-heavy site I built - not that my site will ever generate revenue, but the process became a test of how to balance image quality with site speed.&lt;/p&gt;

&lt;p&gt;Consider &lt;a href="https://tussie-mussies.netlify.app/" rel="noopener noreferrer"&gt;this site&lt;/a&gt; which I built using Astro, with a way to pick flowers and build custom bouquets reflecting the Victorian language of flowers. It looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6ghyualgljogaxddhns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6ghyualgljogaxddhns.png" alt="Tussie Mussie Generator" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you choose the flowers you like, Gemini AI is used to create virtual ‘tussie mussies’, a favorite parlor game in the Victorian era, sending coded messages to enemies and admirers alike. In our case, you can send your AI-generated ‘bouquAI’ via an e-card powered by Mailgun. Here’s an example of a generated bouquet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qvkmop97r5lxcr4z4m0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qvkmop97r5lxcr4z4m0.png" alt="Sample Bouquet" width="782" height="1112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty? Yes! Useful? Well, not so much. Monetizable? Hardly! And fast? Given that there are 118 high-resolution images in the flower database, which I originally downloaded as Creative-Commons licensed flower images and stored locally, not at all!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Need for Speed
&lt;/h2&gt;

&lt;p&gt;Can we speed up this site a little simply by using Cloudinary’s image CDN and some optimizations suggested as best practices? As it turns out, there’s a useful tool that we can use to get a baseline, and then progressively optimize. It’s called &lt;a href="https://link.cloudinary.com/uiHBy" rel="noopener noreferrer"&gt;https://webspeedtest.cloudinary.com/&lt;/a&gt; and is a great way to work through your image optimization challenges.&lt;/p&gt;

&lt;p&gt;I first started by analyzing the page speed without any optimizations, and was unpleasantly surprised to discover that the images I used were heavy as heck - while pagination stops the bulk of them from loading all at once, the six plus the logo that show on the home page totaled almost 3 megabytes. Helpfully, the webspeedtest tool offers hints on how to better follow best practices on image load: smart compression, alongside the use of Cloudinary’s CDN, should make a difference!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9eyzqsua8qixbcr2wl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9eyzqsua8qixbcr2wl3.png" alt="Preliminary results of webspeedtest" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I uploaded all 100+ flower images used by this site up to Cloudinary’s Assets area, keeping their original names so as to continue to be callable using the .json file in my codebase that retains the image names and the flower’s meaning. Then, focusing on the images loaded into the image cards on the homepage, I changed the image’s url to reflect their new residence in the CDN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;   &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"`https://res.cloudinary.com/${cloudName}/image/upload/flowers/${flower.image}`"&lt;/span&gt;
&lt;span class="na"&gt;:alt=&lt;/span&gt;&lt;span class="s"&gt;"flower.name"&lt;/span&gt;
 &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full h-full object-cover"&lt;/span&gt;
 &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For those new to this domain, a CDN (Content Delivery Network) is “a geographically distributed group of servers that caches content close to end users. A CDN allows for the quick transfer of assets needed for loading Internet content, including HTML pages, JavaScript files, stylesheets, images, and videos.” according to &lt;a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt;. Assets geographically closer to users are delivered more quickly to their browser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, it was time to try some of Cloudinary’s image transformations to optimize the delivery. Adding an &lt;code&gt;f_auto&lt;/code&gt; parameter allows my images to be delivered in the fastest way to a given client. A scorecard offered by the webspeedtest tool shows the potential for speeding up delivery given different image formats:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vsxvorq4drjpfofc1cz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vsxvorq4drjpfofc1cz.png" alt="Sample webspeedtest analysis" width="768" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following best practices to enable image compression, I then started tweaking the &lt;code&gt;q_auto&lt;/code&gt; parameter via the URL to see how I could improve my page score. I found that by using a width setting for my responsive cards and adding &lt;code&gt;q_auto:eco&lt;/code&gt;, I was able to compress the images to a reasonable size. By changing the &lt;code&gt;:eco&lt;/code&gt; parameter to other options such as &lt;code&gt;:good&lt;/code&gt; or &lt;code&gt;:best&lt;/code&gt; you can fiddle with the amount of image loss that you can tolerate (the site has to be fast &lt;em&gt;and&lt;/em&gt; look good, after all).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;   &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"`https://res.cloudinary.com/${cloudName}/image/upload/w_250/f_auto,q_auto:eco/flowers/${flower.image}`"&lt;/span&gt;
&lt;span class="na"&gt;:alt=&lt;/span&gt;&lt;span class="s"&gt;"flower.name"&lt;/span&gt;
&lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full h-full object-cover"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I experimented a bit with how the images looked using &lt;code&gt;q_auto&lt;/code&gt; (which is the same as &lt;code&gt;q_auto:good&lt;/code&gt;) by trying ‘best’ and ‘eco’ settings. There’s a clear tradeoff on image quality and page load times, so use your best judgement on what is an acceptable quality level for your images for your use case. The Cloudinary docs offer a good example of how images look when this parameter changes: &lt;a href="https://link.cloudinary.com/uiHBz" rel="noopener noreferrer"&gt;https://cloudinary.com/documentation/image_optimization&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By doing this tweak, I managed to get a better score - from C to B:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyckhcgxx9blwm5mjiwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyckhcgxx9blwm5mjiwy.png" alt="Second run: B" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mediocre to Good isn’t bad! And I get a 100% score on Lighthouse:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9348l2ek9lwzjqta0bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9348l2ek9lwzjqta0bg.png" alt="Lighthouse" width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What other things could I do to speed the image load even more? One thing would be to create a more complex responsive design that would deliver only the smallest images to the smallest screens. Another would be to make sure that all images are meticulously cropped and resized. For the time being, however, I’m satisfied with having speeded up my site a bit. &lt;/p&gt;

&lt;p&gt;Stay tuned for esoteric demos and sign up to enjoy the generous free tier of this top-notch image and video platform!&lt;/p&gt;

&lt;p&gt;What are you doing to make your site wicked fast? Let me know in the comments!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=slow-website" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;About me: I'm the Director of Developer Relations at &lt;a href="https://link.cloudinary.com/uiHBA" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt;. Stay tuned for esoteric demos and sign up to enjoy the generous free tier of this top-notch image and video platform!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>codenewbie</category>
      <category>webperf</category>
      <category>programming</category>
    </item>
    <item>
      <title>Uncovering Family History with Cloudinary’s Image Transformations, Goose, and MCP Servers</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Thu, 24 Jul 2025 15:21:21 +0000</pubDate>
      <link>https://dev.to/cloudinary/uncovering-family-history-with-cloudinarys-image-transformations-and-mcp-servers-1484</link>
      <guid>https://dev.to/cloudinary/uncovering-family-history-with-cloudinarys-image-transformations-and-mcp-servers-1484</guid>
      <description>&lt;p&gt;There’s a peculiar human desire to reconnect with their past by looking for clues in family trees. Did you get that sass from Great-Aunt Edna, who, to her dying day, declined to share her prized German Potato Salad recipe? Did you get those baby blue eyes from your Mom’s side of the family? In a country like the US, shaped by waves of immigration and where people tend to move frequently in search of opportunity, it’s easy to lose track of where we came from in pursuit of where we are going (next). &lt;/p&gt;

&lt;p&gt;Recently I’ve been digging through archives to flesh out my family’s genealogical history a bit, using the interesting software offered by &lt;a href="http://Ancestry.com" rel="noopener noreferrer"&gt;Ancestry.com&lt;/a&gt;, a company that helps you build out your family tree. One thing I found was photos attached to the tree are few and far between - they are a pain to scan and upload, and these paper fragments often are damaged. For this reason I’ve been happy to experiment with ways to upscale and enhance these images using AI - and I discovered a little key to the past while doing so!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I also found that my ninth great-grandmother was the famous Rebecca Nurse Towne, hanged as a witch during the Salem Witch Trials in the 1690s. So there’s that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdk5buo8883vawqevsutf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdk5buo8883vawqevsutf.png" alt="Ancestry timeline" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sample of what family trees look like on Ancestry.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Something Old, Something New
&lt;/h2&gt;

&lt;p&gt;While digging through Ancestry’s pages, I discovered an image I hadn’t seen before of my Great Grandparents, Elmer Dove and Blanche Bartlett Dove: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdgfzplh18g72597k1k86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdgfzplh18g72597k1k86.png" alt="Dove family photo" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While the image is pretty crisp, I put it through a workflow that I built to help my research: enhancing the images using AI to get a few more details from them. To do this, I used &lt;a href="https://block.github.io/goose/" rel="noopener noreferrer"&gt;Goose&lt;/a&gt;, a new tool by Block to interface with LLMs and MCP servers so that you can simply do your work locally without battling tooling. This was exactly what I needed to enhance the images I found on Ancestry right from a desktop app, chatting with Goose via Gemini, my LLM of choice. &lt;a href="https://github.com/cloudinary/mcp-servers" rel="noopener noreferrer"&gt;Cloudinary’s MCP servers&lt;/a&gt; work very well with Goose; here’s how to start using them.&lt;/p&gt;

&lt;p&gt;To get setup to use Goose with Cloudinary’s MCPs, there are a few steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download Goose for free and take a look at how it interfaces with Cloudinary’s MCP servers: &lt;a href="https://block.github.io/goose/docs/mcp/cloudinary-asset-management-mcp/" rel="noopener noreferrer"&gt;https://block.github.io/goose/docs/mcp/cloudinary-asset-management-mcp/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the Cloudinary extension by searching for Cloudinary at &lt;a href="https://block.github.io/goose/extensions/" rel="noopener noreferrer"&gt;https://block.github.io/goose/extensions/&lt;/a&gt; and pressing ‘install’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your Cloudinary URL to the extension’s settings (find the URL by going to the console in &lt;a href="https://link.cloudinary.com/uiHvg" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; and looking for the API key section, where the URL is listed: &lt;code&gt;CLOUDINARY_URL=cloudinary://&amp;lt;your_api_key&amp;gt;:&amp;lt;your_api_secret&amp;gt;@&amp;lt;your_account_name&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For ease of upload, I added an &lt;a&gt;upload preset&lt;/a&gt; so that all the images in this task will go to a specific folder.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdo4tsjxvzecrv5akaskk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdo4tsjxvzecrv5akaskk.png" alt="MCP Settings" width="800" height="701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Configure your LLM of choice using an appropriate API key as outlined by Goose (I use Gemini)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgew7u9yajmxeyp7dj1ti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgew7u9yajmxeyp7dj1ti.png" alt="Configuring Goose" width="800" height="759"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can start chatting with Goose via your LLM. Tell it to upload images straight from Ancestry paths (which you can get by right-clicking on an image in Ancestry) and transform them to bring these pictures into better focus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhcoih5qy4p48lkv9dai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhcoih5qy4p48lkv9dai.png" alt="chat with your LLM" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was amazed by the image quality, and even learned something about Great-Grandfather Elmer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ffront-end-foxes%2Fimage%2Fupload%2Fe_gen_restore%2Ce_upscale%2Fancestors%2Flgvobvhueqgvziibxr5t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ffront-end-foxes%2Fimage%2Fupload%2Fe_gen_restore%2Ce_upscale%2Fancestors%2Flgvobvhueqgvziibxr5t.jpg" alt="Dove family enhanced" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this enhanced image, my eye was caught by the little silver axe pinned to the lapel. Some research using ChatGPT found that this signifies membership in the ‘Modern Woodmen’ Association, a proto life-insurance type organization still in existence that pooled members’ assets in case of death, so that the widow would be taken care of. Given that this photo was taken in the 1890s in Nebraska, and documentation mentions his membership in this organization, this checks out, but I never would have made the connection without the little symbol that shows clearly in the enhanced photo. It’s delightful to see these little humanizing elements pop out from the past. Also that’s a cool moustache.&lt;/p&gt;

&lt;p&gt;Next I tried a transformation of my formidable Great Grandmother Schoenleber, née Isermann, on the other side of the family. This lady went on to be the mother of twelve, including a set of twins, one of whom was my Grandfather. German farm wives do not mess around. I was thrilled to use Goose and the Cloudinary MCP server to go from this grainy photo…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ydjw6nn9exd4p995kvy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ydjw6nn9exd4p995kvy.jpg" alt="Charlotte Schoenleber" width="250" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…to this with some AI enhancement, restoration and brightening, with her amazing spit curls, elaborate lace and earrings on full display:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ffront-end-foxes%2Fimage%2Fupload%2Fe_gen_restore%2Ce_upscale%2Fancestors%2Fidccn3peocnt30tr2ozj" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Ffront-end-foxes%2Fimage%2Fupload%2Fe_gen_restore%2Ce_upscale%2Fancestors%2Fidccn3peocnt30tr2ozj" alt="enhanced photo of Charlotte Schoenleber" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In conclusion, it’s a wonderful experience to “speak” to your ancestors via these old photographs. Using an MCP server allows you to get tooling out of the way and simply interface with an AI agent that will let you see your past just a little more clearly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=family-history" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;About me: I'm the Director of Developer Relations at Cloudinary. Stay tuned for esoteric demos and &lt;a href="https://link.cloudinary.com/uiHvi" rel="noopener noreferrer"&gt;sign up&lt;/a&gt; to enjoy the generous free tier of this top-notch image and video platform!&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>mcp</category>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>Using Cloudinary's New MCP Server to Scrape Mozzarella, Camembert and Parmesan</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Sun, 22 Jun 2025 01:16:22 +0000</pubDate>
      <link>https://dev.to/cloudinary/using-cloudinarys-new-mcp-server-to-scrape-mozarella-camembert-and-parmesan-1m4b</link>
      <guid>https://dev.to/cloudinary/using-cloudinarys-new-mcp-server-to-scrape-mozarella-camembert-and-parmesan-1m4b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;image from Midjourney, amusingly prompted as 'cheesecore'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm always interested in how new technology can help us make our esoteric tasks a little less manual. Speaking of esoteric tasks, did you know that I curate a &lt;a href="https://www.kaggle.com/datasets/jenlooper/cheese" rel="noopener noreferrer"&gt;machine learning model&lt;/a&gt; to classify types of cheese? It was done to power a mobile app like this:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/1Kqtg1Mw2wc?start=286"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The trick with creating custom ML models is that you need to train a model with a bunch of good-quality images so that it can learn about the categories you want to test. In this case, I wanted to be able to walk into a cheese shop and, via my custom ML-enabled mobile app, determine the type of cheese that was available out of the six standard categories of cheese worldwide: bloomy, semi-soft, hard, fresh, blue, and washed-rind. Yes, this is important work. &lt;/p&gt;

&lt;p&gt;But digging through images online and manually dumping them into folders is a pain. Alternately, walking into your local cheese shop and shooting video to later split up into images using ffmp, all the while telling the sales people that "I'm fine, just building up a dataset for my ML model", is kind of embarassing. Isn't there a better way?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feuiwxfehat47j380yelc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feuiwxfehat47j380yelc.gif" alt="https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjA1ZHpncnN2Yzk1dnVnenF1cjA4MmIxemphdHJtYTU5cjhhaHU0biZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l1L2UkgpuiE4U/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Live action view of Jerry impersonating a ML model&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Turns out ... YES! Recently, Cloudinary released an MCP server solution that would allow me to perform a quick web scrape to gather images of types of cheese that I can curate and upload, tagged, to my account. It's the perfect use case! Make the images &lt;em&gt;come to you&lt;/em&gt; using an agent, and make that agent work nicely with Cloudinary, your friend for media management. &lt;strong&gt;All while never leaving the comfort and safety of your IDE&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Meet the &lt;strong&gt;Cheesy MCP&lt;/strong&gt; — the AI-powered agent that scrapes free, Creative-Commons licensed, high-quality cheese photos and delivers them straight to your Cloudinary account. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Of course, this system can be used with images other than cheese! Use it for a sweet way to curate other image categories too.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Is this MCP thing?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;M&lt;/strong&gt;odel &lt;strong&gt;C&lt;/strong&gt;ontext &lt;strong&gt;P&lt;/strong&gt;rotocol, &lt;a href="https://www.anthropic.com/news/model-context-protocol" rel="noopener noreferrer"&gt;launched by Anthropic&lt;/a&gt; last November, is the &lt;del&gt;new hotness&lt;/del&gt; power behind AI agents, enabling them to independently function to perform actions set by a user using an agreed-upon protocol. An example is asking an agent to crawl your mailbox periodically to gather receipts to build a monthly expense report, or periodically prowl the web for images of wedding cakes to add to a Pinterest board. &lt;/p&gt;

&lt;p&gt;Cloudinary has entered the field with an offering allowing you to connect your AI tools like Claude or Cursor to the Cloudinary service for automated asset management. Take a look at the open source, free servers listed &lt;a href="https://github.com/cloudinary/mcp-servers" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt; as they continue to develop and evolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does This Have To Do With Cheese?
&lt;/h2&gt;

&lt;p&gt;Honestly, what a question. What &lt;em&gt;doesn't&lt;/em&gt; have to do with cheese? Still, glad you asked! I built a Python project to leverage this MCP tool from within Cursor, my IDE of choice. The agent surfs Google, bringing me images that I can curate ad hoc, with a nice automation workflow done via chat in Cursor. Once the images are available, I approve them and check their metadata for proper tagging, and say 'upload' in chat. The images are then uploaded right on up to my Cloudinary account, all tagged up and with metadata intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Up and Running
&lt;/h2&gt;

&lt;p&gt;There are a few things you need to do to leverage these servers and a few different ways you can do it. As a Cursor user, I was happy to simply use the 'add to Cursor' buttons available for us:&lt;/p&gt;

&lt;p&gt;For Cursor users, you can install MCP servers with one click using &lt;a href="https://docs.cursor.com/deeplinks" rel="noopener noreferrer"&gt;Cursor deeplinks&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;The following MCP servers are available for Cloudinary:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;GitHub Repo&lt;/th&gt;
&lt;th&gt;Install&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/asset-management-js?tab=readme-ov-file#model-context-protocol-mcp-server" rel="noopener noreferrer"&gt;&lt;strong&gt;Asset Management&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Upload, manage, and transform your media assets with advanced search and organization capabilities&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/asset-management-js" rel="noopener noreferrer"&gt;@cloudinary/asset-management&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cursor.com/install-mcp?name=cloudinary-asset-mgmt&amp;amp;config=eyJjb21tYW5kIjoibnB4IC15IC0tcGFja2FnZSBAY2xvdWRpbmFyeS9hc3NldC1tYW5hZ2VtZW50IC0tIG1jcCBzdGFydCIsImVudiI6eyJDTE9VRElOQVJZX0NMT1VEX05BTUUiOiJjbG91ZF9uYW1lIiwiQ0xPVURJTkFSWV9BUElfS0VZIjoiYXBpX2tleSIsIkNMT1VESU5BUllfQVBJX1NFQ1JFVCI6ImFwaV9zZWNyZXQifX0%3D" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2sbc77d7mextcar2hkc.png" alt="Install MCP Server"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/environment-config-js?tab=readme-ov-file#model-context-protocol-mcp-server" rel="noopener noreferrer"&gt;&lt;strong&gt;Environment Config&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Configure and manage your Cloudinary environment settings, upload presets, and transformations&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/environment-config-js" rel="noopener noreferrer"&gt;@cloudinary/environment-config&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cursor.com/install-mcp?name=cloudinary-env-config&amp;amp;config=eyJjb21tYW5kIjoibnB4IC15IC0tcGFja2FnZSBAY2xvdWRpbmFyeS9lbnZpcm9ubWVudC1jb25maWcgLS0gbWNwIHN0YXJ0IiwiZW52Ijp7IkNMT1VESU5BUllfQ0xPVURfTkFNRSI6ImNsb3VkX25hbWUiLCJDTE9VRElOQVJZX0FQSV9LRVkiOiJhcGlfa2V5IiwiQ0xPVURJTkFSWV9BUElfU0VDUkVUIjoiYXBpX3NlY3JldCJ9fQ%3D%3D" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2sbc77d7mextcar2hkc.png" alt="Install MCP Server"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/structured-metadata-js?tab=readme-ov-file#model-context-protocol-mcp-server" rel="noopener noreferrer"&gt;&lt;strong&gt;Structured Metadata&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Create, manage, and query structured metadata fields for enhanced asset organization and searchability&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/structured-metadata-js" rel="noopener noreferrer"&gt;@cloudinary/structured-metadata&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cursor.com/install-mcp?name=cloudinary-smd&amp;amp;config=eyJjb21tYW5kIjoibnB4IC15IC0tcGFja2FnZSBAY2xvdWRpbmFyeS9zdHJ1Y3R1cmVkLW1ldGFkYXRhIC0tIG1jcCBzdGFydCIsImVudiI6eyJDTE9VRElOQVJZX0NMT1VEX05BTUUiOiJjbG91ZF9uYW1lIiwiQ0xPVURJTkFSWV9BUElfS0VZIjoiYXBpX2tleSIsIkNMT1VESU5BUllfQVBJX1NFQ1JFVCI6ImFwaV9zZWNyZXQifX0%3D" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2sbc77d7mextcar2hkc.png" alt="Install MCP Server"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/analysis-js?tab=readme-ov-file#model-context-protocol-mcp-server" rel="noopener noreferrer"&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Leverage AI-powered content analysis, moderation, and auto-tagging capabilities for your media assets&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/cloudinary/analysis-js" rel="noopener noreferrer"&gt;@cloudinary/analysis&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cursor.com/install-mcp?name=cloudinary-analysis&amp;amp;config=eyJjb21tYW5kIjoibnB4IC15IC0tcGFja2FnZSBAY2xvdWRpbmFyeS9hbmFseXNpcyAtLSBtY3Agc3RhcnQiLCJlbnYiOnsiQ0xPVURJTkFSWV9DTE9VRF9OQU1FIjoiY2xvdWRfbmFtZSIsIkNMT1VESU5BUllfQVBJX0tFWSI6ImFwaV9rZXkiLCJDTE9VRElOQVJZX0FQSV9TRUNSRVQiOiJhcGlfc2VjcmV0In19" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2sbc77d7mextcar2hkc.png" alt="Install MCP Server"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://cloudinary.com/documentation/mediaflows_mcp" rel="noopener noreferrer"&gt;&lt;strong&gt;MediaFlows&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Build and manage low-code workflow automations for images and videos with AI-powered assistance&lt;/td&gt;
&lt;td&gt;MediaFlows MCP&lt;/td&gt;
&lt;td&gt;&lt;a href="https://cursor.com/install-mcp?name=mediaflows&amp;amp;config=eyJ1cmwiOiJodHRwczovL21lZGlhZmxvd3MubWNwLmNsb3VkaW5hcnkuY29tL3YyL21jcCIsImhlYWRlcnMiOnsiY2xkLWNsb3VkLW5hbWUiOiJjbG91ZF9uYW1lIiwiY2xkLWFwaS1rZXkiOiJhcGlfa2V5IiwiY2xkLXNlY3JldCI6ImFwaV9zZWNyZXQifX0%3D" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2sbc77d7mextcar2hkc.png" alt="Install MCP Server"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Make sure you have your Cloudinary account ready with your API credentials handy as you'll need to update the environment variables with your actual credentials after installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Your Engines
&lt;/h2&gt;

&lt;p&gt;Once I installed the MCP JSON into Cursor, it was picked up and I was invited to configure the server. Add your credentials right into the MCP settings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2042vrmw3hnyruohyxvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2042vrmw3hnyruohyxvx.png" alt="install the server"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once ready, Cursor helped me create a Python script to scrape images and dump them into my local folder. By far this was the most finicky bit - web scraping is an inexact science. Once that is done, the system prompts me to curate them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9o68s3h4qnw0g67vy6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9o68s3h4qnw0g67vy6a.png" alt="curate time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the scrape is done and 'candidates' are offered for upload, I am invited to interact with the system via chat, telling the agent to 'upload'. I can check and, if necessary, overwrite any tags for the images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmttixjdmgf2vwn605yv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmttixjdmgf2vwn605yv.png" alt="upload the images right from Cursor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And once I give it the go-ahead, the system makes the handshake with my Cloudinary account and uploads the tagged images after I ensure they are correct:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqaq67ewijo5bbc2x65p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frqaq67ewijo5bbc2x65p.png" alt="tagged images"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fresh, not moldy!
&lt;/h2&gt;

&lt;p&gt;It's a new experience for me to be able to use my IDE as an agent, making handshakes between systems that I can control using code and this protocol. And honestly it took a bit of a mindshift to understand that web scraping can be done this way, rather than a plain cron job + Python or web app. But it's rather powerful, wouldn't you say?&lt;/p&gt;

&lt;p&gt;Give the new Cloudinary MCP servers a try, and let me know what you build. You can check out &lt;a href="https://github.com/jlooper/cheesy-mcp" rel="noopener noreferrer"&gt;my codebase on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=4870-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=mcp-server" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;About me: I'm the Director of Developer Relations at Cloudinary. Stay tuned for esoteric demos and &lt;a href="https://link.cloudinary.com/uiHu9" rel="noopener noreferrer"&gt;sign up&lt;/a&gt; to enjoy the generous free tier of this top-notch image and video platform!&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>ai</category>
      <category>mcp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Guys, I created the most useful AI Agent: the Egg Price-o-matic!</title>
      <dc:creator>Jen Looper</dc:creator>
      <pubDate>Tue, 18 Mar 2025 15:43:58 +0000</pubDate>
      <link>https://dev.to/jenlooper/guys-i-created-the-most-useful-ai-agent-the-egg-price-o-matic-2pl4</link>
      <guid>https://dev.to/jenlooper/guys-i-created-the-most-useful-ai-agent-the-egg-price-o-matic-2pl4</guid>
      <description>&lt;p&gt;Ever since I heard about Agentic AI and the ability that we now have to send little helpers all through the internet to save us some trouble with pesky automations, I've been racking my brains for that killer use case for an AI Agent. I don't really like the idea of an agent creating my entire vacation for me (although helping me get out of my restaurant rut by suggesting a 'surprise' restaurant each weekend would be helpful). Vacations need to be highly personalized and carefully planned, in my opinion, and errors can be costly. I think I'd rather book my own flights, tyvm. &lt;/p&gt;

&lt;p&gt;If an AI Agent could be customized to scroll through my tax history and file them for me, with zero chance of errors, that would be amazing. But until we have such a killer app available, let's try something simple to see if we can create both a killer app AND something that's really easy to build. &lt;/p&gt;

&lt;p&gt;Recently I took the &lt;a href="https://huggingface.co/learn/agents-course/unit0/introduction" rel="noopener noreferrer"&gt;AI Agents course on Hugging Face&lt;/a&gt;, and to be perfectly honest, building these bits of software from scratch is a little onerous. I instead turned to a leader in automations that I've used for years to see what Zapier could teach me about building an app that solves a crucial problem for me: finding the best price of eggs in my local area. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can test this yourself - it's set to my zip code but you can customize it: &lt;br&gt;
&lt;a href="https://agents.zapier.com/copy/75490b5c-c35b-4526-a944-b1e2189603cf" rel="noopener noreferrer"&gt;https://agents.zapier.com/copy/75490b5c-c35b-4526-a944-b1e2189603cf&lt;/a&gt;. &lt;br&gt;
You'll need a Zapier account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Creating an agent in Zapier is a quick three-step process, although you will want to fine-tune the resultant agent based on your needs. I found it best to make a hyperlocal agent, rather than a bot that would allow you to input your zip code to find egg prices, so as to reduce manual input needs.&lt;/p&gt;

&lt;p&gt;First, login to Zapier and create an agent using the button on the left nav:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h64a4jvybf5nvdzz3ea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h64a4jvybf5nvdzz3ea.png" alt="Creating an agent in Zapier" width="550" height="958"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are presented with a few sample agents that you can edit, or offered the option to create your own. For a really special use case like this one, you can create a custom agent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3js2x4iy7qp8bn0gay7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3js2x4iy7qp8bn0gay7v.png" alt="custom agent creation in Zapier" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, you can configure it in the configuration tab, inserting any data source or data connection and adding any actions you want the agent to take. In my case, I wanted rows added to a Google spreadsheet when the agent runs, asking it to scrape the internet in a 20 mile radius of local grocery stores, to find and email me the price of a dozen eggs. You can ask the agent to run ad hoc or on a schedule.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovkp92790gttalc5idvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovkp92790gttalc5idvw.png" alt="Configuring the agent" width="800" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this simple example, you can get a regular email like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzrp7uo85xjadg46dzgk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzrp7uo85xjadg46dzgk.png" alt="Image of email" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... and a spreadsheet progressively populated with data. Then, you could create some visualizations around that data as the prices fluctuate, the sky's the limit!&lt;/p&gt;

&lt;p&gt;Have you tried any AI Agent creation software recently? Let me know what worked for you in the comments, and any pain points you found. If you are interested in following my adventures in AI, subscribe to my weekly LinkedIn newsletter, &lt;a href="https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7299544901526958081" rel="noopener noreferrer"&gt;AI Drops&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>powerfuldevs</category>
      <category>codenewbie</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
