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

> 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](https://clearlogo.dev/login?lang=de) aus dem Dashboard.

## 1. Einfaches HTML

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

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

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

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

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

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

## 5. Dark-Mode-bewusstes Logo

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.

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

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

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

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

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

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

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

```html
<link rel="preconnect" href="https://api.clearlogo.dev" crossorigin />
<link rel="dns-prefetch" href="https://api.clearlogo.dev" />
```

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