I asked Claude Code to build a landing page for a side project. Twenty minutes later I had a real Next.js app — hero, feature grid, pricing, footer, all wired up.
Every image was a gray rectangle.
Not because Claude got lazy. It genuinely can't see your library, doesn't have an image budget, and knows that hotlinking a random URL is a good way to ship a 404. So it does the responsible thing: bg-gray-200, alt="hero image", a // TODO: replace comment, and it moves on to the next component.
The code was done. The app was not. Filling those rectangles was still a manual afternoon of searching, downloading, renaming, and pasting URLs — the exact tab-switching grind that vibe coding was supposed to kill. (This is the "every AI-built app looks the same" problem, one gray box at a time.)
The fix is one command. Give Claude Code the OKSLOP MCP server and it fills the rectangles itself — searching a 50k+ image library first, generating a custom image only when nothing fits.
Install: one line
Claude Code has a built-in MCP registry. Add OKSLOP to it:
claude mcp add okslop -- npx -y okslop-mcp-server
That's the whole setup. No API key required — search, browse, and the flagship find-or-generate tool all work anonymously (500 requests/day). Restart Claude Code and you'll see the okslop tools show up.
If you want custom generation, collections, and higher limits, grab a key at okslop.com/developers and pass it through:
claude mcp add okslop --env OKSLOP_API_KEY=ok_key_... -- npx -y okslop-mcp-server
The server publishes 36 tools, but you almost never name them. You describe what you want; Claude picks the tool. The one it reaches for most is find_or_generate_image.
The one tool to know: find_or_generate_image
Here's the whole philosophy in one tool name. Search the free library first. Generate only on a miss.
You hand it a description; it hands back one commercial-use, attribution-free URL plus a note saying which path it took. When a good match already exists, you pay nothing and get an instant URL. When nothing fits, it generates a custom image to spec in a contributor's style and returns a deterministic URL you can commit immediately.
That's the right default for an agent. It doesn't burn a generation credit — or your patience — on an image the commons already has. We go deep on the decision boundary in the flagship-tool post; here, just watch Claude use it.
The session: filling the rectangles
Back to that landing page. I told Claude:
Replace every placeholder image on the landing page with a real one from
OKSLOP. Use a warm, minimal style so the page feels cohesive.
Claude read the components, found the empty slots, and called the tool once per slot. The first call:
find_or_generate_image(
query="warm minimal home office workspace at golden hour",
orientation="landscape"
)
And the response it got back:
**find_or_generate_image** for "warm minimal home office workspace at golden hour"
Found in library (free, commercial-use, no attribution). 214 candidates
matched "warm minimal home office workspace at golden hour".
Image URL: https://okslop.com/img/.../preview
- **Sunlit desk with laptop and ceramic mug** (1024×768) — https://okslop.com/img/.../preview [ID: ...]
Library hit. Free, instant, done. Claude wrote the URL straight into the hero's src.
For the pricing section I'd written something oddly specific — "a single origami crane on a slate desk" — and the library came up short. So the tool crossed the boundary and generated:
**find_or_generate_image** for "single origami crane on a slate desk, top-down"
No close library match — generated a custom image to spec in the "nova-chen"
style (status: queued). The URL works immediately (placeholder until ready)
and is deterministic + commercial-use safe.
Image URL: https://okslop.com/img/.../preview
Same shape of answer, different path. The URL is live the instant Claude writes it — it serves a placeholder while the image renders, then swaps to the real thing. Nothing to poll, nothing to wait on.
Five slots, five real images, one prompt. I never opened a browser tab.
Doing a whole blog in one call
The landing page was five images. A blog backfill is more, and there's a tool built for exactly that: backfill_content_images. You hand it a list of slots — each a key plus a description — and it runs find-or-generate on every one, returning a key → URL map:
backfill_content_images(slots='[
{"key":"hero","description":"quiet city at sunrise","orientation":"landscape"},
{"key":"section-1","description":"hands typing on a laptop"},
{"key":"section-2","description":"team whiteboard sketch"}
]')
The report tells you which slots came from the library and which were generated:
**Backfill report** — 3 slot(s):
- **hero** (📚 library): https://okslop.com/img/.../preview
- **section-1** (📚 library): https://okslop.com/img/.../preview
- **section-2** (✨ generated): https://okslop.com/img/.../preview
Summary: 2 from library, 1 generated, 0 unfilled.
If you want to budget before you spend, plan_backfill reads a piece of content and proposes the slots and queries for you, and estimate_cost prices a batch — both run locally, no API call, no credits. Handy when Claude is about to illustrate a long post and you want to see the bill first.
Why the contributor style matters
When the tool does have to generate, it generates in a contributor's style — a named AI artist with a consistent look, not a random one-off. That's the difference between a page that looks designed and a page that looks like a mood board fell down the stairs.
Point every generated image at the same contributor and your whole site speaks one visual language: same palette, same mood, same restraint. Browse the roster at okslop.com/contributors and pick one that fits your brand. Claude will use it for anything it has to generate, and your landing page ends up looking like yours instead of like every other app shipped this week.
What this actually changes
Vibe coding closed the gap between "I have an idea" and "the app runs." It left one gap open: the app runs, but every image is a gray box, and closing that was still manual work an agent couldn't touch.
The MCP server closes it. Claude Code already knows how to edit your files. Now it has real images to edit them with — and it's smart enough to reach for the commons before it slops something new.
Install it in one line: claude mcp add okslop -- npx -y okslop-mcp-server. Grab a key at okslop.com/developers if you want generation and higher limits, then tell Claude to fill the rectangles.
This is the first post in a series on running OKSLOP inside your coding agent — Cursor and Windsurf are next.
Related: How find_or_generate_image decides · Migrating off the Unsplash API · Every vibe-coded app looks the same


