AI Model Directory

  • Home
  • Every model. Every provider. Always current.

Loading model directory...

(function() { 'use strict'; var TYPE_LABELS = { llm:'Language', image:'Image', video:'Video', tts:'Voice', composition:'Music', transcription:'Transcription', embedding:'Embedding', rerank:'Rerank', capability:'Capability', stem_separation:'Audio', '3d':'3D' }; var TYPE_ICONS = { llm:'icon-messages-square', image:'icon-image', video:'icon-video', tts:'icon-mic', composition:'icon-music', transcription:'icon-captions', embedding:'icon-brain', rerank:'icon-arrow-up-down', capability:'icon-sparkles', stem_separation:'icon-sliders-horizontal', '3d':'icon-box' }; var MAX_CTX = 2000000; // for bar scaling var allModels = [], allProviders = [], data = null; var currentView = 'grid', currentSort = { field: 'name', dir: 'asc' }; var compareSet = new Set(); var providerIcons = {}; // key -> icon URL // ── Helpers ── function esc(s) { if (!s) return ''; var d = document.createElement('div'); d.textContent = s; return d.innerHTML; } function formatCtx(n) { if (!n) return ''; if (n >= 1000000) return (n/1000000).toFixed(n%1000000===0?0:1)+'M'; if (n >= 1000) return (n/1000)+'K'; return n.toString(); } function formatPrice(rate) { if (!rate) return '-'; var perM = rate * 1000; if (perM < 0.01) return '<$0.01/M'; return '$' + perM.toFixed(2) + '/M'; } function formatDate(d) { return d ? d.substring(0,10) : ''; } function speedDots(speed) { if (!speed) return ''; var h = ''; for (var i=1;i<=5;i++) h += ''; return h+''; } function ctxBar(ctx) { if (!ctx) return ''; var MID = 1000000; var pct = ctx <= MID ? Math.sqrt(ctx/MID)*50 : 50+(ctx-MID)/(MAX_CTX-MID)*50; pct = Math.min(100, Math.max(2, pct)); return '
'+formatCtx(ctx)+' tokens'+formatCtx(MAX_CTX)+'
'; } function provIcon(m) { var icon = m.provider_icon || providerIcons[m.provider]; if (!icon) return ''; return ''; } function getModalities(m) { if (!m.modalities) return ''; var inp = (m.modalities.input || []).join(', '); var out = (m.modalities.output || []).join(', '); return inp + ' → ' + out; } // ── URL Params (Deep Links) ── function readParams() { var p = new URLSearchParams(window.location.search); return { type: p.get('type')||'', provider: p.get('provider')||'', status: p.get('status')||'', search: p.get('search')||'', view: p.get('view')||'grid' }; } function writeParams() { var p = new URLSearchParams(); var search = (document.getElementById('dir-search')||{}).value||''; var provider = (document.getElementById('dir-provider')||{}).value||''; var typePill = document.querySelector('.ai-dir-pill.active'); var type = typePill ? typePill.dataset.type : ''; var statusPill = document.querySelector('.ai-dir-status-pill.active'); var status = statusPill ? statusPill.dataset.status : ''; if (type) p.set('type', type); if (provider) p.set('provider', provider); if (status) p.set('status', status); if (search) p.set('search', search); if (currentView !== 'grid') p.set('view', currentView); var qs = p.toString(); history.replaceState(null, '', qs ? '?'+qs : window.location.pathname); } // ── Card Rendering ── function renderCard(m) { var badges = []; badges.push(''+(TYPE_LABELS[m.type]||m.type)+''); if (m.status==='deprecated') badges.push('Deprecated'); if (m.status==='sunset') badges.push('Sunset'); if (m.is_new && m.status==='active') badges.push('New'); if (m.vision) badges.push('Vision'); if (m.tools) badges.push('Tools'); if (m.capabilities && m.capabilities.indexOf('reasoning')!==-1) badges.push('Reasoning'); if (m.capabilities && m.capabilities.indexOf('search')!==-1) badges.push('Search'); var meta = []; if (m.context_window) meta.push(' '+formatCtx(m.context_window)+' ctx'); if (m.max_output) meta.push(' '+formatCtx(m.max_output)+' out'); if (m.speed) meta.push(''+speedDots(m.speed)+''); var pricing = ''; if (m.pricing) { var p = m.pricing; if (p.input || p.output) { pricing = '
'; if (p.input) pricing += '
Input'+formatPrice(p.input)+'
'; if (p.output) pricing += '
Output'+formatPrice(p.output)+'
'; pricing += '
'; } else if (p.unit) { pricing = '
Per unit$'+p.unit.toFixed(4)+'
'; } } var statusClass = m.status!=='active' ? ' status-'+m.status : ''; var statusDate = ''; if (m.deprecated_at) statusDate = '
Deprecated '+formatDate(m.deprecated_at)+'
'; if (m.sunset_at) statusDate = '
Sunset '+formatDate(m.sunset_at)+'
'; var checked = compareSet.has(m.key); var checkHtml = '
'+(checked?'':'')+'
'; return '
' + checkHtml + '
' + '
'+esc(m.name)+'
' + '
'+provIcon(m)+esc(m.provider_name)+'
' + '
' + '
'+badges.join('')+'
' + (m.description ? '
'+esc(m.description)+'
' : '') + statusDate + (meta.length ? '
'+meta.join('')+'
' : '') + (m.context_window ? ctxBar(m.context_window) : '') + pricing + '
'; } // ── Table Rendering ── function renderTable(models) { var html = '
'; html += '' + '' + '' + '' + '' + ''; models.forEach(function(m) { var features = []; if (m.vision) features.push('Vision'); if (m.tools) features.push('Tools'); if (m.capabilities && m.capabilities.indexOf('reasoning')!==-1) features.push('Reasoning'); if (m.streaming) features.push('Stream'); var inputP = m.pricing&&m.pricing.input ? formatPrice(m.pricing.input) : '-'; var outputP = m.pricing&&m.pricing.output ? formatPrice(m.pricing.output) : '-'; var rowStyle = (m.status==='sunset'||!m.enabled) ? ' style="opacity:0.5"' : ''; var badge = ''; if (m.status==='deprecated') badge = ' Deprecated'; else if (m.status==='sunset') badge = ' Sunset'; else if (m.is_new) badge = ' New'; var checked = compareSet.has(m.key); html += '' + '' + '' + '' + '' + '' + '' + '' + ''; }); html += '
Model Provider TypeContext InputOutputFeatures
'+(checked?'':'')+'
'+esc(m.name)+''+badge+''+(m.provider_icon?'':'')+esc(m.provider_name)+''+(TYPE_LABELS[m.type]||m.type)+''+formatCtx(m.context_window)+''+inputP+''+outputP+''+features.join(', ')+'
'; return html; } // ── Detail Panel ── function openDetail(key) { var m = allModels.find(function(x){return x.key===key;}); if (!m) return; var panel = document.getElementById('detail-panel'); var overlay = document.getElementById('detail-overlay'); var modHtml = ''; if (m.modalities) { var inp = (m.modalities.input||[]).map(function(x){return ''+x+'';}).join(' '); var out = (m.modalities.output||[]).map(function(x){return ''+x+'';}).join(' '); modHtml = '
'+inp+''+out+'
'; } var capsHtml = ''; if (m.capabilities && m.capabilities.length) { capsHtml = m.capabilities.map(function(c){return ''+c+'';}).join(''); } var html = ''; html += '

'+esc(m.name)+'

'; html += '
'+provIcon(m)+esc(m.provider_name)+'
'; html += '
'; html += ''+(TYPE_LABELS[m.type]||m.type)+''; if (m.status==='deprecated') html += 'Deprecated'; if (m.status==='sunset') html += 'Sunset'; if (m.is_new&&m.status==='active') html += 'New'; if (m.vision) html += 'Vision'; if (m.tools) html += 'Tools'; if (m.capabilities&&m.capabilities.indexOf('reasoning')!==-1) html += 'Reasoning'; html += '
'; if (m.description) html += '
'+esc(m.description)+'
'; if (modHtml) html += '

Modalities

'+modHtml+'
'; html += '

Specifications

'; if (m.context_window) html += '
Context Window
'+formatCtx(m.context_window)+' tokens
'; if (m.max_output) html += '
Max Output
'+formatCtx(m.max_output)+' tokens
'; if (m.speed) html += '
Speed
'+speedDots(m.speed)+'
'; html += '
Status
'+(m.status||'active')+'
'; html += '
'; if (m.context_window) html += '

Context Window

'+ctxBar(m.context_window)+'
'; if (m.pricing) { html += '

Pricing

'; var p = m.pricing; if (p.input) html += '
Input
'+formatPrice(p.input)+'
'; if (p.output) html += '
Output
'+formatPrice(p.output)+'
'; if (p.unit) html += '
Per Unit
$'+p.unit.toFixed(4)+'
'; if (p.per_1k) html += '
Per 1K Chars
$'+p.per_1k.toFixed(4)+'
'; if (p.per_second) html += '
Per Second
$'+p.per_second.toFixed(6)+'
'; html += '
'; } html += '

Dates

'; html += '
Added
'+formatDate(m.created_at)+'
'; if (m.updated_at) html += '
Updated
'+formatDate(m.updated_at)+'
'; if (m.deprecated_at) html += '
Deprecated
'+formatDate(m.deprecated_at)+'
'; html += '
'; html += '
'+esc(m.key)+'Click to copy
'; html += 'Use on Zubnet '; panel.innerHTML = html; panel.classList.add('open'); overlay.classList.add('open'); document.body.style.overflow = 'hidden'; document.getElementById('detail-close').onclick = closeDetail; overlay.onclick = closeDetail; document.getElementById('detail-key-box').onclick = function() { var key = this.dataset.key; navigator.clipboard.writeText(key).then(function() { var hint = document.querySelector('.detail-key .copy-hint'); if (hint) { hint.textContent = 'Copied!'; setTimeout(function(){ hint.textContent = 'Click to copy'; }, 1500); } }); }; } function closeDetail() { document.getElementById('detail-panel').classList.remove('open'); document.getElementById('detail-overlay').classList.remove('open'); document.body.style.overflow = ''; } // ── Compare Mode ── function toggleCompare(key) { if (compareSet.has(key)) { compareSet.delete(key); } else if (compareSet.size < 4) { compareSet.add(key); } updateCompareBar(); render(); } function updateCompareBar() { var bar = document.getElementById('compare-bar'); var chips = document.getElementById('compare-chips'); var btn = document.getElementById('compare-go'); if (compareSet.size === 0) { bar.classList.remove('visible'); return; } bar.classList.add('visible'); var html = ''; compareSet.forEach(function(key) { var m = allModels.find(function(x){return x.key===key;}); html += ''+esc(m?m.name:key)+' ×'; }); chips.innerHTML = html; btn.disabled = compareSet.size < 2; chips.querySelectorAll('.remove').forEach(function(el) { el.onclick = function(e) { e.stopPropagation(); toggleCompare(el.dataset.key); }; }); } function openCompare() { if (compareSet.size < 2) return; var models = []; compareSet.forEach(function(k){ var m=allModels.find(function(x){return x.key===k;}); if(m)models.push(m); }); var modal = document.getElementById('compare-modal'); var inner = document.getElementById('compare-modal-inner'); var html = ''; html += '

Model Comparison

'; html += ''; models.forEach(function(m){ html += ''; }); html += ''; var rows = [ ['Provider', function(m){return esc(m.provider_name);}], ['Type', function(m){return TYPE_LABELS[m.type]||m.type;}], ['Status', function(m){return ''+(m.status||'active')+'';}], ['Context', function(m){return formatCtx(m.context_window)||'-';}], ['Max Output', function(m){return formatCtx(m.max_output)||'-';}], ['Speed', function(m){return m.speed?speedDots(m.speed):'-';}], ['Vision', function(m){return m.vision?'':'-';}], ['Tools', function(m){return m.tools?'':'-';}], ['Reasoning', function(m){return m.capabilities&&m.capabilities.indexOf('reasoning')!==-1?'':'-';}], ['Input Price', function(m){return m.pricing&&m.pricing.input?formatPrice(m.pricing.input):'-';}], ['Output Price', function(m){return m.pricing&&m.pricing.output?formatPrice(m.pricing.output):'-';}], ['Modalities', function(m){return getModalities(m)||'-';}], ]; rows.forEach(function(r){ html += ''; models.forEach(function(m){ html += ''; }); html += ''; }); html += '
'+esc(m.name)+'
'+r[0]+''+r[1](m)+'
'; inner.innerHTML = html; modal.classList.add('open'); document.body.style.overflow = 'hidden'; document.getElementById('compare-close').onclick = function(){ modal.classList.remove('open'); document.body.style.overflow=''; }; modal.onclick = function(e){ if(e.target===modal){modal.classList.remove('open');document.body.style.overflow='';} }; } // ── Export ── function exportJSON() { var blob = new Blob([JSON.stringify(data.models, null, 2)], {type:'application/json'}); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'zubnet-models.json'; a.click(); } function exportCSV() { var headers = ['key','name','provider','type','status','context_window','max_output','speed','vision','tools','input_price','output_price']; var rows = [headers.join(',')]; data.models.forEach(function(m){ rows.push([m.key,'"'+esc(m.name)+'"',m.provider,m.type,m.status,m.context_window||'',m.max_output||'',m.speed||'',m.vision?'yes':'no',m.tools?'yes':'no',m.pricing&&m.pricing.input?m.pricing.input:'',m.pricing&&m.pricing.output?m.pricing.output:''].join(',')); }); var blob = new Blob([rows.join('\n')], {type:'text/csv'}); var a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'zubnet-models.csv'; a.click(); } // ── Filter & Render ── function getFilteredModels() { var search = (document.getElementById('dir-search')||{}).value||''; search = search.toLowerCase().trim(); var provider = (document.getElementById('dir-provider')||{}).value||''; var typePill = document.querySelector('.ai-dir-pill.active'); var type = typePill ? typePill.dataset.type : ''; var statusPill = document.querySelector('.ai-dir-status-pill.active'); var status = statusPill ? statusPill.dataset.status : ''; var filtered = allModels.filter(function(m) { if (provider && m.provider!==provider) return false; if (type && m.type!==type) return false; if (status && m.status!==status) return false; if (search) { var h = (m.name+' '+m.key+' '+m.provider_name+' '+(m.description||'')).toLowerCase(); if (h.indexOf(search)===-1) return false; } return true; }); filtered.sort(function(a,b) { var av=a[currentSort.field]||'',bv=b[currentSort.field]||''; if (typeof av==='number'&&typeof bv==='number') return currentSort.dir==='asc'?av-bv:bv-av; av=String(av).toLowerCase(); bv=String(bv).toLowerCase(); return avbv?(currentSort.dir==='asc'?1:-1):0; }); return filtered; } function render() { var filtered = getFilteredModels(); var countEl = document.getElementById('dir-count'); if (countEl) countEl.textContent = 'Showing '+filtered.length+' of '+allModels.length+' models'; var container = document.getElementById('dir-models'); if (!container) return; if (filtered.length===0) { container.innerHTML = '
No models match your filters
'; return; } if (currentView==='grid') { container.innerHTML = '
'+filtered.map(renderCard).join('')+'
'; } else { container.innerHTML = renderTable(filtered); } // Bind clicks container.querySelectorAll('.ai-dir-card, .ai-dir-table tr[data-key]').forEach(function(el) { el.addEventListener('click', function(e) { if (e.target.closest('.compare-check')) return; openDetail(el.dataset.key); }); }); container.querySelectorAll('.compare-check').forEach(function(el) { el.addEventListener('click', function(e) { e.stopPropagation(); toggleCompare(el.dataset.key); }); }); container.querySelectorAll('th[data-sort]').forEach(function(th) { th.addEventListener('click', function() { var f = th.dataset.sort; if (currentSort.field===f) currentSort.dir = currentSort.dir==='asc'?'desc':'asc'; else { currentSort.field=f; currentSort.dir='asc'; } render(); }); }); writeParams(); } // ── Build UI ── function buildUI() { var dir = document.getElementById('ai-directory'); var params = readParams(); currentView = params.view || 'grid'; // Build provider icon map (data.providers||[]).forEach(function(p){ if(p.icon) providerIcons[p.key]=p.icon; }); // Timestamp + export var ts = data.generated_at ? new Date(data.generated_at).toLocaleString(undefined,{dateStyle:'medium',timeStyle:'short'}) : ''; var tsHtml = '
Live data — last updated '+ts+'
' + '
' + '' + '' + ' RSS' + '
'; // Stats var sc = data.status_counts||{}; var statsHtml = tsHtml+'
'+ '
'+data.total_models+'
AI Models
'+ '
'+data.total_providers+'
Providers
'+ (data.new_models>0?'
'+data.new_models+'
Added Recently
':'')+ '
'+Object.keys(data.type_counts).length+'
Categories
'; // Status pills var statusPillsHtml = ''; if ((sc.deprecated||0)>0||(sc.sunset||0)>0) { statusPillsHtml = '
'+ 'All'+ 'Active ('+(sc.active||0)+')'+ ((sc.deprecated||0)>0?'Deprecated ('+sc.deprecated+')':'')+ ((sc.sunset||0)>0?'Sunset ('+sc.sunset+')':'')+ '
'; } // Type pills var pillsHtml = '
All '+data.total_models+''; var types = Object.entries(data.type_counts).sort(function(a,b){var la=(TYPE_LABELS[a[0]]||a[0]).toLowerCase(),lb=(TYPE_LABELS[b[0]]||b[0]).toLowerCase();return lalb?1:0;}); types.forEach(function(t){ pillsHtml += ''+(TYPE_LABELS[t[0]]||t[0])+' '+t[1]+''; }); pillsHtml += '
'; // Controls var provOpts = ''; data.providers.slice().sort(function(a,b){var na=a.name.toLowerCase(),nb=b.name.toLowerCase();return nanb?1:0;}).forEach(function(p){ if(p.model_count>0) provOpts += ''; }); var controlsHtml = '
'+ ''+ ''+ '
'+ ''+ '
'; var countHtml = '
'; var modelsHtml = '
'; // Changelog var changelogHtml = ''; var cl = data.recent_changelog||[]; // Filter out initial backfill cl = cl.filter(function(c){return c.notes!=='Initial catalog entry';}); if (cl.length>0) { var CL = {added:'Added',updated:'Updated',deprecated:'Deprecated',sunset:'Sunset',removed:'Removed',pricing_change:'Pricing',reactivated:'Reactivated'}; changelogHtml = '

Recent Changes

'+ ' Subscribe
'; cl.forEach(function(c){ var det = ''; if (c.field_changed&&c.old_value&&c.new_value) det = '
'+esc(c.field_changed)+': '+esc(c.old_value)+' → '+esc(c.new_value)+'
'; changelogHtml += '
'+ '
'+formatDate(c.detected_at)+'
'+ ''+esc(c.model_key)+''+ ''+esc(c.provider_key)+''+ ''+(CL[c.change_type]||c.change_type)+''+ (c.notes?'
'+esc(c.notes)+'
':'')+ det+'
'; }); changelogHtml += '
'; } var footerHtml = ''; dir.innerHTML = statsHtml+pillsHtml+statusPillsHtml+controlsHtml+countHtml+modelsHtml+changelogHtml+footerHtml; // Bind events document.getElementById('dir-search').addEventListener('input', render); document.getElementById('dir-provider').addEventListener('change', render); document.getElementById('btn-csv').addEventListener('click', exportCSV); document.getElementById('btn-json').addEventListener('click', exportJSON); document.getElementById('compare-go').addEventListener('click', openCompare); document.querySelectorAll('.ai-dir-pill').forEach(function(pill){ pill.addEventListener('click', function(){ document.querySelectorAll('.ai-dir-pill').forEach(function(p){p.classList.remove('active');}); pill.classList.add('active'); render(); }); }); document.querySelectorAll('.ai-dir-status-pill').forEach(function(pill){ pill.addEventListener('click', function(){ document.querySelectorAll('.ai-dir-status-pill').forEach(function(p){p.classList.remove('active');}); pill.classList.add('active'); render(); }); }); document.querySelectorAll('.ai-dir-view-btn').forEach(function(btn){ btn.addEventListener('click', function(){ document.querySelectorAll('.ai-dir-view-btn').forEach(function(b){b.classList.remove('active');}); btn.classList.add('active'); currentView=btn.dataset.view; render(); }); }); // Keyboard shortcut: / to focus search document.addEventListener('keydown', function(e) { if (e.key==='/'&&document.activeElement.tagName!=='INPUT') { e.preventDefault(); document.getElementById('dir-search').focus(); } if (e.key==='Escape') closeDetail(); }); render(); } // ── JSON-LD ── function injectJsonLd() { var items = data.models.slice(0,50).map(function(m,i){ return { '@type':'SoftwareApplication', position:i+1, name:m.name, applicationCategory:'AI Model', operatingSystem:'Cloud', offers: m.pricing&&m.pricing.input ? {'@type':'Offer',price:(m.pricing.input*1000).toFixed(2),priceCurrency:'USD'} : undefined }; }); var ld = { '@context':'https://schema.org', '@type':'ItemList', name:'Zubnet AI Model Directory', description:'Browse '+data.total_models+'+ AI models from '+data.total_providers+' providers', numberOfItems:data.total_models, itemListElement:items }; var script = document.createElement('script'); script.type = 'application/ld+json'; script.textContent = JSON.stringify(ld); document.head.appendChild(script); } // ── Load ── fetch('/site/api/models.json') .then(function(r){return r.json();}) .then(function(d){ data=d; allModels=d.models; allProviders=d.providers; document.getElementById('dir-loading').style.display='none'; // Dynamic title update document.title = 'Zubnet / AI Model Directory — '+d.total_models+'+ Models, '+d.total_providers+' Providers'; buildUI(); injectJsonLd(); }) .catch(function(err){ document.getElementById('dir-loading').innerHTML='

Failed to load model directory. Please try again later.

'; console.error('Failed to load models:',err); }); })();