
# Suelta un logotipo de empresa en tu aplicación — recetas de copiar y pegar

> Fragmentos prácticos para las formas comunes en que un logotipo termina: una etiqueta `<img>`, un componente React, una Next.js Image, una ranura de avatar Tailwind, un elemento `<picture>` consciente del modo oscuro, un respaldo de imagen OG y una URL firmada del servidor. Cada fragmento funciona contra el endpoint público `https://api.clearlogo.dev`.
>
> Todos los ejemplos asumen que tienes una clave de navegador (para código de cliente) o una clave de servidor (para código de backend). [Crea una clave](https://clearlogo.dev/login?lang=es) desde el dashboard.

## 1. HTML simple

Integración más rápida posible — pega la URL en una etiqueta `<img>`.

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

Establece `size` para que coincida con la dimensión renderizada para que el navegador no desperdicie ancho de banda escalando un activo más grande.

## 2. Componente React

Un pequeño componente reutilizable cubre la mayoría de las necesidades de interfaz de usuario del producto.

```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"` y `decoding="async"` mantienen listas largas (CRM, directorios, tablas de cuentas) de bloquear la pintura.

## 3. Next.js `<Image>`

Agrega el host de la API a `next.config.js` una sola vez, luego usa el componente `<Image>` optimizado en todas partes.

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

Solicita `size * 2` para nitidez retina en pantallas HiDPI. Usa `unoptimized` si deseas que la negociación WebP de la API fluya hacia el cliente; elimínalo si deseas que Next.js maneje la negociación de formato en sí.

## 4. Ranura de avatar Tailwind

Suelta el logotipo en una ranura de UI fija que se mantiene visualmente consistente en todas las marcas.

```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` más un tamaño de ranura fijo es la forma más confiable para tablas y listas. Empareja con el parámetro `content=80` para que el logotipo nunca llegue al borde de la ranura.

## 5. Logotipo consciente del modo oscuro

Usa `<picture>` con `prefers-color-scheme` para cambiar variantes oscuro/claro en tiempo de pintura, sin JavaScript o rerenders por logotipo.

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

Envuelto como un componente React:

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

La API vuelve a la variante clara cuando no existe una versión oscura, así que siempre es seguro solicitar `theme=dark`. Para cambios de tema a nivel de aplicación (no a nivel del sistema operativo), controla la URL de origen desde tu estado de tema en lugar de `prefers-color-scheme`.

## 6. Renderizado de lista con un marcador de posición

Para listas largas, renderiza un marcador de posición inmediato para que las ranuras vacías no parpadeen.

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

El fondo neutral llena la ranura al instante, y el logotipo se desvanece una vez decodificado.

## 7. Respaldo de error con la primera letra

Si la API no puede encontrar un logotipo para un dominio, renderiza un avatar de letra determinista en su lugar.

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

El respaldo nunca realiza una solicitud de red, así que incluso las filas frías se mantienen rápidas.

## 8. Respaldo de imagen Open Graph

Utiliza una búsqueda del lado del servidor para incrustar un logotipo en tu propia tarjeta OG generada dinámicamente.

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

Usa una clave de **servidor** aquí, no una clave de navegador — Las funciones Edge son del lado del servidor, y una clave de servidor es lo que sobrevive a encabezados de origen sin restricciones.

## 9. Firma del backend para interfaces UI sensibles

Cuando no deseas que la URL sea pública (p. ej. herramientas administrativas internas), procesa a través de tu 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",
    },
  });
}
```

Sin clave de API en el origen de la página, y controlas el almacenamiento en caché en tu propio CDN.

## 10. Asistente de TypeScript

Un único asistente mantiene la construcción de URL consistente en toda la base de código.

```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` protege contra caracteres inusuales en dominios y hace que el asistente sea seguro para llamar con entrada no confiable.

## 11. Preconectarse para calentar la conexión temprano

Para dashboards que renderizan docenas de logotipos encima de la carpeta, la primera solicitud paga por DNS, TCP y TLS. Agrega un único `<link rel="preconnect">` al encabezado de tu documento para que la conexión esté lista antes de que el primer `<img>` se active — cada logotipo posterior obtiene una ventaja sin la masa de precargas por URL.

```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` resuelve DNS y abre el apretón de manos TCP/TLS inmediatamente; `dns-prefetch` es un respaldo económico para navegadores que ignoran la preconexión. Dos sugerencias totales, sin importar cuántos logotipos renderice la página. Prefiere esto sobre `<link rel="preload" as="image">` por logotipo — las precargas son pesadas, cuentan hacia presupuestos de ancho de banda, y no ayudan si la URL renderizada termina siendo ligeramente diferente (tamaño, tema, token) de la precargada.

## FAQ

### ¿Con cuál receta debo empezar?

Para un único logotipo, la receta `<img>` simple es suficiente. Para listas y tablas, salta a la ranura de avatar Tailwind y al patrón de carga perezosa.

### ¿Necesito una clave para probar?

No. El endpoint funciona anónimamente para navegación de bajo volumen. Agrega una clave de navegador antes de que envíes a producción para que la solicitud sea debidamente atribuida y contada contra tu plan.

### ¿Qué tamaño debo solicitar?

Coincide el tamaño renderizado en CSS, luego solicita `2x` eso para nitidez retina. No solicites `1024` para una ranura de 32 píxeles — cuesta ancho de banda y no se ve mejor.

### ¿Cómo manejo el modo oscuro sin JavaScript?

Usa un elemento `<picture>` con una `<source>` restringida por `media="(prefers-color-scheme: dark)"`. El navegador elige la URL correcta en tiempo de pintura — no hook React, no rerender por logotipo, no gastos generales por fila incluso en listas largas.

### ¿Cómo hago que una lista de logotipos se cargue más rápido?

Agrega un único `<link rel="preconnect" href="https://api.clearlogo.dev">` en el encabezado de tu documento. Eso abre DNS/TCP/TLS una sola vez para cada logotipo en la página, que es más económico que `<link rel="preload">` por URL.

### ¿Cómo muestro un respaldo cuando la API no devuelve un logotipo?

Escucha `onError` en el `<img>` e intercambia por un avatar de letra o un icono genérico. La receta de respaldo de error anterior es la forma de producción.

### ¿Puedo usar una clave de navegador desde una renderización del lado del servidor?

Puedes — pero una clave de servidor es un mejor ajuste porque envía la solicitud vía `Authorization: Bearer …` en lugar de depender de controles de origen. Para Componentes de Servidor de Next.js, rutas OG, o proxies de backend, usa una clave de servidor.

### ¿Cómo almaceno logotipos en caché en mi propio CDN?

Utiliza la receta de firma de backend anterior. La respuesta ascendente incluye `Cache-Control` de larga duración, para que puedas establecer los mismos encabezados en tu proxy y dejar que tu CDN haga el resto.
