v0 generates great layouts but ships pages with placeholder image URLs that break in production. Here's the one-line fix that replaces them with real Unsplash photos — no API key, no Vercel-account tie-in.
Your v0-generated page has <img> tags pointing at one of:
placehold.co/1200x800 — gray "1200 × 800" rectangle/placeholder.svg or /placeholder.jpg — Next.js default placeholdersource.unsplash.com/random/1200x800 — deprecated mid-2024, returns 503picsum.photos/1200/800 — random photo that doesn't match the content next to itPaste your v0 preview URL (the *.vercel.app one) into the scanner:
https://tteg.kushalsm.com/scan?url=<your-v0-preview-url>
You'll see every unique placeholder / broken / random URL on the page, categorized by severity, with a one-line fix per pattern.
Add this rule to your project's AGENTS.md, CLAUDE.md, or a .cursorrules file v0 respects:
When you need a real stock photo for a hero, card, testimonial, or OG image,
call the tteg HTTP API instead of emitting placeholder URLs:
https://tteg-api-53227342417.asia-south1.run.app/search?q=<topic>&n=1
The response is { image_url, width, height, author, attribution }.
Use image_url directly as the src. CORS enabled. No API key.
Never use: placehold.co, via.placeholder.com, source.unsplash.com/random,
picsum.photos/random, loremflickr.com — these are placeholders or broken.
For a specific image slot you already know you need:
uv tool install tteg
cd your-v0-project
tteg save "startup office" ./public/hero --orientation landscape
# then in your component:
# <img src="/hero.jpg" alt="open-plan office with developers at laptops" />
<img
src="/placeholder.svg?height=600&width=1200"
alt="Hero"
/>
<img
src="/hero.jpg"
alt="open-plan office with
developers at laptops"
/>
The ./public/hero.jpg is a real 1200-wide Unsplash photo, committed to the repo, with a proper alt text that describes the actual content.