import type { Metadata } from 'next'; import Link from 'next/link'; import { GraphWorkbench } from '@/components/graph/graph-workbench'; import { defaultModeFor, GRAPH_MODES, graphHref, isGraphMode } from '@/components/graph/modes'; import { NodeSearch } from '@/components/graph/node-search-link'; import { BreadcrumbLd } from '@/components/meta/breadcrumb-ld'; import { EntityBadge } from '@/components/ui/badges'; import { Container, Note, PageHeader } from '@/components/ui/section'; import { EmptyState, Unavailable } from '@/components/ui/unavailable'; import { api, apiD3, safe } from '@/lib/api'; import { fmtInt } from '@/lib/format'; import { routes, SITE_NAME, SITE_URL, typeLabel } from '@/lib/site'; import type { GraphExploreMode } from '@/lib/types'; type SP = { node?: string; mode?: string; depth?: string }; export const revalidate = 600; function resolve(sp: SP): { node: string | null; mode: GraphExploreMode | null; depth: 1 | 2 } { return { node: sp.node?.trim() || null, mode: isGraphMode(sp.mode) ? sp.mode : null, depth: sp.depth === '2' ? 2 : 1 }; } /** 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. */ async function defaultRoot(): Promise { const o = await safe(api.companies({ limit: 1, sort: 'models' })); if (o?.items?.[0]?.slug) return o.items[0].slug; const t = await safe(apiD3.trending('views', { type: 'model', limit: 1, days: 7 })); if (t?.items?.[0]?.slug) return t.items[0].slug; const m = await safe(api.models({ limit: 1, sort: 'quality' })); return m?.items?.[0]?.slug ?? null; } export async function generateMetadata({ searchParams }: { searchParams: Promise }): Promise { const { node, mode, depth } = resolve(await searchParams); const d = node ? await safe(api.entity(node)) : null; const m = mode ?? defaultModeFor(d?.entity_type); const modeLabel = GRAPH_MODES.find((x) => x.mode === m)?.label ?? 'Graph'; const title = d ? `${d.name} — ${modeLabel.toLowerCase()} graph` : 'Knowledge graph — every entity, every relation'; 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.'; const canonical = d ? graphHref(d.slug, m, depth) : '/graph'; const og = `${SITE_URL}/graph/og${d ? `?node=${encodeURIComponent(d.slug)}&mode=${m}&depth=${depth}` : ''}`; 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 }; } export default async function GraphIndexPage({ searchParams }: { searchParams: Promise }) { const sp = await searchParams; const { node: asked, mode: askedMode, depth } = resolve(sp); const node = asked ?? (await defaultRoot()); const d = node ? await safe(api.entity(node)) : null; const mode = askedMode ?? defaultModeFor(d?.entity_type); const graph = d ? await safe(apiD3.graphExplore(d.slug, mode, depth, 150)) : null; const modeDef = GRAPH_MODES.find((x) => x.mode === mode)!; return ( <> Knowledge graph {d && } } title={ d ? ( <> {modeDef.label} around{' '} {d.name} ) : ( 'Every entity, every relation' ) } 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.'} aside={ graph ? (

{fmtInt(graph.counts?.nodes ?? graph.nodes.length)} nodes · {fmtInt(graph.counts?.edges ?? graph.edges.length)} edges · depth {graph.depth} {graph.truncated ? · truncated : null}

) : undefined } className="pb-3 md:pb-4" />
{!node ? (
) : !d ? (
Pick a root from the atlas:
) : !graph ? (
) : graph.nodes.length <= 1 ? (
Relations are written only when a source states them. Try another mode:{' '} {GRAPH_MODES.filter((m) => m.mode !== mode) .slice(0, 4) .map((m, i) => ( {i > 0 && ' · '} {m.label} ))} , or open {d.name}.
) : (
Modes map to /graph/explore?mode=: {GRAPH_MODES.map((m) => m.mode).join(' · ')}. The API never returns more than 150 nodes and says so (truncated). Nothing is inferred: an edge exists only when a source stated the relation. Methodology →
)} ); }