Nomic Embed Browser — Cache Inspector
by Zatcepin
HTML
<base target="_blank">
<div class="container">
<h1>Nomic Embed Browser</h1>
<p class="subtitle">Inspect IndexedDB cache, load models, and run embeddings locally</p>
<!-- Cache Inspector -->
<div class="card">
<h2>IndexedDB Cache</h2>
<div class="cache-grid">
<div class="stat">
<div class="stat-label">Total Cached</div>
<div class="stat-value" id="cacheTotal">—</div>
</div>
<div class="stat">
<div class="stat-label">Files</div>
<div class="stat-value" id="cacheFiles">—</div>
</div>
<div class="stat">
<div class="stat-label">Model Status</div>
<div class="stat-value" id="modelStatus">Not loaded</div>
</div>
<div class="stat">
<div class="stat-label">Backend</div>
<div class="stat-value" id="backendStatus">—</div>
</div>
</div>
<div class="file-list" id="fileList" style="display:none;"></div>
<div class="btn-row">
<button class="btn-ghost" id="refreshCacheBtn">Refresh Cache Info</button>
<button class="btn-danger" id="clearCacheBtn">Clear Cache</button>
<button class="btn-primary" id="loadModelBtn">Load Model</button>
</div>
<div class="progress-wrap" id="progressWrap">
<div class="progress-bar"><div class="progress-fill" id="progressFill"></div></div>
<div class="progress-text" id="progressText">0%</div>
</div>
<div class="log" id="cacheLog"></div>
</div>
<!-- Embedding -->
<div class="card">
<h2>Generate Embedding</h2>
<textarea id="textInput" placeholder="search_query: What is matryoshka embedding?">search_query: What is matryoshka embedding?</textarea>
<div class="btn-row">
<button class="btn-primary" id="embedBtn" disabled>Get Embedding</button>
<button class="btn-ghost" id="copyBtn" disabled>Copy...
CSS
:root {
--bg: #0f0f11;
--surface: #1a1a1e;
--surface-2: #232328;
--border: #2a2a30;
--text: #e8e8ec;
--text-dim: #909098;
--accent: #5b8cff;
--accent-hover: #7aa3ff;
--danger: #ff5b5b;
--danger-hover: #ff7a7a;
--success: #4ade80;
--warn: #fbbf24;
--radius: 10px;
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--mono: "SF Mono", Monaco, "Cascadia Code", monospace;
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: var(--font);
line-height: 1.5;
padding: 24px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
h1 {
font-size: 1.5rem;
margin: 0 0 4px 0;
font-weight: 600;
}
.subtitle {
color: var(--text-dim);
font-size: 0.9rem;
margin-bottom: 24px;
}
/* Cards */
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 20px;
margin-bottom: 16px;
}
.card h2 {
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-dim);
margin: 0 0 12px 0;
font-weight: 600;
}
/* Cache status grid */
.cache-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
}
.stat {
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 14px;
}
.stat-label {
font-size: 0.75rem;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 4px;
}
.stat-value {
font-size: 1.1rem;
font-weight: 600;
font-family: var(--mono);
}
...
JavaScript
import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';
// ── Config ──
const MODEL_ID = 'nomic-ai/nomic-embed-text-v1.5';
const DB_NAME = 'transformers-cache';
const DB_VERSION = 1;
// ── State ──
let extractor = null;
let isLoading = false;
// ── DOM refs ──
const $ = id => document.getElementById(id);
const cacheTotal = $('cacheTotal');
const cacheFiles = $('cacheFiles');
const modelStatus = $('modelStatus');
const backendStatus = $('backendStatus');
const fileList = $('fileList');
const progressWrap = $('progressWrap');
const progressFill = $('progressFill');
const progressText = $('progressText');
const cacheLog = $('cacheLog');
const embedBtn = $('embedBtn');
const copyBtn = $('copyBtn');
const embedOutput = $('embedOutput');
const embedLog = $('embedLog');
// ── Helpers ──
function fmtBytes(b) {
if (b === 0) return '0 B';
const k = 1024;
const sizes = ['B','KB','MB','GB'];
const i = Math.floor(Math.log(b) / Math.log(k));
return parseFloat((b / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function log(el, msg, type = '') {
el.textContent = msg;
el.className = 'log ' + type;
}
function setLoading(loading) {
isLoading = loading;
$('loadModelBtn').disabled = loading;
$('clearCacheBtn').disabled = loading;
$('refreshCacheBtn').disabled = loading;
if (loading) {
progressWrap.classList.add('active');
} else {
progressWrap.classList.remove('active');
progressFill.style.width = '0%';
progressText.textContent = '0%';
}
}
// ── IndexedDB Inspection ──
async function inspectCache() {
cacheTotal.textContent = '—';
cacheFiles.textContent = '—';
fileList.style.display = 'none';
fileList.innerHTML = '';
...