Images & Media.
Where to find photos, video, and frames. How to host them with Cloudinary. And how not to get charged for things you didn't mean to do.
The image workflow, in one paragraph
Find the images. Upload only the ones you'll actually use to a hosting service (I use Cloudinary). Reference them in your code by URL. Optimize as needed. Don't pile up unused files in Cloudinary — you get billed on what's stored and served.
Where to find images and video
I split sources into premium (paid, higher production value, broader licensing) and free (great for most uses, occasional licensing caveats). Use placeholders during the build, swap real images in toward the end.
Premium
Adobe Stock
My go-to for frames, photo overlays, video B-roll, and anything where I need higher production value. Subscription. Search filter for "video" gets you HD/4K loops perfect for hero backgrounds.
Shutterstock
Comparable to Adobe Stock. Slightly different catalog. Worth a search if you can't find the right shot on Adobe.
Envato Elements
Subscription. Photos, video, fonts, mockups, and design templates all in one. Less curated than Adobe Stock but cheaper.
Free
Unsplash
Free, high-quality photos. Most of what you need for blog posts, generic hero shots, lifestyle imagery.
Pexels
Like Unsplash but also has a strong free video library. Great for animated hero backgrounds without an Adobe Stock subscription.
Pixabay
Photos, vectors, and music. Underrated for stock that doesn't look like stock. Good fallback when Unsplash and Pexels both come up dry.
Placeholders (use during the build)
Don't go shopping for real images while you're still figuring out the layout. Use placeholders so the page renders, ship the layout, then swap.
placehold.co
Quick gray placeholders with custom dimensions and labels. Like placehold.co/800x450 for a 16:9 placeholder.
picsum.photos
Random Lorem-Ipsum-style stock photos. Use picsum.photos/seed/abc/800/450 for stable URLs that always return the same image.
Hosting your images
You have three realistic options: serve images from your GitHub repo, use a free CDN, or use a dedicated image hosting service like Cloudinary. Here's the trade-off:
Option 1: GitHub repo (free, simple, limited)
Drop images in your repo's img folder, reference them by relative path. This is fine for small sites with a few images. Don't do this if you have hundreds of photos or any video — GitHub repos are not meant to be CDNs and you'll hit size limits.
Option 2: Cloudinary (my default)
Cloudinary is an image and video hosting service with a free tier and built-in optimization. You upload an image, get a URL back, and Cloudinary serves it fast and at the right size for whatever device is viewing it.
Free tier: 25 GB of storage and 25 GB of bandwidth a month. That's enough for most small client sites. Beyond that, paid tiers start around $99/month — significantly more than most freelance sites need.
⚠ Watch your usage on Cloudinary
Don't dump every image you might use into Cloudinary. Only upload the ones you've decided to ship with. Each unused image is taking up storage and counting toward your monthly limits.
If you blow past the free tier, you don't get a friendly upgrade prompt — Cloudinary will start serving your images more slowly or charge you, depending on your plan. The number-one Cloudinary mistake people make is treating it like Google Drive instead of a production CDN.
Practice: upload 10 images max during the build. Once the site is final, audit the images you actually used and delete the rest from Cloudinary. Storage stays clean and bandwidth stays low.
Pro tip: let Claude Code grab images from Cloudinary directly
If you're working in Claude Code, you don't have to copy-paste image URLs one by one. You can give Claude your Cloudinary API credentials and Claude will go find images for you, list what's available, and drop the right URLs into your code.
-
Get your Cloudinary credentials
In your Cloudinary dashboard, find your Cloud Name, API Key, and API Secret. They're on the main dashboard page under "Account Details."
-
Save them in a file called
.envin your project folderThe file is plain text, looks like this:
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret -
Add
.envto your.gitignoreimmediatelySo the file never gets committed to GitHub. API secrets in a public repo = bots will find them and use your account. Claude Code can do this for you: ask it to "add .env to .gitignore."
-
Tell Claude to use them
Now you can prompt: "Look at my Cloudinary account using the credentials in .env. Find the images in the 'acf-website' folder and use the appropriate ones in this section." Claude will fetch the list and drop in the right URLs.
This works much better if your Cloudinary is organized. Two habits that pay off:
- One folder per project. Don't dump everything in the root. Make a folder for each client (
acf-website,zuda-launcher, etc.) so Claude can scope the search. - Label your images clearly. "founder-nicole-headshot.jpg" beats "IMG_8472.jpg" by a mile. Claude can guess what an image is for from a good filename. Same goes for tags inside Cloudinary if you use them.
Option 3: Other image CDNs
Imgix
Pro-grade image CDN with strong transformation features. Pricier than Cloudinary but more flexible if you need on-the-fly resizing and complex transforms.
ImageKit
Cheaper alternative to Cloudinary with comparable features. Good if you need more headroom on the free tier.
Bunny.net
Generic but cheap CDN with image optimization. Pay-as-you-go, very low costs, no fancy bells.
Optimizing images before you upload
Even with Cloudinary doing automatic optimization, you should still pre-optimize. Smaller files = lower bandwidth bills + faster load times.
Squoosh
Free Google tool. Drag in an image, tweak quality and format (WebP, AVIF), see the file size drop in real time. Output is dramatically smaller than unoptimized JPEGs.
TinyPNG
Drag and drop bulk PNG/JPEG compressor. Less control than Squoosh but faster for batches.
Rough size targets
- Hero images: 1600–2000 px wide, under 300 KB if possible.
- Section images: 800–1200 px wide, under 150 KB.
- Thumbnails / card images: 400–600 px wide, under 60 KB.
- Avatars and small icons: 200 px wide max, under 30 KB.
If your hero is 5 MB you're going to lose mobile visitors. Mobile-first means image-budget-first too.
Video on the web
Video makes a hero feel cinematic. Done wrong, it ruins your performance and your bill.
- Keep it short. 5–10 second loops. No one watches a 90-second hero video.
- Mute and autoplay. Always. Browsers won't autoplay video with sound.
- Use MP4 (H.264) and WebM. Both formats for browser compatibility. Adobe Stock and Pexels often offer multiple format downloads.
- Resolution: 1080p is plenty. 4K hero loops are overkill and balloon file size.
- Compress before upload. A 30-second 4K MP4 from Adobe Stock can be 200 MB. Use Handbrake or Squoosh to get it under 5 MB before uploading.
- Mobile fallback. Many sites disable hero video on small screens — phones don't get the same treatment, they get a high-quality static image instead. Saves bandwidth, looks fine.
Common mistakes
- Uploading high-res unedited photos straight from a phone. A 12 MB image on a hero ruins your page speed. Always optimize.
- Treating Cloudinary like Google Drive. Storage isn't free — only upload what you ship. Audit and delete after launch.
- Embedding images via the original Adobe Stock or Unsplash URL. Don't hot-link from third parties. Download, upload to your own host (Cloudinary), reference your own URL.
- Skipping alt text. Every image needs descriptive alt text — for accessibility and for SEO. "Image of a thing" is not alt text. "Founder Nicole Roeseler smiling at a community event" is alt text.
- Forgetting that Adobe Stock has licensing terms. Standard licenses cover web use; Extended is for things like merch. Read the license summary at download.
How images flowed for ACF
For the ACF site we needed a mix: founder portraits (provided by the client), event photos (provided), generic foster-youth lifestyle imagery (Adobe Stock and Pexels), and one cinematic 8-second video loop for the home page hero (Adobe Stock — three crossfaded clips of community moments).
Everything went through Cloudinary at dstssdnoj. Total assets: about 25 photos, 3 short videos, after the post-launch cleanup. Cloudinary usage stays well under the free tier. The pre-launch state had nearly 80 candidate images uploaded; we deleted the unused 55 the week the site went live.
What's next
You have the assets sorted. Next up: how to actually talk to Claude during the build. The literal prompts I paste, organized by stage, plus the meta-tips for getting the best output.