Skip to content

Releases: clawnify/logokit

v0.3.0

Choose a tag to compare

@pallaoro pallaoro released this 29 Jul 12:42

Stale-index results now degrade to a favicon, not to nothing

The bundled index is a snapshot of a registry that moves — upstream touched the
icon data on 25 separate days in the last fortnight, and occasionally renames a
slug (SMMIXBlogent).

An added brand was always fine: lookup misses, the chain falls through to the
favicon tier. A renamed one was not — resolution succeeded against the stale
index, the URL 404'd, and because logo() stops at the first provider that
resolves, nothing else was ever tried. The documented onError handler could
only hide the image.

logo() now attaches the rest of the chain as fallback, resolved recursively:

<img
  src={hit.url}
  onError={(e) => { if (hit.fallback) e.currentTarget.src = hit.fallback.url; }}
/>

The same shape covers thesvg.org being unreachable — a single origin sits behind
every vector URL the library emits.

fallback is absent when nothing else can serve the query: format: "vector"
excludes raster by design, and a brand-name query has no domain for the favicon
tier. fetchLogo() already walked past failing providers and is unchanged.

Additive only — no breaking changes.

v0.2.0

Choose a tag to compare

@pallaoro pallaoro released this 29 Jul 12:37

Raster-only entry point

import { logo } from "@clawnify/logokit/gstatic";

Same favicon tier, size-snapping and status-gated fetchLogo as the main entry,
without the 6,492-brand index in its module graph.

Bundlers already tree-shook the index away — importing gstatic from the main
entry is 636 B gzipped versus 109 KB for logo(). Node and Workers don't
tree-shake: they evaluate the whole graph on import, so the main entry costs a
few ms and ~1.4 MB of heap per cold start even when nothing is resolved.
This entry costs ~186 KB.

Resolves domains only — brand names need the index by definition. Prefer the
main entry unless you've measured and care; vectors where they exist are the
point of the library.

A test asserts the index never reappears in this entry's graph, so the isolation
can't regress silently.

No breaking changes.

v0.1.0

Choose a tag to compare

@pallaoro pallaoro released this 29 Jul 12:32

First release.

Resolves a domain, URL, email address, or brand name to a logo URL.
theSVG supplies real vectors for 6,492 brands; Google's favicon endpoint
covers everything else as PNG.

import { logo } from "@clawnify/logokit";

logo("stripe.com");   // svg · thesvg
logo("acme-inc.io");  // png · gstatic

Resolution is offline. A generated index maps 3,547 domains and 5,399 name
forms onto slugs, so a miss costs nothing and never burns a request.

Notes

  • format is part of the contract. The fallback tier only ever returns raster,
    so callers are told what they got rather than handed a favicon that looks like
    a vector until it scales. format: "vector" opts out of the fallback.
  • Shared homepages are never guessed. ~500 OSS projects list github.com and
    ~630 Azure marks list azure.microsoft.com; mapping a shared domain to an
    arbitrary member returns the wrong brand. The 71 domains that stay ambiguous
    are dropped to the favicon tier and listed in ambiguous-domains.json.
  • Providers are plain objects and the chain is an ordered array, so adding a
    source is a local change.

Logos are trademarks of their respective owners, referenced for identification
under nominative fair use. Per-mark licenses vary — see NOTICE.md.