import type { CloudRegionSummary } from "@dci/core"; import type { Metadata } from "next"; import Link from "next/link"; import { SectionNav } from "@/components/entity/section-nav"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Page, PageHeader, Section } from "@/components/ui/card"; import { CountryFlag } from "@/components/ui/country-flag"; import { FilterChips, type Chip } from "@/components/ui/filter-chips"; import { Metric, MetricCell, MetricRow } from "@/components/ui/metric"; import { EmptyState, OfflineNotice } from "@/components/ui/states"; import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table"; import { api } from "@/lib/api"; import { countryName, fmtDate, fmtInt } from "@/lib/format"; import { routes } from "@/lib/routes"; import { pageMetadata } from "@/lib/seo"; import { compareBy, hrefWith, parseSort, sortTh, spGet, type SearchParams, type SortState } from "@/lib/sort"; import { CLOUD_STATUSES, CLOUD_STATUS_LABEL, CloudStatusBadge, type CloudStatus } from "../cloud-format"; export const revalidate = 120; export const metadata: Metadata = pageMetadata({ title: "Cloud regions", description: "Public cloud regions by provider — code, location, availability zones, launch date, status and sovereignty, each linked to the provider's published source.", path: routes.cloudRegions(), }); const SORT_KEYS = ["provider", "code", "name", "city", "country", "azs", "launched", "status"] as const; type SortKey = (typeof SORT_KEYS)[number]; const BASE = routes.cloudRegions(); const sel = "h-9 rounded-sm border border-hair-2 bg-surface px-2 text-[13px] text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"; function RegionTable({ items, showProvider, sp, sort }: { items: CloudRegionSummary[]; showProvider: boolean; sp: SearchParams; sort: SortState | null }) { const th = (key: SortKey) => (sort ? sortTh(BASE, sp, sort, key) : {}); return ( {showProvider && } {items.map((r) => ( {showProvider && ( )} ))}
ProviderCode Region City Country AZs Launched Status Sovereign
{r.provider.name} {r.code}
{r.name} {r.city ? ` · ${r.city}` : ""}
{r.name} {r.city ?? "—"} {r.availabilityZones ?? —} {fmtDate(r.launchedOn)} {r.isSovereign ? ( Sovereign ) : ( — )}
); } export default async function CloudRegionsPage({ searchParams }: { searchParams: Promise }) { const sp = await searchParams; const provider = spGet(sp, "provider"); const country = spGet(sp, "country")?.toUpperCase(); const statusRaw = spGet(sp, "status"); const status = (CLOUD_STATUSES as string[]).includes(statusRaw ?? "") ? (statusRaw as CloudStatus) : undefined; const sorted = spGet(sp, "sort") !== undefined; // Unfiltered list for facets + metrics; filtered list for the table (the API filters server-side). const [all, filtered] = await Promise.all([api.cloudRegions({ per_page: 400 }), provider || country || status ? api.cloudRegions({ per_page: 400, provider, country, status }) : null]); const ok = all.items.length > 0; const items = filtered ? filtered.items : all.items; const providers = Array.from(new Map(all.items.map((r) => [r.provider.slug, { slug: r.provider.slug, name: r.provider.name, n: 0 }])).values()); for (const r of all.items) providers.find((p) => p.slug === r.provider.slug)!.n++; providers.sort((a, b) => b.n - a.n || a.name.localeCompare(b.name)); const countries = Array.from(new Set(all.items.map((r) => r.countryIso2).filter((x): x is string => !!x))).sort((a, b) => countryName(a).localeCompare(countryName(b))); const operational = all.items.filter((r) => r.status === "operational").length; const announced = all.items.filter((r) => r.status === "announced").length; const chips: Chip[] = []; if (provider) chips.push({ key: "provider", label: "Provider", value: providers.find((p) => p.slug === provider)?.name ?? provider, removeHref: hrefWith(BASE, sp, { provider: undefined }) }); if (country) chips.push({ key: "country", label: "Country", value: countryName(country), removeHref: hrefWith(BASE, sp, { country: undefined }) }); if (status) chips.push({ key: "status", label: "Status", value: CLOUD_STATUS_LABEL[status], removeHref: hrefWith(BASE, sp, { status: undefined }) }); const sort = sorted ? parseSort(sp, SORT_KEYS, { key: "provider", order: "asc" }) : null; let flat: CloudRegionSummary[] = items; if (sort) { const get = (r: CloudRegionSummary): string | number | null => { switch (sort.key) { case "provider": return r.provider.name; case "code": return r.code; case "name": return r.name; case "city": return r.city; case "country": return r.countryIso2 ? countryName(r.countryIso2) : null; case "azs": return r.availabilityZones; case "launched": return r.launchedOn; case "status": return r.status; } }; flat = [...items].sort(compareBy(get, sort.order)); } const groups = sorted ? [] : providers .map((p) => ({ ...p, items: items.filter((r) => r.provider.slug === p.slug).sort((a, b) => a.code.localeCompare(b.code)) })) .filter((g) => g.items.length); return ( Show on map } /> {!ok && }

Coordinates are city-level (the published location), never the physical data center.

{ok && ( )}
{sort && } {sort && } {sorted ? "Group by provider" : "Flat sortable table"}
{ok && items.length === 0 && } {!sorted && groups.length > 0 && ({ id: g.slug, label: g.name, count: g.items.length }))} className="mt-3" />} {sorted ? (
) : (
{groups.map((g) => (
{g.name} } description={`${g.items.length} ${g.items.length === 1 ? "region" : "regions"} · ${g.items.filter((r) => r.status === "operational").length} operational`} className="scroll-mt-28" aside={ Only {g.name} } >
))}
)}
); }