返回

Integration cookbook

将公司徽标放入你的应用——复制粘贴食谱

生产就绪的片段,用于将公司徽标添加到你的UI,从普通img标签到React、Next.js Image、Tailwind头像、深色模式处理、OG后备和服务器端签名。

实用片段用于徽标最终出现的常见形状:一个<img>标签、一个React组件、一个Next.js Image、一个Tailwind头像插槽、一个深色模式感知<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>

将API主机添加到next.config.js一次,然后在任何地方使用优化的<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
    />
  );
}

请求size * 2用于HiDPI显示器上的Retina清晰度。如果你想要API中的WebP协商流向客户端,使用unoptimized;如果你想要Next.js自己处理格式协商,删除它。

4. Tailwind头像插槽

将徽标放入一个固定的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 },
  );
}

在这里使用服务器密钥,而不是浏览器密钥——Edge函数是服务器端的,服务器密钥在不受限制的源标头中存活。

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/logo/{domain}——页面源中没有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是忽略预连接的浏览器的廉价后备。总共两个提示,无论页面渲染多少徽标。相比每个徽标的<link rel="preload" as="image">更倾向于这个——预加载很重,计入带宽预算,如果渲染的URL最终与预加载的略有不同(大小、主题、令牌)也无助益。

常见问题

我应该从哪个食谱开始?

对于单个徽标,普通<img>食谱就足够了。对于列表和表,跳到Tailwind头像插槽和延迟加载模式。

我需要一个密钥用于测试吗?

否。端点对低体积浏览匿名工作。在你发布到生产前添加浏览器密钥,以便请求被正确归因并计入你的计划。

我应该请求什么大小?

匹配CSS中的渲染大小,然后请求2x用于Retina清晰度。不要为32像素插槽请求1024——它浪费带宽并看起来不会更好。

我如何在没有JavaScript的情况下处理深色模式?

使用由media="(prefers-color-scheme: dark)"门控的<picture>元素与<source>。浏览器在绘制时选择正确的URL——没有React钩子、没有每个徽标的重新渲染、长列表中没有每行开销。

我如何使徽标列表加载更快?

在你的文档标题中添加单个<link rel="preconnect" href="https://api.clearlogo.dev">。这为页面上的每个徽标打开一次DNS/TCP/TLS,这比每URL的<link rel="preload">便宜。

当API返回没有徽标时,我如何显示后备?

<img>上监听onError并交换字母头像或通用图标。上面的错误后备食谱是生产形状。

我可以从服务器端渲染使用浏览器密钥吗?

你可以——但服务器密钥是更好的拟合,因为它通过Authorization: Bearer …而不是依靠源检查发送请求。对于Next.js服务器组件、OG路由或后端代理,使用服务器密钥。

我如何在我自己的CDN处缓存徽标?

使用上面的后端签名食谱。上游响应包括长期Cache-Control,所以你可以在你的代理上设置相同的标题并让你的CDN做其余部分。

在操场中尝试真实域

一旦食谱形状看起来正确,交换你自己的几个客户或合作伙伴域并在你发布之前预览结果。