CoolFace
Apppublic

Cortiq-Labs/iconclip-demo

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
App README

IconClip — Static Browser Demo

100% frontend-only Hugging Face Space. No Python, no GPU, no backend. Type a query, get the top-K matching icons across 11 open-license libraries, ranked by IconClip text→image cosine similarity. Everything — tokenisation, ONNX forward pass, cosine math, SVG rendering — runs in your tab.

How it works

  1. 1.On first load, the browser pulls the q8 text encoder (Cortiq-Labs/IconClip-ViT-L-14-text-encoder-ONNX, ~119 MB total: 113 MB ONNX + 7 MB tokeniser assets) via transformers.js v4.
  2. 2.In parallel, it fetches the pre-computed L2-normalised image embedding matrix (iconclip-vit-l-14.parquet, ~26 MB; 22 827 rows × 768 f32). The embedding parquet must be hosted alongside this Space (see Assets below).
  3. 3.Per query: tokenise → CLIPTextModelWithProjection forward (~30-60 ms on modern laptops, ~150 ms on phones) → dot against the matrix (vectors are already unit-norm so dot == cosine) → top-K argmax.
  4. 4.Per result: render the icon's SVG inline (fetched lazily per-library from the companion images parquet on first use, cached in the Cache API).

All slider / filter state is client-side. After the initial asset load the Space makes zero network calls except for the lazy per-library image parquet on first checkbox-enable.

Files

PathWhat it is
index.htmlEntry point. Pure HTML, ESM imports from CDN.
js/config.jsURLs + library list. Edit here to repoint to your own dataset.
js/engine.jstransformers.js text encoder loader + parquet embedding loader.
js/cosine.jsDot-product, normalisation, top-K. Pure math, browser-agnostic.
js/filters.jsLibrary checkbox state + corpus-id prefix filtering.
js/app.jsUI glue: debounced search, slider, chip handlers, render loop.
css/styles.cssLayout + colour tokens. Contrast ≥ 4.5:1 verified.
tests.htmlOpen in browser → runs cosine/filter unit tests against the DOM.

Asset hosting

This demo expects two companion parquets to live on a Hugging Face dataset:

{DATASET_REPO}/data/embeddings/iconclip-vit-l-14.parquet      # 26 MB, all 22 827 rows
{DATASET_REPO}/data/images/{library}.parquet                  # ~145 MB total across 11 libs

The embeddings parquet schema is:

_id:          STRING  (e.g. "lucide:bell")
embedding:    LIST<FLOAT>  (768-d, L2-normalised)

The per-library images parquet schema is:

_id:          STRING  (e.g. "lucide:bell")
svg_text:     STRING  (raw SVG markup, ready for innerHTML)

URLs are configured in js/config.js. As of this Space's publication the embedding parquet has not yet been uploaded to the iconclip-search-benchmark dataset (which is text-metadata-only — see its README). Once embeddings ship to that dataset or a sibling, point config.EMBEDDINGS_URL at the resolve URL.

Running locally

No build step. Just open index.html over HTTP (file:// won't work — ONNX Runtime Web needs proper MIME types for the .wasm files):

bash
cd spaces/iconclip-demo-static
python3 -m http.server 7860
# → http://127.0.0.1:7860

Or with any other static server (npx serve, caddy file-server, …).

Performance

Measured on a 2024 laptop (M2-class, 16 GB) over a 200 Mbps connection:

StageTimeBytes over wire
Page + JS load~50 ms< 50 KB
Encoder cold load (first visit)~3-4 s~119 MB
Encoder warm (subsequent visits)~150 ms0 (browser cache)
Embeddings parquet load~1 s~26 MB
Per-query inference + top-50 over 22 827~80-150 ms0

Time-to-first-search on cold load: ~5 s (encoder + parquet in parallel). After cache warm: ~300 ms.

Browser support

Tested on Chromium 130+, Firefox 130+, Safari 18+. WebAssembly SIMD is required (universal among the above). WebGPU is opt-in — the demo defaults to WASM for portability; flip config.DEVICE to 'webgpu' for a 5-10× speed-up on supporting browsers.

License

MIT. Model weights, tokeniser assets, and per-icon SVGs each carry their own upstream licenses (see the IconClip Search Benchmark dataset card).