Zurück

Integrationskochbuch

Unternehmenslogos in Ihre App einfügen – Copy-Paste-Rezepte

Produktionsreife Ausschnitte zum Hinzufügen von Unternehmenslogos zu Ihrer UI, von einem einfachen img-Tag bis React, Next.js Image, Tailwind-Avatare, Dark-Mode-Verwaltung, OG-Fallbacks und serverseitiges Signing.

Praktische Ausschnitte für die gängigen Formen, in denen ein Logo auftaucht: ein <img>-Tag, eine React-Komponente, ein Next.js Image, ein Tailwind-Avatar-Platz, ein Dark-Mode-bewusstes <picture>-Element, ein OG-Bild-Fallback und eine serversignierte URL. Jeder Ausschnitt funktioniert gegen den öffentlichen https://api.clearlogo.dev-Endpoint.

Alle Beispiele gehen davon aus, dass Sie einen Browser-Key (für Client-Code) oder einen Server-Key (für Backend-Code) haben. Erstellen Sie einen Key aus dem Dashboard.

1. Einfaches HTML

Schnellstmögliche Integration – fügen Sie die URL in ein <img>-Tag ein.

<img
  src="https://api.clearlogo.dev/logo/github.com?size=64&content=80&token=YOUR_BROWSER_KEY"
  alt="GitHub"
  width="64"
  height="64"
/>

Stellen Sie size auf die gerenderte Dimension ein, damit der Browser keine Bandbreite bei der Skalierung eines größeren Assets verschwendet.

2. React-Komponente

Eine kleine wiederverwendbare Komponente deckt die meisten Anforderungen der Produkt-UI ab.

type CompanyLogoProps = {
  domain: string;
  size?: 32 | 48 | 64 | 96 | 128;
  alt?: string;
};

const BROWSER_KEY = process.env.NEXT_PUBLIC_CLEARLOGO_KEY!;

export function CompanyLogo({ domain, size = 64, alt }: CompanyLogoProps) {
  return (
    <img
      src={`https://api.clearlogo.dev/logo/${domain}?size=${size}&content=80&token=${BROWSER_KEY}`}
      alt={alt ?? `${domain} logo`}
      width={size}
      height={size}
      loading="lazy"
      decoding="async"
    />
  );
}

loading="lazy" und decoding="async" halten lange Listen (CRMs, Verzeichnisse, Kontentabellen) davon ab, das Rendering zu blockieren.

3. Next.js <Image>

Fügen Sie den API-Host einmal zu next.config.js hinzu, verwenden Sie dann überall die optimierte <Image>-Komponente.

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      { protocol: "https", hostname: "api.clearlogo.dev" },
    ],
  },
};
import Image from "next/image";

export function CompanyLogo({ domain, size = 64 }: { domain: string; size?: number }) {
  return (
    <Image
      src={`https://api.clearlogo.dev/logo/${domain}?size=${size * 2}&content=80&token=${process.env.NEXT_PUBLIC_CLEARLOGO_KEY}`}
      alt={`${domain} logo`}
      width={size}
      height={size}
      unoptimized
    />
  );
}

Fordern Sie size * 2 für Retina-Schärfe auf HiDPI-Displays an. Verwenden Sie unoptimized, wenn Sie die WebP-Verhandlung von der API zum Client durchlassen möchten; entfernen Sie ihn, wenn Sie die Formatverhandlung von Next.js selbst durchführen lassen möchten.

4. Tailwind-Avatar-Slot

Platzieren Sie das Logo in einem festen UI-Slot, das über Marken hinweg visuell konsistent bleibt.

<div className="flex items-center gap-3">
  <div className="h-10 w-10 overflow-hidden rounded-md bg-neutral-100 ring-1 ring-neutral-200">
    <img
      src={`https://api.clearlogo.dev/logo/${domain}?size=64&content=80&token=${BROWSER_KEY}`}
      alt=""
      className="h-full w-full object-contain"
    />
  </div>
  <div>
    <div className="font-medium">{name}</div>
    <div className="text-sm text-neutral-500">{domain}</div>
  </div>
</div>

object-contain plus eine feste Slot-Größe ist die zuverlässigste Form für Tabellen und Listen. Koppeln Sie mit dem content=80-Parameter, sodass das Logo nie gegen den Slot-Rand stößt.

Verwenden Sie <picture> mit prefers-color-scheme, damit der Browser Dark/Light-Varianten zur Render-Zeit austauscht – null JavaScript, null Re-Renders und null Pro-Logo-Hooks in einer Liste von 50.

<picture>
  <source
    srcset="https://api.clearlogo.dev/logo/github.com?size=64&theme=dark&token=YOUR_BROWSER_KEY"
    media="(prefers-color-scheme: dark)"
  />
  <img
    src="https://api.clearlogo.dev/logo/github.com?size=64&theme=light&token=YOUR_BROWSER_KEY"
    alt="GitHub"
    width="64"
    height="64"
  />
