import type { Metadata } from 'next';
import Link from 'next/link';
import { ActiveFilters, type FacetGroup, Facets, FilterBar, ListingLayout } from '@/components/listing/filters';
import { BreadcrumbLd } from '@/components/meta/breadcrumb-ld';
import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table';
import { EntityBadge } from '@/components/ui/badges';
import { EntityLink, QualityMark } from '@/components/ui/entity';
import { Hint } from '@/components/ui/hint';
import { Pagination, withParams } from '@/components/ui/pagination';
import { Container, PageHeader } from '@/components/ui/section';
import { Unavailable } from '@/components/ui/unavailable';
import { api, safe } from '@/lib/api';
import { fmtInt, num, titleCase } from '@/lib/format';
import { routes, SITE_NAME } from '@/lib/site';
export const metadata: Metadata = {
title: 'Organizations — companies, labs and universities building AI',
description: 'Every organization in the atlas — companies, research labs, universities — with country, kind, canonical model count and papers, each attribute backed by a source.',
alternates: { canonical: '/companies' },
};
export const revalidate = 300;
type SP = Record;
const LIMIT = 50;
const KEYS = ['q', 'country', 'kind', 'sort', 'order', 'offset'] as const;
const SORTS = [
{ value: 'models', label: 'Most models' },
{ value: 'name', label: 'Name' },
{ value: 'updated', label: 'Recently updated' },
{ value: 'quality', label: 'Data quality' },
];
export default async function CompaniesPage({ searchParams }: { searchParams: Promise }) {
const sp = await searchParams;
const current: Record = {};
for (const k of KEYS) if (sp[k]) current[k] = sp[k];
const offset = Math.max(0, Number(current.offset) || 0);
const sort = current.sort ?? 'models';
const [page, stats] = await Promise.all([safe(api.companies({ ...current, sort, limit: LIMIT, offset, facets: 1 })), safe(api.stats())]);
const href = (patch: Record) => withParams('/companies', current, patch);
const facetGroups: FacetGroup[] = [
{ key: 'country', label: 'Country', items: (page?.facets?.countries ?? []).map((x) => ({ value: x.value, count: x.count })) },
{ key: 'kind', label: 'Kind', items: (page?.facets?.kinds ?? []).map((x) => ({ value: x.value, label: titleCase(x.value), count: x.count })) },
];
const sortHref = (s: string) => href({ sort: s, order: sort === s && current.order !== 'asc' ? 'asc' : undefined, offset: undefined });
const definition = stats?.definitions?.organizations_total ?? 'Organizations = companies, labs and universities (entity types company, organization, lab, university); merged duplicates excluded.';
const SortTh = ({ s, children, num: n }: { s: string; children: React.ReactNode; num?: boolean }) => (
|
{children}
{sort === s && {current.order === 'asc' ? '↑' : '↓'}}
|
);
return (
{fmtInt(page.total)} organizations (companies, labs, universities)
) : undefined
}
>
href(p)} className="mt-3" />
href(p)} />}>
{!page ? (
) : (
<>
Organization
| Type |
Country |
Kind |
Founded |
Models
Papers |
Quality
{page.items.length === 0 && No organizations match these filters.}
{page.items.map((c) => {
const a = c.attributes ?? {};
return (
|
{c.description && {c.description}}
|
|
{typeof a.country === 'string' ? a.country : —} |
{typeof a.org_kind === 'string' ? titleCase(a.org_kind) : —} |
{a.founded ? String(a.founded).slice(0, 4) : —} |
{num(c.model_count) ? (
{fmtInt(c.model_count)}
) : (
0
)}
|
{num(c.paper_count) ? fmtInt(c.paper_count) : 0} |
|
);
})}
href({ offset: o || undefined })} className="mt-4" />
>
)}
);
}