spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1import type { CloudRegionSummary } from "@dci/core";2import type { Metadata } from "next";3import Link from "next/link";4import { Breadcrumbs } from "@/components/entity/breadcrumbs";5import { SectionNav } from "@/components/entity/section-nav";6import { SourcesFooter } from "@/components/entity/sources-footer";7import { Bars } from "@/components/intelligence/client-charts";8import { ApiNote, CoverageBar, HonestEmpty, PillLink } from "@/components/intelligence/shared";9import { Page, PageHeader, Section } from "@/components/ui/card";10import { CountryFlag } from "@/components/ui/country-flag";11import { Metric, MetricCell, MetricRow } from "@/components/ui/metric";12import { ErrorState, OfflineNotice } from "@/components/ui/states";13import { RowLink, TBody, THead, Table, Td, Th, Tr } from "@/components/ui/table";14import { api } from "@/lib/api";15import { fmtInt, placeLine } from "@/lib/format";16import { routes } from "@/lib/routes";17import { pageMetadata } from "@/lib/seo";1819export const revalidate = 120;2021export const metadata: Metadata = pageMetadata({22 title: "Connectivity",23 description: "Internet exchanges, cloud regions by provider, carrier hotels and connectivity density by market — from published IXP↔facility links and provider region lists. Submarine cable landing stations are listed only once a licensed source exists.",24 path: routes.connectivity(),25});2627const IXP_LIMIT = 50;2829export default async function ConnectivityPage() {30 const r = await api.connectivity();31 if (!r.ok) {32 return (33 <Page className="py-6">34 <Breadcrumbs items={[{ name: "Connectivity", href: routes.connectivity() }]} className="mb-4" />35 <OfflineNotice detail={r.error} className="mb-4" />36 <ErrorState />37 </Page>38 );39 }40 const d = r.data;41 const ixps = [...d.ixps].sort((a, b) => b.facilityCount - a.facilityCount).slice(0, IXP_LIMIT);4243 // cloud regions grouped by provider44 const byProvider = new Map<string, { provider: CloudRegionSummary["provider"]; regions: CloudRegionSummary[] }>();45 for (const cr of d.cloudRegions) {46 const g = byProvider.get(cr.provider.id) ?? { provider: cr.provider, regions: [] };47 g.regions.push(cr);48 byProvider.set(cr.provider.id, g);49 }50 const providers = Array.from(byProvider.values()).sort((a, b) => b.regions.length - a.regions.length);51 const statusSplit = (regions: CloudRegionSummary[]) => {52 const c: Record<string, number> = {};53 for (const x of regions) c[x.status] = (c[x.status] ?? 0) + 1;54 return Object.entries(c)55 .sort((a, b) => b[1] - a[1])56 .map(([k, v]) => `${v} ${k}`)57 .join(" · ");58 };59 const metrosCovered = d.byMetro.filter((m) => m.ixps > 0 || m.cloudRegions > 0 || m.facilitiesWithCarriers > 0).length;6061 const sections = [62 { id: "ixps", label: "Internet exchanges", count: ixps.length },63 { id: "cloud", label: "Cloud regions", count: providers.length },64 { id: "carrier-hotels", label: "Carrier hotels", count: d.carrierHotels.length },65 { id: "metros", label: "By market", count: d.byMetro.length },66 { id: "landing", label: "Landing stations" },67 ];6869 return (70 <Page>71 <Breadcrumbs items={[{ name: "Connectivity", href: routes.connectivity() }]} className="pt-3" />72 <PageHeader eyebrow="Intelligence" title="Connectivity" description="Where networks meet: internet exchanges, public cloud regions, carrier-dense facilities and the markets that concentrate them." aside={<PillLink href={routes.map("layer=connectivity")}>Connectivity layer on the map →</PillLink>} />7374 <MetricRow cols={5}>75 <MetricCell>76 <Metric value={fmtInt(d.ixps.length)} label="Internet exchanges" note="with facility links" />77 </MetricCell>78 <MetricCell>79 <Metric value={fmtInt(d.cloudRegions.length)} label="Cloud regions" note={`${fmtInt(providers.length)} providers`} />80 </MetricCell>81 <MetricCell>82 <Metric value={fmtInt(d.carrierHotels.length)} label="Carrier hotels" note="type carrier hotel or ≥ 20 carriers" />83 </MetricCell>84 <MetricCell>85 <Metric value={fmtInt(metrosCovered)} label="Markets covered" note={`of ${fmtInt(d.byMetro.length)} listed`} />86 </MetricCell>87 <MetricCell>88 <Metric value={fmtInt(d.landingStations.length)} label="Landing stations" note={d.landingStations.length === 0 ? "no licensed connector yet" : "licensed source"} />89 </MetricCell>90 </MetricRow>91 <ApiNote note={d.note} label="From the index" className="mt-3" />9293 <SectionNav items={sections} className="mt-4" />9495 <div className="flex flex-col gap-8 pt-6">96 <Section id="ixps" title="Internet exchanges" description={`Top ${fmtInt(ixps.length)} by facilities where the exchange is present. Network counts are shown only when published.`} className="scroll-mt-28" aside={<Link href={routes.ixps()} className="text-[12.5px] text-ink-3 hover:text-ink">All exchanges →</Link>}>97 {ixps.length === 0 ? (98 <HonestEmpty title="No internet exchange linked to a facility yet" />99 ) : (100 <Table dense mobileCollapse={{ total: ixps.length, label: "exchanges" }}>101 <THead>102 <tr>103 <Th>Exchange</Th>104 <Th>Country</Th>105 <Th className="hidden md:table-cell">Market</Th>106 <Th numeric className="hidden sm:table-cell">107 Networks108 </Th>109 <Th numeric>Facilities</Th>110 <Th numeric className="hidden sm:table-cell">111 Operators112 </Th>113 </tr>114 </THead>115 <TBody>116 {ixps.map((x) => (117 <Tr key={x.id}>118 <Td primary>119 <RowLink href={routes.ixp(x.slug)}>{x.name}</RowLink>120 {x.nameLong && x.nameLong !== x.name && <div className="hidden text-[11.5px] text-ink-3 sm:block">{x.nameLong}</div>}121 </Td>122 <Td label="Country">123 <CountryFlag iso2={x.countryIso2} withName className="max-w-[140px] text-ink-2" />124 </Td>125 <Td label="Market" className="hidden md:table-cell" muted>126 {x.metro ? (127 <Link href={routes.market(x.metro.slug)} className="hover:text-ink hover:underline">128 {x.metro.name}129 </Link>130 ) : (131 (x.city ?? "—")132 )}133 </Td>134 <Td label="Networks" numeric className="hidden sm:table-cell">135 {x.networkCount === null ? <span className="text-ink-4">—</span> : fmtInt(x.networkCount)}136 </Td>137 <Td label="Facilities" numeric lead>138 {fmtInt(x.facilityCount)}139 </Td>140 <Td label="Operators" numeric className="hidden sm:table-cell">141 {fmtInt(x.operatorCount)}142 </Td>143 </Tr>144 ))}145 </TBody>146 </Table>147 )}148 </Section>149150 <Section id="cloud" title="Cloud regions by provider" description="Public cloud regions as published by each provider; regions are associated with a market, not a facility, unless a source says so." className="scroll-mt-28" aside={<Link href={routes.cloudRegions()} className="text-[12.5px] text-ink-3 hover:text-ink">All cloud regions →</Link>}>151 {providers.length === 0 ? (152 <HonestEmpty title="No cloud region indexed" />153 ) : (154 <Bars155 showRank={false}156 items={providers.map((p) => ({157 label: p.provider.name,158 value: p.regions.length,159 href: `${routes.cloudRegions()}?provider=${encodeURIComponent(p.provider.slug)}`,160 secondary: statusSplit(p.regions),161 display: `${fmtInt(p.regions.length)} ${p.regions.length === 1 ? "region" : "regions"}`,162 }))}163 />164 )}165 </Section>166167 <Section id="carrier-hotels" title="Carrier hotels" description="Facilities typed carrier hotel or with ≥ 20 published carriers, by carrier count." className="scroll-mt-28">168 {d.carrierHotels.length === 0 ? (169 <HonestEmpty title="No carrier hotel identified" detail="carrier counts come from published facility pages and registries" />170 ) : (171 <Table dense mobileCollapse={{ total: d.carrierHotels.length, label: "facilities" }}>172 <THead>173 <tr>174 <Th>Facility</Th>175 <Th className="hidden sm:table-cell">Operator</Th>176 <Th>Location</Th>177 <Th numeric>Carriers</Th>178 <Th numeric className="hidden sm:table-cell">179 IXPs180 </Th>181 </tr>182 </THead>183 <TBody>184 {d.carrierHotels.map((f) => (185 <Tr key={f.id}>186 <Td primary>187 <RowLink href={routes.facility(f.slug)}>{f.name}</RowLink>188 <div className="text-[11.5px] text-ink-3 sm:hidden">{f.operator?.name ?? "Operator unknown"}</div>189 </Td>190 <Td label="Operator" className="hidden sm:table-cell">191 {f.operator ? (192 <Link href={routes.operator(f.operator.slug)} className="text-ink-2 hover:text-ink hover:underline">193 {f.operator.name}194 </Link>195 ) : (196 <span className="text-ink-4">—</span>197 )}198 </Td>199 <Td label="Location" muted>200 <span className="inline-flex items-center gap-1.5">201 <CountryFlag iso2={f.countryIso2} size={12} />202 <span className="truncate">{placeLine(f)}</span>203 </span>204 </Td>205 <Td label="Carriers" numeric lead>206 {f.carriersCount === null || f.carriersCount === undefined ? <span className="text-ink-4">—</span> : fmtInt(f.carriersCount)}207 </Td>208 <Td label="IXPs" numeric className="hidden sm:table-cell">209 {f.ixpCount === null || f.ixpCount === undefined ? <span className="text-ink-4">—</span> : fmtInt(f.ixpCount)}210 </Td>211 </Tr>212 ))}213 </TBody>214 </Table>215 )}216 </Section>217218 <Section id="metros" title="By market" description="Exchanges, cloud regions and the share of facilities with published carriers, per market." className="scroll-mt-28">219 {d.byMetro.length === 0 ? (220 <HonestEmpty title="No market with connectivity data" />221 ) : (222 <Table dense mobileCollapse={{ total: d.byMetro.length, label: "markets" }}>223 <THead>224 <tr>225 <Th>Market</Th>226 <Th numeric>IXPs</Th>227 <Th numeric>Cloud regions</Th>228 <Th className="hidden sm:table-cell">Facilities with carriers</Th>229 <Th numeric className="hidden md:table-cell">230 Facilities231 </Th>232 </tr>233 </THead>234 <TBody>235 {d.byMetro.map((m) => (236 <Tr key={m.id}>237 <Td primary>238 <RowLink href={routes.market(m.slug)}>239 <span className="inline-flex items-center gap-1.5">240 <CountryFlag iso2={m.countryIso2} size={12} />241 {m.name}242 </span>243 </RowLink>244 </Td>245 <Td label="IXPs" numeric lead>246 {fmtInt(m.ixps)}247 </Td>248 <Td label="Cloud regions" numeric>249 {fmtInt(m.cloudRegions)}250 </Td>251 <Td label="Facilities with carriers" className="hidden sm:table-cell">252 <span className="inline-flex items-center gap-2">253 <CoverageBar value={m.facilities ? m.facilitiesWithCarriers / m.facilities : null} width="w-[110px]" label="Facilities with published carriers" />254 <span className="figure text-[11.5px] text-ink-3">255 {fmtInt(m.facilitiesWithCarriers)}/{fmtInt(m.facilities)}256 </span>257 </span>258 </Td>259 <Td label="Facilities" numeric className="hidden md:table-cell">260 {fmtInt(m.facilities)}261 </Td>262 </Tr>263 ))}264 </TBody>265 </Table>266 )}267 </Section>268269 <Section id="landing" title="Submarine cable landing stations" description="Listed only from a licensed source." className="scroll-mt-28">270 {d.landingStations.length === 0 ? (271 <HonestEmpty title="No landing station indexed" detail="submarine cable landing stations are empty until a licensed connector exists — never inferred from proximity or news" />272 ) : (273 <ul className="divide-y divide-hair">274 {d.landingStations.map((l) => (275 <li key={l.id} className="flex items-center justify-between gap-3 py-2 text-[13px]">276 <span className="inline-flex items-center gap-1.5 text-ink">277 <CountryFlag iso2={l.countryIso2} size={12} />278 {l.name}279 </span>280 <span className="text-[11.5px] text-ink-3">{l.sourceName}</span>281 </li>282 ))}283 </ul>284 )}285 </Section>286 </div>287288 <SourcesFooter sources={r.sources} note="IXP presence comes from published exchange↔facility links; carrier counts and cloud regions are taken as published. Nothing here is inferred from geography." />289 </Page>290 );291}292