</picture>

Verpackt als React-Komponente:

export function CompanyLogo({ domain, size = 64 }: { domain: string; size?: number }) {
  const base = `https://api.clearlogo.dev/logo/${domain}?size=${size}&content=80&token=${BROWSER_KEY}`;
  return (
    <picture>
      <source srcSet={`${base}&theme=dark`} media="(prefers-color-scheme: dark)" />
      <img src={`${base}&theme=light`} alt={`${domain} logo`} width={size} height={size} />
    </picture>
  );
}

Die API weicht zur Light-Variante aus, wenn keine Dark-Version existiert, daher ist es immer sicher, theme=dark anzufordern. Für App-Level-Theme-Switches (nicht OS-Level) treiben Sie die Quell-URL von Ihrem Theme-Status statt prefers-color-scheme an.

6. List Rendering mit Platzhalter

Für lange Listen, rendern Sie einen sofortigen Platzhalter, sodass leere Slots nicht blinken.

function LogoCell({ domain }: { domain: string }) {
  const [loaded, setLoaded] = useState(false);
  return (
    <div className="relative h-10 w-10 rounded-md bg-neutral-100">
      <img
        src={`https://api.clearlogo.dev/logo/${domain}?size=64&content=80&token=${BROWSER_KEY}`}
        alt=""
        loading="lazy"
        onLoad={() => setLoaded(true)}
        className={`h-full w-full object-contain transition-opacity ${
          loaded ? "opacity-100" : "opacity-0"
        }`}
      />
    </div>
  );
}

7. Error-Fallback mit dem ersten Buchstaben

Wenn die API kein Logo für eine Domain findet, rendern Sie stattdessen einen deterministischen Buchstaben-Avatar.

function LogoOrFallback({ domain, name }: { domain: string; name: string }) {
  const [errored, setErrored] = useState(false);

  if (errored) {
    return (
      <div className="flex h-10 w-10 items-center justify-center rounded-md bg-neutral-200 font-medium text-neutral-600">
        {name[0]?.toUpperCase() ?? "?"}
      </div>
    );
  }

  return (
    <img
      src={`https://api.clearlogo.dev/logo/${domain}?size=64&content=80&token=${BROWSER_KEY}`}
      alt={`${name} logo`}
      width={40}
      height={40}
      className="rounded-md"
      onError={() => setErrored(true)}
    />
  );
}

Der Fallback sendet niemals eine Netzwerkanfrage, daher bleiben auch kalte Zeilen zügig.

8. Open Graph Bild-Fallback

Betten Sie ein Logo über einen serverseitigen Fetch in Ihr eigenes dynamisch generiertes OG-Bild ein.

// app/og/route.ts (Next.js, Edge runtime)
import { ImageResponse } from "next/og";

export const runtime = "edge";

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const domain = searchParams.get("domain") ?? "example.com";

  const logoUrl = `https://api.clearlogo.dev/logo/${domain}?size=256&content=80&token=YOUR_SERVER_KEY`;

  return new ImageResponse(
    (
      <div style={{ display: "flex", alignItems: "center", padding: 64 }}>
        <img src={logoUrl} width={128} height={128} alt="" />
        <span style={{ marginLeft: 32, fontSize: 64 }}>{domain}</span>
      </div>
    ),
    { width: 1200, height: 630 },
  );
}

Verwenden Sie hier einen Server-Key, keinen Browser-Key – Edge-Funktionen sind serverseitig, und ein Server-Key ist das, was unrestricted Origin-Header übersteht.

9. Backend-Signing für sensible UIs

Wenn Sie die URL nicht öffentlich machen möchten (z.B. interne Admin-Tools), proxen Sie über Ihr Backend.

// app/api/logo/[domain]/route.ts (Next.js)
export async function GET(
  request: Request,
  { params }: { params: { domain: string } },
) {
  const upstream = await fetch(
    `https://api.clearlogo.dev/logo/${params.domain}?size=128&content=80`,
    { headers: { Authorization: `Bearer ${process.env.CLEARLOGO_SERVER_KEY}` } },
  );
  return new Response(upstream.body, {
    headers: {
      "Content-Type": upstream.headers.get("Content-Type") ?? "image/png",
      "Cache-Control": "public, max-age=86400, s-maxage=86400",
    },
  });
}

Jetzt verwendet Ihr Frontend /api/logo/{domain} – kein API-Key in der Page-Source, und Sie kontrollieren das Caching bei Ihrem eigenen CDN.

10. TypeScript-Helfer

Ein einziger Helfer hält die URL-Konstruktion über die Codebasis konsistent.

type LogoOptions = {
  size?: 16 | 32 | 48 | 64 | 96 | 128 | 192 | 256 | 512 | 1024;
  content?: number; // 50–100, step 5
  theme?: "light" | "dark";
  format?: "png" | "webp" | "jpeg";
};

