> ## Documentation Index
> Fetch the complete documentation index at: https://www.logo.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Add logos to an integrations marketplace

> Ship an integrations page where every connector tile pulls its logo from a domain, so the grid stays current through partner rebrands.

export const IntegrationsGridDemo = () => {
  const TOKEN = "live_6a1a28fd-6420-4492-aeb0-b297461d9de2";
  const INTEGRATIONS = [{
    name: "Slack",
    domain: "slack.com"
  }, {
    name: "GitHub",
    domain: "github.com"
  }, {
    name: "Notion",
    domain: "notion.so"
  }, {
    name: "Figma",
    domain: "figma.com"
  }, {
    name: "Linear",
    domain: "linear.app"
  }, {
    name: "Dropbox",
    domain: "dropbox.com"
  }, {
    name: "Zoom",
    domain: "zoom.us"
  }, {
    name: "Salesforce",
    domain: "salesforce.com"
  }];
  return <div className="not-prose my-8 rounded-2xl border border-zinc-950/10 bg-gradient-to-br from-zinc-50 to-white p-6 shadow-sm sm:p-8 dark:border-white/10 dark:from-zinc-900 dark:to-zinc-950">
      <ul className="mx-auto grid max-w-lg grid-cols-2 gap-3 sm:grid-cols-4">
        {INTEGRATIONS.map(tool => <li className="flex flex-col items-center gap-2.5 rounded-xl border border-zinc-950/10 bg-white px-3 py-5 dark:border-white/10 dark:bg-zinc-900" key={tool.domain}>
            {}
            <span className="flex h-12 w-12 items-center justify-center rounded-lg bg-white">
              <img alt={`${tool.name} logo`} className="h-7 w-7 rounded-md object-contain" height="28" loading="lazy" src={`https://img.logo.dev/${tool.domain}?token=${TOKEN}&size=28&retina=true&format=webp`} width="28" />
            </span>
            <span className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
              {tool.name}
            </span>
          </li>)}
      </ul>
    </div>;
};

Integration directories, app marketplaces, partner grids: each is a wall of tiles, and every tile needs the partner's logo. Host those files yourself and a rebrand quietly breaks the grid.

A visitor scans the marketplace and every connector shows its current mark. Each tile builds its image from the partner's domain with the [Logo API](/docs/logo-images/introduction), so the grid stays current with no files to swap.

## Demo

Each tile below is the same component with a different domain:

<IntegrationsGridDemo />

Every logo loads live from `img.logo.dev`, requested by domain at render time.

## Build it with AI

<Prompt description="Want this integrations grid in your app? This prompt gives your AI coding tool everything it needs to build it in your framework." actions={["copy", "cursor"]}>
  Build an integrations marketplace grid using Logo.dev.

  * Each connector is a name plus a domain. Render a responsive grid of tiles (2 columns on mobile, 4 on desktop) with the logo above the name.
  * Logos are plain image URLs: [https://img.logo.dev/:domain?token=LOGO\_DEV\_PUBLISHABLE\_KEY\&size=28\&retina=true\&format=webp](https://img.logo.dev/:domain?token=LOGO_DEV_PUBLISHABLE_KEY\&size=28\&retina=true\&format=webp)
  * Sit every logo on a small white well (a rounded square) so transparent dark marks and baked-white backgrounds both read consistently on grey or dark surfaces.
  * Lazy-load the logo images so a catalog with hundreds of connectors only fetches what is on screen.
  * Unknown domains still render: Logo.dev returns a generated monogram instead of a broken image, so no error handling is needed.
  * Use a Logo.dev publishable key; it is built for client-side code.
  * Reference implementation: [https://www.logo.dev/docs/use-cases/integration-logos](https://www.logo.dev/docs/use-cases/integration-logos)
</Prompt>

## Code

This example is in React, but you can get the same result in any frontend framework: each tile is one image URL on a white well. Paste `IntegrationTile.tsx`, then map your catalog over it as the Usage tab shows.

<CodeGroup>
  ```tsx IntegrationTile.tsx theme={null}
  export function IntegrationTile({
    name,
    domain,
    token,
  }: {
    name: string;
    domain: string;
    token: string;
  }) {
    return (
      <div className="flex flex-col items-center gap-2.5 rounded-xl border border-zinc-950/10 bg-white px-3 py-5 dark:border-white/10 dark:bg-zinc-900">
        {/* Logos are designed for light backgrounds and some ship with baked
            white ones, so every logo sits on a white well. */}
        <span className="flex h-12 w-12 items-center justify-center rounded-lg bg-white">
          <img
            alt={`${name} logo`}
            className="h-7 w-7 rounded-md object-contain"
            height={28}
            loading="lazy"
            src={`https://img.logo.dev/${domain}?token=${token}&size=28&retina=true&format=webp`}
            width={28}
          />
        </span>
        <span className="text-xs font-medium">{name}</span>
      </div>
    );
  }
  ```

  ```tsx Usage theme={null}
  import { IntegrationTile } from "./IntegrationTile";

  const INTEGRATIONS = [
    { name: "Slack", domain: "slack.com" },
    { name: "GitHub", domain: "github.com" },
    { name: "Notion", domain: "notion.so" },
    { name: "Figma", domain: "figma.com" },
  ];

  export function IntegrationsGrid() {
    return (
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
        {INTEGRATIONS.map((tool) => (
          <IntegrationTile
            domain={tool.domain}
            key={tool.domain}
            name={tool.name}
            token="LOGO_DEV_PUBLISHABLE_KEY"
          />
        ))}
      </div>
    );
  }
  ```
</CodeGroup>

<Note>
  Your [publishable key](/docs/platform/api-keys) is built for client-side code, so
  you can ship it in the browser as-is.
</Note>

## How it works

* **Every logo is one image URL.** `img.logo.dev/:domain` returns the partner's logo, and `size`, `retina`, and `format=webp` handle the rendering. See all [image parameters](/docs/logo-images/introduction#parameters).
* **Rebrands handle themselves.** When a partner changes their logo, the same URL serves the new one. Adding a connector is one array entry; there is no asset to swap.
* **Unknown domains still render.** When Logo.dev doesn't have a logo, it returns a generated monogram instead of a broken image, so the grid works with any catalog you give it. See [fallback images](/docs/logo-images/introduction#fallback-images).
* **A white well keeps the grid uniform.** Logos are designed for light backgrounds, so each sits on a small white chip and lazy-loads as it scrolls into view.

## Make it your own

* **Go greyscale until hover.** Add `&greyscale=true` for a muted grid, or apply it conditionally so tiles gain color on hover. See all [image parameters](/docs/logo-images/introduction#parameters).
* **Turn the tiles into cards.** Use the [job board logos](/docs/use-cases/job-board-logos) pattern when each entry needs more than a logo and a name.
* **Animate the same catalog.** Feed the domains to the [animated logo wall](/docs/use-cases/animated-logo-wall) for a partners section on the landing page.

## Next steps

<CardGroup cols={2}>
  <Card title="Logo API" icon="image" href="/docs/logo-images/introduction">
    See every image URL parameter: size, format, theme, greyscale, and fallbacks.
  </Card>

  <Card title="Job board logos" icon="briefcase" href="/docs/use-cases/job-board-logos">
    Build the card-based sibling for listing feeds.
  </Card>
</CardGroup>
