Fix broken images in v0-generated pages

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.

Symptom

Your v0-generated page has <img> tags pointing at one of:

Fast audit

Paste 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.

Fix at the source: give v0 a real image-source instruction

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.

Fix it right now: one command

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" />

Before / after

Before (v0 default)

<img
  src="/placeholder.svg?height=600&width=1200"
  alt="Hero"
/>

After (tteg)

<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.

Why not just wait for v0 to fix it? v0's default placeholders are correct from Vercel's perspective — they don't ship broken URLs, they ship "fill this in later" signals. The breakage is in the "ship to production without filling in later" step, which is the human-in-the-loop's job, not v0's. This page is that job reduced to one CLI call.

Related

tteg on GitHub →