Skip to main content
The strongest moment to show a logo is during signup: a new user types their work email, and your product greets them with their own brand. That flash of recognition turns a generic form into something that already feels like their workspace. As the user types, the preview pane flips from a grey placeholder to their company’s logo and name. Every logo is a Logo API image URL built from the domain after the @, so there is nothing to look up or store.

Demo

Type any work email: The preview brands itself live from img.logo.dev as you type; try a domain nobody has heard of and you still get a monogram.

Build it with AI

Want a branded signup preview in your app? This prompt gives your AI coding tool everything it needs to build it in your framework.

Open in Cursor

Code

This example is in React, but you can get the same result in any frontend framework: the preview is one image URL rebuilt as the input changes. OnboardingPreview.tsx is the whole component, and the Usage tab renders it with your publishable key.
import { useMemo, useState } from "react";

export function OnboardingPreview({ token }: { token: string }) {
  const [email, setEmail] = useState("");

  const domain = useMemo(() => {
    const at = email.indexOf("@");
    if (at === -1) {
      return null;
    }
    const candidate = email.slice(at + 1).trim().toLowerCase();
    return candidate.includes(".") ? candidate : null;
  }, [email]);

  const company = useMemo(() => {
    if (!domain) {
      return null;
    }
    const name = domain.split(".")[0];
    return name.charAt(0).toUpperCase() + name.slice(1);
  }, [domain]);

  return (
    <div className="grid max-w-2xl items-center gap-6 sm:grid-cols-2">
      <div>
        <label
          className="mb-2 block text-sm font-medium"
          htmlFor="signup-email"
        >
          Work email
        </label>
        <input
          className="w-full rounded-xl border border-zinc-950/10 bg-white px-4 py-3 text-base focus:outline-none focus:ring-2 focus:ring-zinc-950/20 dark:border-white/20 dark:bg-zinc-900 dark:text-white"
          id="signup-email"
          onChange={(e) => setEmail(e.target.value)}
          placeholder="you@stripe.com"
          type="email"
          value={email}
        />
      </div>
      <div className="rounded-xl border border-zinc-950/10 bg-white p-4 dark:border-white/10 dark:bg-zinc-900">
        <div className="flex items-center gap-3">
          {domain ? (
            <img
              alt={`${company} logo`}
              className="h-9 w-9 rounded-lg object-contain"
              height={36}
              key={domain}
              src={`https://img.logo.dev/${domain}?token=${token}&format=webp&retina=true&size=72`}
              width={36}
            />
          ) : (
            <div className="h-9 w-9 rounded-lg bg-zinc-200 dark:bg-zinc-700" />
          )}
          <div className="min-w-0">
            <div className="truncate text-sm font-semibold">
              {company ? `${company} workspace` : "Your workspace"}
            </div>
            <div className="truncate text-xs text-zinc-400">
              {domain ?? "yourcompany.com"}
            </div>
          </div>
        </div>
        <div className="mt-4 space-y-2">
          <div className="h-2 w-3/4 rounded bg-zinc-100 dark:bg-zinc-800" />
          <div className="h-2 w-1/2 rounded bg-zinc-100 dark:bg-zinc-800" />
          <div className="h-2 w-2/3 rounded bg-zinc-100 dark:bg-zinc-800" />
        </div>
      </div>
    </div>
  );
}
Your publishable key is built for client-side code, so you can ship it in the browser as-is.

How it works

  • One image URL returns the logo. img.logo.dev/:domain serves it, and size, retina, and format parameters keep the preview sharp and light. See all image parameters.
  • The domain comes from the email. Everything after the @ is the lookup key, so identifying the company costs zero API calls.
  • Unknown domains still look intentional. Logo.dev serves a generated monogram when it has no logo for a domain, so a startup nobody has heard of still gets a branded preview. See fallback images.
  • The preview holds still. The logo slot keeps one fixed size whether it shows the placeholder, a monogram, or the real logo.

Make it your own

  • Skip free email providers. Keep a small denylist for domains like gmail.com and show the neutral placeholder instead, the way the logo from a domain example handles missing logos.
  • Pre-fill the company name. Resolve the domain with the Search API on the server to get the proper name instead of a capitalized domain.
  • Theme the whole page. The Brand API returns colors and other assets to brand more than the logo slot.

Next steps

Brand API

Get full brand profiles: logo, brandmark, banners, and colors.

Logo from a domain

Render your own fallback instead of the monogram.