Photo Mosaic

A hero collage of photos with a few tags, to set the scene for a trip, a dish or a place.

Pattern

≈ 775 tokens per use (tool 406 · guidance 220 · typical payload 149)How token costs are estimated

Example: Photo Mosaic

Plan a 10-day Pacific Northwest road trip

Your 10-day Pacific Northwest road trip

  • 10 days
  • Road trip
  • Nature + cities

When to use

  • Opening a plan or an answer that is visual by nature: a trip, a dish, a place, an event, a venue.
  • The agent has 1–5 real photos from a search or tool result.

When not to use

  • The agent doesn't have real image URLs. It must never invent or guess them.
  • The user wants to browse or pick from many photos. Use a Slide Gallery.
  • Each image is an option with its own title. Use Inspiration Cards.

How the agent should use it

  • Use it once, at the top of the reply. It sets the scene; the details follow in text or other components.
  • Take every image src from a tool result or the host, never from memory. Only http(s) URLs and data:image/(png|jpeg|webp|svg+xml) load.
  • Put the strongest photo first. It becomes the hero.
  • Write real alt text that says what each photo shows. It's required.
  • Keep tags to a few words each, at most 5, and only facts from the plan ("10 days", "Road trip").
  • Lifecycle: photos are a snapshot, so it usually needs none. If src values are signed URLs that expire, set expiresAt to their expiry. When the agent replaces the plan, mark the old call superseded (supersededBy).

Layouts

The layout follows the number of photos. The whole mosaic is about 16:9 (aspect: "wide", a little taller on phones when there are three or more photos) or square (aspect: "square").

PhotosLayout
1One wide photo
2Side by side
3A hero on the left (about 60%) and two stacked on the right
4A hero and three: one wide over two small
5Two over three

Interaction

  • Enlarge: clicking a photo opens it in a lightbox (a native <dialog>), with its caption below. Captions appear only there, never on the mosaic. The previous and next buttons and the arrow keys move between photos, and moves are announced politely ("Photo 2 of 5: …"). Escape, Close or a click on the backdrop returns focus to the photo that opened it.
  • Broken images: a photo that fails to load, or whose src isn't allowed, becomes a neutral tile showing its alt text.
  • Streaming: the three-photo layout shows placeholders from the first token, and photos fill in as they arrive. Photos load lazily.

Installation

npx shadcn@latest add https://your-site.com/r/photo-mosaic.json

Usage

The Photo Mosaic is display-only, so the tool can return immediately:

app/api/chat/route.ts
import { tool } from "ai"
import { photoMosaicTool } from "@/components/genui/photo-mosaic.schema"

const tools = {
  [photoMosaicTool.name]: tool({
    description: photoMosaicTool.description,
    inputSchema: photoMosaicTool.inputSchema,
    execute: async () => ({ shown: true }),
  }),
}

Render it through the Renderer under show_photos, or directly:

<PhotoMosaic
  {...part.input}
  status={part.state === "input-streaming" ? "streaming" : "ready"}
  onResult={track}
/>

onResult is optional and for analytics only. It fires each time a photo is enlarged, never locks the mosaic, and the agent doesn't need to answer it:

{ action: "open", index: 0 } // zero-based

With LangGraph

Push it from a graph node with ui.push({ name: "show_photos", props }, { message }), and render the thread's UI messages with the Renderer.

Schema

PropTypeNotes
titlestring?e.g. "Your 10-day Pacific Northwest road trip"
aspect"wide" | "square"Shape of the whole mosaic. Default "wide" (about 16:9)
images{ src, alt, caption? }[]1–5 photos, the hero first. src is data-bound; caption shows only in the lightbox
tagsstring[]?Up to 5 short chips, up to 24 characters each

Host props: status (streaming or ready), onResult and className.

Source

On this page