Image Browser

Using the image browser to select images for your layers.

The ActionImageBrowser component is a plugin for the ActionImage component. It allows you to select images from a list of images. We can use it to build a custom image browser plugin.

In the following example, we'll build a meme browser plugin. We'll use the Imgflip API to fetch memes.

Download the Starter Template

We'll start by downloading the starter template.

Add License Key

Add your LICENSE KEY to the package.json file:

package.json
"@shadcn/designer": "https://ds.shadcn.com/registry?license=YOUR_LICENSE_KEY&version=0.4.2",

Install Dependencies

Install the dependencies by running the following command:

pnpm install

Update the frame size

Let's update the example post frameSize to 1080x1080 which works better for memes.

lib/post.ts
import { Layer } from "@shadcn/designer"
 
export async function getPost() {
  return {
    id: "xg9x0ff27hx09n0d",
    title: "Untitled Post",
    layers: [
      {
        id: "xqxbjdzdjyz",
        name: "Image",
        type: "image",
        value: "https://images.unsplash.com/photo-1503023345310-bd7c1de61c7d",
        cssVars: {
          "--width": "1080px", // <--- Update this
          "--height": "1080px", // <--- Update this
          "--z-index": "0",
          "--translate-x": "0px",
          "--translate-y": "0px",
        },
      },
    ],
    meta: {
      frameSize: {
        width: 1080, // <--- Update this
        height: 1080, // <--- Update this
      },
    },
  }
}

If you visit http://localhost:3000 you should see the following:

Image Browser

Add a Meme Browser

Let's add our meme browser to the ActionImage component. We can use the ActionImageBrowser component to build our meme browser.

In components/editor.tsx, find the PanelRight component and add the following to ActionImage component:

components/editor.tsx
<ActionImage
  plugins={[
    // ... other plugins
    {
      id: "meme-browser",
      label: "Meme Browser",
      description: "Select a meme from the browser.",
      component: (
        <ActionImageBrowser
          apiUrl="/api/memes"
        />
      ),
    },
  ]}
/>

If you select an image layer and click the Image button in the right panel, you should see a new Meme Browser tab in the image dialog.

Build our API route

The ActionImageBrowser component requires an API route to fetch the images. We'll create a simple API route to fetch memes from the imgflip API.

app/api/memes/route.ts
import { NextRequest, NextResponse } from "next/server"
 
import { imagesResponseSchema } from "@shadcn/designer/schema"
 
const DEFAULT_QUERY = "Pikachu"
 
export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url)
  const query = searchParams.get("query") || DEFAULT_QUERY
  const page = Number(searchParams.get("page")) || 1
  const per_page = Number(searchParams.get("per_page")) || 9
 
  const url = `https://api.imgflip.com/get_memes`
  const response = await fetch(url)
  const data = await response.json()
 
  // Imgflip does not have pagination.
  // We'll implement a faux pagination and search.
  const startIndex = (page - 1) * per_page
  const endIndex = startIndex + per_page
  const memes = data.data.memes.filter((meme: { name: string }) =>
    meme.name.toLowerCase().includes(query.toLowerCase())
  )
  const thisPage = memes.slice(startIndex, endIndex)
 
  return NextResponse.json(
    imagesResponseSchema.parse({
      results: thisPage.map((meme: { id: string; url: string }) => ({
        id: meme.id,
        url: meme.url,
        thumbnailUrl: meme.url,
      })),
      total: memes.length,
      total_pages: Math.ceil(memes.length / per_page),
    })
  )
}

To make sure we return the correct data structure, we'll use the imagesResponseSchema from the @shadcn/designer/schema package.

That's it!

That's all you need. You can now select an image, open the image dialog, search and apply a meme to the layer.