Photos from Cloudinary
Out of the box, your template resizes every photo when the site is built and serves AVIF and WebP versions from your own host. That is fast and needs no account. With Cloudinary turned on, the photos are delivered by Cloudinary’s image CDN instead: resized on request, in the best format each browser takes, and cached close to your visitors.
Templates: all (a site made earlier gets it with npx wptom update).
Service: Cloudinary (free plan available; usage above it is paid,
see Cloudinary’s pricing).
Setting: PUBLIC_CLOUDINARY_CLOUD_NAME.
How it works
Section titled “How it works”-
Production builds only. Cloudinary is used when the site is built for production (
npm run build, and every deploy).npm run devkeeps serving the photos itself, because Cloudinary can’t reach your computer. -
Fetch URLs. You don’t upload anything. Each photo’s address points at Cloudinary, which fetches the original from your live site once, keeps it, and serves the resized copies:
https://res.cloudinary.com/<cloud-name>/image/fetch/c_limit,w_960,f_auto,q_auto/https://your-domain.com/_astro/photo.jpg -
f_autoandq_auto. Cloudinary picks the format (AVIF or WebP where the browser supports them) and a quality that keeps the photo looking the same at a smaller size.c_limitnever makes a photo larger than its original. -
A
srcset. Each photo lists the same widths as before, so phones download small copies and large screens sharp ones. -
Which photos. The site’s own photos (the files in your project, also when edited in Keystatic). Photos that come from a hosted CMS (Sanity, EmDash) are served the way they were before. Icons, the logo and drawn graphics are unchanged.
Your site’s address in astro.config.mjs (site) is where Cloudinary fetches the originals
from, so it must be your live domain.
Without the setting
Section titled “Without the setting”Nothing changes: photos are resized at build time and served from your host, as AVIF and WebP with a JPEG fallback.
1. Find your cloud name
Section titled “1. Find your cloud name”- Sign up at cloudinary.com (or sign in).
- On the Console’s home page (Dashboard, under your product environment), copy the
Cloud name, e.g.
dxyz123ab. It is not your account email or the environment’s display name.
2. Allow fetched URLs, for your domain only
Section titled “2. Allow fetched URLs, for your domain only”New Cloudinary accounts block fetch URLs until you allow them.
- In the Console, open Settings → Security.
- Under Restricted media types, uncheck Fetched URL, so fetched images are allowed.
- Under Allowed fetch domains, add your site’s domain (e.g.
your-domain.com, andwww.your-domain.comif you use it). Then Cloudinary fetches only from your site, and nobody can use your account to deliver other people’s images. - Save.
3. Add the setting
Section titled “3. Add the setting”In .env and in Vercel (Settings → Environment Variables):
PUBLIC_CLOUDINARY_CLOUD_NAME=dxyz123abThen redeploy. The setting is written into the pages at build time, so it takes effect only in a new build.
Locally, npm run dev doesn’t change. A local npm run build with the setting already points
the photos at Cloudinary, which fetches them from your live site: if that site doesn’t have
the same photos yet, the preview shows broken images. Test on the deployed site instead.
4. Check it works on the live site
Section titled “4. Check it works on the live site”- Open the live site, right-click a photo and choose Inspect. Its
srcandsrcsetstart withhttps://res.cloudinary.com/<your-cloud-name>/image/fetch/. - In the developer tools’ Network tab (filter Img), reload: the photos come from
res.cloudinary.com, with the typeaviforwebp. - The first visit to each photo is a little slower while Cloudinary fetches the original; the next ones are served from its cache.
- In the Cloudinary Console, the usage reports show the delivered images and transformations.
Turn it off
Section titled “Turn it off”Remove PUBLIC_CLOUDINARY_CLOUD_NAME in Vercel (and .env) and redeploy. The photos are
resized at build time again, as before.
Fallback
Section titled “Fallback”- No setting, or
npm run dev: the photos are served by your site, as without Cloudinary. - A cloud name with characters Cloudinary doesn’t allow (spaces, dots…): Cloudinary is
switched off for the build, the build log shows
[photo] Cloudinary is off: Invalid Cloudinary cloud name, and the photos are served by your site. Your site never fails to build because of it. - A cloud name that looks right but isn’t yours, or fetched URLs still blocked: the build can’t tell, and the photos break on the live site. See below.
Troubleshooting
Section titled “Troubleshooting”| What you see | Why, and what to do |
|---|---|
| Photos are broken on the live site; opening one shows an error from Cloudinary | Fetched URLs are still restricted, or your domain isn’t in Allowed fetch domains (check www too). Fix it in Settings → Security; no redeploy needed |
| Broken photos, and the Cloudinary address contains another domain | The site in astro.config.mjs isn’t your live domain. Set it and redeploy |
| Broken photos right after the first deploy with Cloudinary | Check the cloud name: copy it again from the Console. A wrong cloud name gives Cloudinary errors for every photo |
| Photos still come from your own domain | The setting wasn’t there when the site was built: add it in Vercel and redeploy. Or the photo comes from Sanity or EmDash, which keep their own delivery |
[photo] Cloudinary is off in the build log |
The cloud name has the wrong form. Copy it again, without spaces or quotes |
| You replaced a photo, but the old one still shows | Cloudinary keeps fetched originals for a while. A new file name (which a build gives a changed photo) is fetched fresh |