export function logoUrl(domain: string, opts: LogoOptions = {}): string {
  const params = new URLSearchParams({
    size: String(opts.size ?? 64),
    content: String(opts.content ?? 80),
    token: process.env.NEXT_PUBLIC_CLEARLOGO_KEY!,
  });
  if (opts.theme) params.set("theme", opts.theme);
  if (opts.format) params.set("format", opts.format);
  return `https://api.clearlogo.dev/logo/${encodeURIComponent(domain)}?${params}`;
}

encodeURIComponent schützt vor ungewöhnlichen Zeichen in Domains und macht den Helfer sicher zu aufzurufen mit nicht vertrautem Input.

11. Preconnect zur frühen Erwärmung der Verbindung

Für Dashboards, die Dutzende von Logos über dem Falz rendern, zahlt die erste Anfrage für DNS, TCP und TLS. Fügen Sie einen einzigen <link rel="preconnect"> in Ihren Document Head ein, damit die Verbindung bereit ist, bevor das erste <img> trifft – jedes nachfolgende Logo erhält einen Kopfstart ohne Per-URL-Preload-Bloat.

<link rel="preconnect" href="https://api.clearlogo.dev" crossorigin />
<link rel="dns-prefetch" href="https://api.clearlogo.dev" />
// Next.js
import Head from "next/head";

export function ClearLogoPreconnect() {
  return (
    <Head>
      <link rel="preconnect" href="https://api.clearlogo.dev" crossOrigin="" />
      <link rel="dns-prefetch" href="https://api.clearlogo.dev" />
    </Head>
  );
}

preconnect löst DNS auf und öffnet den TCP/TLS-Handshake sofort; dns-prefetch ist ein billiger Fallback für Browser, die preconnect ignorieren. Zwei Hinweise insgesamt, egal wie viele Logos die Seite rendert. Bevorzugen Sie dies gegenüber <link rel="preload" as="image"> pro Logo – Preloads sind gewichtig, zählen zu Bandbreitenetats, und helfen nicht, wenn die gerenderte URL am Ende etwas anders ausfällt (Größe, Theme, Token) als die vorgeladene.

FAQ

Mit welchem Rezept sollte ich beginnen?

Für ein einzelnes Logo ist das einfache <img>-Rezept ausreichend. Für Listen und Tabellen, beginnen Sie mit dem Tailwind-Avatar-Slot + Lazy-Load-Muster.

Benötige ich einen Key zum Testen?

Nein. Der Endpoint funktioniert anonym für Low-Volume-Browsing. Fügen Sie einen Browser-Key hinzu, bevor Sie zur Produktion ausrollen, damit die Anfrage richtig zugeordnet und gegen Ihren Plan gezählt wird.

Welche Größe sollte ich anfordern?

Passen Sie die gerenderte Größe in CSS an, fordern Sie dann 2x das für Retina-Schärfe an. Fordern Sie nicht 1024 für einen 32-Pixel-Slot an – es kostet Bandbreite und sieht nicht besser aus.

Wie handhabers Dark Mode ohne JavaScript?

Verwenden Sie ein <picture>-Element mit einem <source>, das durch media="(prefers-color-scheme: dark)" limitiert ist. Der Browser wählt die richtige URL zur Render-Zeit – kein React Hook, kein Re-Render pro Logo, keine Pro-Zeilen-Overhead auch in langen Listen.

Wie lasse ich eine Liste von Logos schneller laden?

Fügen Sie einen einzigen <link rel="preconnect" href="https://api.clearlogo.dev"> in Ihren Document Head ein. Das öffnet DNS/TCP/TLS einmal für jedes Logo auf der Seite, was billiger ist als <link rel="preload"> pro URL.

Wie zeige ich einen Fallback, wenn die API kein Logo zurückgibt?

Hören Sie auf onError auf dem <img> und tauschen Sie einen Buchstaben-Avatar oder ein generisches Symbol aus. Das Error-Fallback-Rezept oben ist die Produktionsform.

Kann ich einen Browser-Key von einem Server-Side-Render verwenden?

Sie können – aber ein Server-Key passt besser, da er die Anfrage über Authorization: Bearer … sendet statt sich auf Origin-Checks zu verlassen. Für Next.js Server Components, OG-Routen oder Backend-Proxies, verwenden Sie einen Server-Key.

Wie cache ich Logos bei meinem eigenen CDN?

Verwenden Sie das Backend-Signing-Rezept oben. Die upstream-Antwort enthält langlebige Cache-Control, daher können Sie die gleichen Header auf Ihrem Proxy setzen und Ihren CDN den Rest überlassen.

Echte Domain im Playground ausprobieren

Sobald die Rezeptform richtig aussieht, tauschen Sie einige Ihrer eigenen Kunden- oder Partner-Domains aus und schauen Sie sich die Vorschau an, bevor Sie versenden.