HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1import type { Metadata } from 'next';2import Link from 'next/link';3import { GraphWorkbench } from '@/components/graph/graph-workbench';4import { defaultModeFor, GRAPH_MODES, graphHref, isGraphMode } from '@/components/graph/modes';5import { NodeSearch } from '@/components/graph/node-search-link';6import { BreadcrumbLd } from '@/components/meta/breadcrumb-ld';7import { EntityBadge } from '@/components/ui/badges';8import { Container, Note, PageHeader } from '@/components/ui/section';9import { EmptyState, Unavailable } from '@/components/ui/unavailable';10import { api, apiD3, safe } from '@/lib/api';11import { fmtInt } from '@/lib/format';12import { routes, SITE_NAME, SITE_URL, typeLabel } from '@/lib/site';13import type { GraphExploreMode } from '@/lib/types';1415type SP = { node?: string; mode?: string; depth?: string };16export const revalidate = 600;1718function resolve(sp: SP): { node: string | null; mode: GraphExploreMode | null; depth: 1 | 2 } {19 return { node: sp.node?.trim() || null, mode: isGraphMode(sp.mode) ? sp.mode : null, depth: sp.depth === '2' ? 2 : 1 };20}2122/** Default root when none is asked: the organization with the most canonical models (company ecosystem — the richest landing view), else the most viewed model this week. Never hardcoded. */23async function defaultRoot(): Promise<string | null> {24 const o = await safe(api.companies({ limit: 1, sort: 'models' }));25 if (o?.items?.[0]?.slug) return o.items[0].slug;26 const t = await safe(apiD3.trending('views', { type: 'model', limit: 1, days: 7 }));27 if (t?.items?.[0]?.slug) return t.items[0].slug;28 const m = await safe(api.models({ limit: 1, sort: 'quality' }));29 return m?.items?.[0]?.slug ?? null;30}3132export async function generateMetadata({ searchParams }: { searchParams: Promise<SP> }): Promise<Metadata> {33 const { node, mode, depth } = resolve(await searchParams);34 const d = node ? await safe(api.entity(node)) : null;35 const m = mode ?? defaultModeFor(d?.entity_type);36 const modeLabel = GRAPH_MODES.find((x) => x.mode === m)?.label ?? 'Graph';37 const title = d ? `${d.name} — ${modeLabel.toLowerCase()} graph` : 'Knowledge graph — every entity, every relation';38 const description = d ? `${modeLabel} around ${d.name} (${typeLabel(d.entity_type).toLowerCase()}) on ${SITE_NAME}: ${depth}-hop neighbourhood with the predicate of every stated relation.` : 'Explore the AI ecosystem as a graph: model lineage, research networks, company ecosystems, benchmark, dataset, provider and hardware graphs — every edge is a stated relation with a source.';39 const canonical = d ? graphHref(d.slug, m, depth) : '/graph';40 const og = `${SITE_URL}/graph/og${d ? `?node=${encodeURIComponent(d.slug)}&mode=${m}&depth=${depth}` : ''}`;41 return { title, description, alternates: { canonical }, openGraph: { title: `${title} | ${SITE_NAME}`, description, url: `${SITE_URL}${canonical}`, images: [{ url: og, width: 1200, height: 630 }] }, twitter: { card: 'summary_large_image', images: [og] }, robots: node && !d ? { index: false } : undefined };42}4344export default async function GraphIndexPage({ searchParams }: { searchParams: Promise<SP> }) {45 const sp = await searchParams;46 const { node: asked, mode: askedMode, depth } = resolve(sp);47 const node = asked ?? (await defaultRoot());48 const d = node ? await safe(api.entity(node)) : null;49 const mode = askedMode ?? defaultModeFor(d?.entity_type);50 const graph = d ? await safe(apiD3.graphExplore(d.slug, mode, depth, 150)) : null;51 const modeDef = GRAPH_MODES.find((x) => x.mode === mode)!;5253 return (54 <>55 <BreadcrumbLd items={[{ name: SITE_NAME, href: '/' }, { name: 'Knowledge graph', href: '/graph' }, ...(d ? [{ name: d.name, href: graphHref(d.slug, mode, depth) }] : [])]} />56 <Container wide>57 <PageHeader58 eyebrow={59 <>60 Knowledge graph {d && <EntityBadge type={d.entity_type} small />}61 </>62 }63 title={64 d ? (65 <>66 {modeDef.label} around{' '}67 <Link href={routes.entity(d)} className="hover:text-accent">68 {d.name}69 </Link>70 </>71 ) : (72 'Every entity, every relation'73 )74 }75 lede={d ? `${modeDef.hint[0]?.toUpperCase()}${modeDef.hint.slice(1)}. Nodes are coloured by type; every edge is a relation stated by a source. Click a node for its facts, double-click to expand its neighbourhood, pick another root or mode in the rail.` : 'Pick a root entity and a mode to draw its neighbourhood.'}76 aside={77 graph ? (78 <p className="tnum text-xs text-ink-3">79 {fmtInt(graph.counts?.nodes ?? graph.nodes.length)} nodes · {fmtInt(graph.counts?.edges ?? graph.edges.length)} edges · depth {graph.depth}80 {graph.truncated ? <span className="text-warning"> · truncated</span> : null}81 </p>82 ) : undefined83 }84 className="pb-3 md:pb-4"85 />86 </Container>87 {!node ? (88 <Container>89 <div className="pb-16">90 <Unavailable what="Graph" reason="No root could be chosen (the API did not answer)." />91 </div>92 </Container>93 ) : !d ? (94 <Container>95 <div className="pb-16">96 <EmptyState title={`No entity called “${node}”`}>97 Pick a root from the atlas:98 <div className="mx-auto mt-3 max-w-md text-left">99 <NodeSearch mode={mode} depth={depth} />100 </div>101 </EmptyState>102 </div>103 </Container>104 ) : !graph ? (105 <Container>106 <div className="pb-16">107 <Unavailable what="Graph" reason="The graph service did not answer." />108 </div>109 </Container>110 ) : graph.nodes.length <= 1 ? (111 <Container>112 <div className="pb-16">113 <EmptyState title={`No ${modeDef.label.toLowerCase()} relations recorded for ${d.name}`}>114 Relations are written only when a source states them. Try another mode:{' '}115 {GRAPH_MODES.filter((m) => m.mode !== mode)116 .slice(0, 4)117 .map((m, i) => (118 <span key={m.mode}>119 {i > 0 && ' · '}120 <Link href={graphHref(d.slug, m.mode, depth)} className="link">121 {m.label}122 </Link>123 </span>124 ))}125 , or <Link href={routes.entity(d)} className="link">open {d.name}</Link>.126 </EmptyState>127 </div>128 </Container>129 ) : (130 <div className="pb-12">131 <GraphWorkbench key={`${d.slug}:${mode}:${depth}`} initial={graph} root={{ slug: d.slug, name: d.name, entity_type: d.entity_type }} mode={mode} depth={depth} />132 <Container wide>133 <Note className="mt-4">134 Modes map to <span className="mono">/graph/explore?mode=</span>: {GRAPH_MODES.map((m) => m.mode).join(' · ')}. The API never returns more than 150 nodes and says so (<span className="mono">truncated</span>). Nothing is inferred: an edge exists only when a source stated the relation. <Link href={routes.methodology()} className="link">Methodology →</Link>135 </Note>136 </Container>137 </div>138 )}139 </>140 );141}142