戻る

Integration cookbook

アプリに企業ロゴをドロップする — コピーペーストレシピ

プロダクション対応のスニペットで企業ロゴをUIに追加します。シンプルなimgタグからReact、Next.js Image、Tailwind avatar、ダークモード処理、OGフォールバック、サーバー側署名まで。

ロゴが終わる一般的な形についての実践的なスニペット:<img>タグ、Reactコンポーネント、Next.js Image、Tailwind avatarスロット、ダークモード対応の<picture>要素、OGイメージフォールバック、およびサーバー署名URL。すべてのスニペットはパブリックhttps://api.clearlogo.devエンドポイントに対して機能します。

すべての例は、ブラウザキー(クライアントコード用)またはサーバーキー(バックエンドコード用)を持っていることを想定しています。ダッシュボードからキーを作成します

1. プレーンHTML

最速可能な統合 — URLを<img>タグに貼り付けます。

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

sizeをレンダリング済みディメンションと一致させて、ブラウザがより大きなアセットをスケーリングして帯域幅を無駄にしないようにします。

2. Reactコンポーネント

小さな再利用可能なコンポーネントはほとんどのプロダクトUI要件をカバーします。

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"decoding="async"は長いリスト(CRM、ディレクトリ、アカウントテーブル)がペイントをブロックしないようにします。

3. Next.js <Image>

next.config.jsにAPIホストを一度追加し、その後、最適化された<Image>コンポーネントをどこでも使用します。

// 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
    />
  );
}

HiDPIディスプレイで網膜の鮮鋭度のためにsize * 2をリクエストします。WebP交渉がAPIからクライアントにフローするようにしたい場合はunoptimizedを使用します。Next.jsが形式交渉自体を処理するようにしたい場合は削除してください。

4. Tailwind avatarスロット

ロゴを固定されたUIスロットにドロップし、ブランド全体で視覚的に一貫性を保ちます。

<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に加えて固定のスロットサイズはテーブルとリストの最も確実な形です。ロゴがスロットエッジに触れないようにcontent=80パラメータとペアにしてください。

5. ダークモード対応ロゴ

<picture>prefers-color-schemeで使用してダーク/ライトバリアントをペイント時にスワップします。JavaScriptやロゴごとの再レンダーはゼロです。

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

Reactコンポーネントとしてラップ:

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>
  );
}

APIは暗いバージョンが存在しない場合はライトバリアントにフォールバックするため、theme=darkをリクエストすることは常に安全です。アプリレベルのテーマスイッチ(OSレベルではない)の場合は、prefers-color-schemeの代わりにテーマ状態から宛先URLを駆動します。

6. プレースホルダ付きリストレンダリング

長いリストの場合は、即座プレースホルダーをレンダリングし、空のスロットがフラッシュしないようにします。

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. 最初の文字付きエラーフォールバック

APIがドメインのロゴを見つけられない場合は、代わりに決定的な文字アバターをレンダリングします。

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)}
    />
  );
}

フォールバックはネットワークリクエストを実行しないため、たとえコールド行でもすばやくとどまります。

8. Open Graphイメージフォールバック

サーバー側フェッチを介して動的に生成されたOGイメージにロゴを埋め込みます。

// 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 },
  );
}

ブラウザキーではなくサーバーキーをここで使用します — エッジ関数はサーバー側であり、サーバーキーは制限されていないオリジンヘッダーを通じて存続するものです。

9. 機密UIのためのバックエンド署名

URLをパブリックにしたくない場合(例:内部管理ツール)、バックエンドを通じてプロキシします。

// 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",
    },
  });
}

ページソースにはAPIキーがなく、独自のCDNでキャッシング制御を実行します。

10. TypeScriptヘルパー

単一のヘルパーはコードベース全体でURL構築を一貫性保ちます。

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はドメイン内の一般的でない文字に対して保護し、ヘルパーを信頼できない入力で呼び出すことを安全にします。

11. 接続を早期にウォームするためのプリコネクト

ダッシュボードが数十個のロゴをフォールド上方でレンダリングする場合、最初のリクエストはDNS、TCP、およびTLSをカバーします。単一の<link rel="preconnect">をドキュメントヘッドに追加して、最初の<img>がヒットする前に接続が準備できるようにします — 後続のすべてのロゴはURL単位でプリロードのブロートウェアなしで先手を取ります。

<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はDNSを解決し、TCP/TLSハンドシェイクを直ちに開きます。dns-prefetchはプリコネクトを無視するブラウザの安価なフォールバックです。2つのヒント、ページがレンダリングするロゴの数に関係なくです。ロゴごとの<link rel="preload" as="image">を優先してください — プリロードは重量級であり、帯域幅予算に対してカウントし、レンダリングされたURLが僅かに異なる場合は役立ちません(サイズ、テーマ、トークン)プリロードされたものから。

FAQ

どのレシピから始めるべきですか?

単一のロゴの場合、シンプルな<img>レシピで十分です。リストとテーブルの場合は、Tailwind avatarスロット + ロゴ遅延ロードパターンから始めます。

テストのためにキーが必要ですか?

いいえ。エンドポイントは低ボリュームブラウジングのために匿名で機能します。ブラウザキーをプロダクションに配送する前に追加して、リクエストが適切に属され、プランに対してカウントされるようにします。

どのサイズをリクエストする必要がありますか?

CSSでレンダリングされたサイズを一致させ、その後、視網膜の鮮鋭度のために2xをリクエストします。32ピクセルスロットのために1024をリクエストしないでください — 帯域幅を消費し、見た目が良くなっていません。

JavaScriptなしでダークモードを処理する方法は?

media="(prefers-color-scheme: dark)"でゲート付きの<source>を持つ<picture>要素を使用します。ブラウザはペイント時に正しいURLを選択します — ReactフックなしでReactフック、ロゴごとのアサレンダーなし、長いリストでもロゴ単位のオーバーヘッドなし。

ロゴのリストをより高速に読み込むにはどうすればよいですか?

単一の<link rel="preconnect" href="https://api.clearlogo.dev">をドキュメントヘッドに追加します。これにより、ページ上のすべてのロゴに対してDNS/TCP/TLSが一度開きます。これはURL単位での<link rel="preload">よりも安価です。

APIがロゴを返さない場合、フォールバックを表示するにはどうすればよいですか?

<img>onErrorをリッスンし、文字アバターまたはジェネリックアイコンにスワップします。上記のエラーフォールバックレシピはプロダクション形状です。

サーバー側のレンダリングからブラウザキーを使用できますか?

できます — しかし、サーバーキーはより良いフィットです。なぜなら、オリジンチェックに依存するのではなく、Authorization: Bearer …を介してリクエストを送信するためです。Next.js Server Components、OGルート、またはバックエンドプロキシの場合は、サーバーキーを使用します。

独自のCDNでロゴをキャッシュするにはどうすればよいですか?

上記のバックエンド署名レシピを使用します。アップストリーム応答には長寿命Cache-Controlが含まれるため、プロキシで同じヘッダーを設定でき、CDNに残りを処理させることができます。

プレイグラウンドで実際のドメインを試す

レシピの形が適切に見えたら、数個の独自のカスタマーまたはパートナードメインをスワップして、配送する前に結果をプレビューしてください。