HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1import type { Metadata } from 'next';2import Link from 'next/link';3import { Sparkline } from '@/components/charts';4import { Dash, IntelListing, str } from '@/components/intelligence/listing-table';5import { Chip } from '@/components/ui/badges';6import { EntityLink, QualityMark } from '@/components/ui/entity';7import { api, safe } from '@/lib/api';8import { fmtDate, fmtInt, num } from '@/lib/format';9import { routes, SITE_NAME, SITE_URL } from '@/lib/site';1011export const metadata: Metadata = { title: 'AI frameworks, inference engines, libraries and runtimes — versions, licences, stars', description: 'Training frameworks, inference engines, serving stacks, libraries, runtimes, agent frameworks, orchestration and eval harnesses with latest version, release date, licence and repository stars read from PyPI, GitHub and release pages.', alternates: { canonical: routes.frameworks() }, openGraph: { title: `AI frameworks | ${SITE_NAME}`, url: `${SITE_URL}${routes.frameworks()}`, siteName: SITE_NAME } };12export const revalidate = 300;1314type Extra = { stars: number[] };15/** Canonical kind vocabulary → label; entity_type is the fallback when no `kind` attribute is stated. */16const KIND_LABELS: Record<string, string> = {17 training_framework: 'Training framework',18 training: 'Training framework',19 inference_engine: 'Inference engine',20 inference: 'Inference engine',21 serving: 'Serving',22 library: 'Library',23 runtime: 'Runtime',24 agent_framework: 'Agent framework',25 agent: 'Agent framework',26 orchestration: 'Orchestration',27 eval_harness: 'Eval harness',28 evaluation: 'Eval harness',29 framework: 'Framework',30};31const kindOf = (e: { entity_type: string; attributes: Record<string, unknown> }) => {32 const k = str(e.attributes?.kind) ?? str(e.attributes?.category);33 if (k) return KIND_LABELS[k.toLowerCase().replace(/[\s-]+/g, '_')] ?? k;34 return KIND_LABELS[e.entity_type] ?? e.entity_type;35};3637export default async function FrameworksPage({ searchParams }: { searchParams: Promise<Record<string, string | undefined>> }) {38 const sp = await searchParams;39 return (40 <IntelListing<Extra>41 title="Frameworks & runtimes"42 eyebrow="Frameworks"43 lede="Training frameworks, inference engines, serving stacks, libraries, runtimes, agent frameworks, orchestration and eval harnesses. Versions and stars are read from PyPI, GitHub and release pages — never estimated."44 basePath="/frameworks"45 searchParams={sp}46 fetch={(q) => api.explore('framework', q)}47 sorts={[48 { value: 'updated', label: 'Recently updated' },49 { value: 'stars', label: 'Stars' },50 { value: 'release', label: 'Latest release' },51 { value: 'name', label: 'Name' },52 { value: 'quality', label: 'Data quality' },53 ]}54 filters={sp.org ? [{ kind: 'hidden', name: 'org', value: sp.org }] : []}55 connectors={['github (repositories)', 'pypi', 'release feeds']}56 compare57 enrich={async (items) => {58 const hist = await Promise.all(items.map((e) => safe(api.entityHistory(e.slug, 'metric.stars'))));59 const m = new Map<string, Extra>();60 hist.forEach((h, i) => {61 const vals = (h?.items ?? []).slice().sort((a, b) => a.observed_at.localeCompare(b.observed_at)).map((c) => num(c.value)).filter((v): v is number => v !== null);62 m.set(items[i]!.slug, { stars: vals });63 });64 return m;65 }}66 columns={[67 {68 key: 'name',69 label: 'Framework',70 primary: true,71 render: (e) => (72 <>73 <EntityLink e={e} />74 {e.description && <span className="block max-w-md truncate text-xs text-ink-3">{e.description}</span>}75 </>76 ),77 },78 { key: 'kind', label: 'Kind', render: (e) => <Chip>{kindOf(e)}</Chip> },79 { key: 'version', label: 'Latest release', className: 'mono text-xs text-ink', render: (e) => (str(e.attributes?.latest_version) ? <>{(str(e.attributes.latest_version) as string).slice(0, 24)}{str(e.attributes?.latest_release_at) && <span className="tnum block font-sans text-[11px] text-ink-3">{fmtDate(str(e.attributes.latest_release_at))}</span>}</> : <Dash />) },80 { key: 'license', label: 'Licence', className: 'max-w-[10rem] truncate text-ink-2', render: (e) => str(e.attributes?.license) ?? <Dash /> },81 {82 key: 'stars',83 label: 'Stars',84 num: true,85 className: 'tnum',86 render: (e, x) => {87 const v = num(e.attributes?.['metric.stars']);88 if (v === null) return <Dash />;89 const distinct = new Set(x?.stars ?? []).size;90 return (91 <span className="inline-flex items-center justify-end gap-2">92 {x && x.stars.length >= 2 && distinct >= 2 && <Sparkline values={x.stars} width={64} height={18} stroke="var(--type-framework)" title={`Stars history · ${x.stars.length} observations`} />}93 <span>{fmtInt(v)}</span>94 </span>95 );96 },97 },98 { key: 'language', label: 'Language', className: 'text-ink-2', render: (e) => str(e.attributes?.language) ?? <Dash /> },99 { key: 'org', label: 'Organization', className: 'text-ink-2', render: (e) => (e.organization ? <Link href={routes.entity({ entity_type: 'company', slug: e.organization.slug })} className="hover:text-accent">{e.organization.name}</Link> : <Dash />) },100 { key: 'quality', label: 'Quality', num: true, render: (e) => <QualityMark q={e.quality?.score} /> },101 ]}102 note="Stars are a GitHub metric observed at crawl time; the sparkline appears once the claim history holds two distinct values (see each framework's History tab). Kind falls back to the entity type (framework · library · runtime) when no source states a finer category."103 />104 );105}106