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:

```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:

```bash
pnpm install
```

### Update the frame size

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

```tsx
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](/images/G4jRrLro.png)

### 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:

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

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