Skip to main content

Install

No framework peer dependencies required. The core engine runs anywhere with a DOM (canvas API).

createLogoSoup Engine

The core engine is what every framework adapter wraps. You can use it directly for vanilla JS apps, Web Components, or any framework that doesn’t have a dedicated adapter.

Engine API

createLogoSoup()

Creates a new engine instance. Each instance has its own image cache and state.

engine.process(options)

Triggers a processing run. Cancels any in-flight work from a previous process() call. Accepts all shared options.
Calling process() again with new options re-uses cached measurements for logos that haven’t changed. Only new logos trigger image loading.

engine.subscribe(listener)

Subscribes to state changes. Returns an unsubscribe function.
The listener receives no arguments. Call getSnapshot() inside the listener to read the current state. This design matches the pattern expected by React.useSyncExternalStore, Vue’s shallowRef, Svelte’s createSubscriber, and Solid’s from().

engine.getSnapshot()

Returns the current immutable state snapshot. Returns the same reference (===) when state hasn’t changed, which is critical for frameworks that use referential equality to avoid unnecessary re-renders.
The snapshot shape:
If some images fail but others succeed, the engine still transitions to "ready" with the successful logos. "error" only occurs when all images fail.

engine.destroy()

Cleans up the engine: revokes blob URLs, cancels in-flight work, clears the image cache, and removes all subscribers.
Always call destroy() when you’re done with the engine to avoid memory leaks from blob URLs.

Lifecycle

A typical lifecycle looks like:
Calling process() while a previous run is still loading cancels the in-flight work. Only the latest process() call’s results are emitted.

Re-processing on Option Changes

Call process() again whenever options change. The engine caches image measurements, so re-processing with the same logos but different baseSize or scaleFactor is synchronous (no network requests):
The cache is invalidated when contrastThreshold, densityAware, or backgroundColor change, since these affect the measurement itself.

Web Components Example

Usage:

Integrating with Other Frameworks

The subscribe/getSnapshot shape is designed to plug into any reactivity system. If your framework isn’t directly supported, the pattern is:
  1. Create an engine with createLogoSoup()
  2. Subscribe to changes and push snapshots into your framework’s reactive primitive
  3. Call process() when options change
  4. Call destroy() on teardown
This is exactly what the React, Vue, Svelte, Solid, and Angular adapters do, each in ~30-80 lines of framework-specific code.