spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1/** href builders — single place for every internal route, so entity pages can be added later without touching callers. */23export const SITE_URL = (process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.datacenterindex.io").replace(/\/$/, "");45export const routes = {6 home: () => "/",7 map: (qs?: string) => (qs ? `/map?${qs}` : "/map"),8 search: (q?: string) => (q ? `/search?q=${encodeURIComponent(q)}` : "/search"),9 live: (qs?: string) => (qs ? `/live?${qs}` : "/live"),10 datacenters: (qs?: string) => (qs ? `/datacenters?${qs}` : "/datacenters"),11 facility: (slug: string) => `/datacenters/${slug}`,12 operators: () => "/operators",13 operator: (slug: string) => `/operators/${slug}`,14 countries: () => "/countries",15 country: (slug: string) => `/countries/${slug}`,16 markets: () => "/datacenters/markets",17 market: (slug: string) => `/datacenters/markets/${slug}`,18 projects: (qs?: string) => (qs ? `/projects?${qs}` : "/projects"),19 project: (slug: string) => `/projects/${slug}`,20 rankings: (key?: string) => (key ? `/rankings#${key}` : "/rankings"),21 ranking: (key: string) => `/rankings/${key}`,22 bot: () => "/bot",23 cloudRegions: () => "/cloud-regions",24 cloudRegion: (slug: string) => `/cloud-regions/${slug}`,25 ixps: () => "/ixps",26 ixp: (slug: string) => `/ixps/${slug}`,27 sources: () => "/sources",28 source: (id: string) => `/sources/${id}`,29 methodology: () => "/methodology",30 about: () => "/about",31 apiDocs: () => "/api/v1/docs",32 // 2026-09-12 — intelligence graph33 ai: () => "/ai-infrastructure",34 pulse: (qs?: string) => (qs ? `/pulse?${qs}` : "/pulse"),35 explore: (qs?: string) => (qs ? `/explore?${qs}` : "/explore"),36 compareOperators: (slugs?: string[]) => (slugs?.length ? `/compare/operators?slugs=${slugs.map(encodeURIComponent).join(",")}` : "/compare/operators"),37 coverage: () => "/coverage",38 power: () => "/power",39 connectivity: () => "/connectivity",40 download: () => "/download",41 apiDocsPage: () => "/developers",42 watchlist: () => "/watchlist",43 timeMachine: () => "/map?layer=facilities&time=1",44} as const;4546/** Entity link from an event / generic (type, slug). Unknown types fall back to search. */47export function entityHref(type: string, slug: string | null | undefined, name?: string): string {48 if (!slug) return routes.search(name);49 switch (type) {50 case "facility":51 case "campus":52 return routes.facility(slug);53 case "operator":54 case "company":55 case "carrier":56 return routes.operator(slug);57 case "country":58 return routes.country(slug);59 case "metro":60 case "city":61 return routes.market(slug);62 case "project":63 case "construction_phase":64 case "expansion":65 return routes.project(slug);66 case "cloud_region":67 return routes.cloudRegion(slug);68 case "ixp":69 return routes.ixp(slug);70 case "source":71 return routes.source(slug);72 default:73 return routes.search(name ?? slug);74 }75}7677/** Desktop primary navigation (spec §101): Map · Facilities · Markets · Operators · Projects · AI · Live, then "More". */78export const NAV_PRIMARY = [79 { label: "Map", href: routes.map() },80 { label: "Facilities", href: routes.datacenters() },81 { label: "Markets", href: routes.markets() },82 { label: "Operators", href: routes.operators() },83 { label: "Projects", href: routes.projects() },84 { label: "AI", href: routes.ai() },85 { label: "Live", href: routes.live() },86] as const;8788/** "More" menu: countries, cloud, IXPs, power, connectivity, rankings, pulse, explore, compare, coverage, sources, methodology, API, downloads. */89export const NAV_MORE = [90 { label: "Countries", href: routes.countries() },91 { label: "Cloud regions", href: routes.cloudRegions() },92 { label: "Internet exchanges", href: routes.ixps() },93 { label: "Power & grid", href: routes.power() },94 { label: "Connectivity", href: routes.connectivity() },95 { label: "Rankings", href: routes.rankings() },96 { label: "Pulse", href: routes.pulse() },97 { label: "Explore", href: routes.explore() },98 { label: "Compare operators", href: routes.compareOperators() },99 { label: "Coverage", href: routes.coverage() },100 { label: "Watchlist", href: routes.watchlist() },101 { label: "Sources", href: routes.sources() },102 { label: "Methodology", href: routes.methodology() },103 { label: "Downloads", href: routes.download() },104 { label: "API", href: routes.apiDocsPage() },105 { label: "About", href: routes.about() },106] as const;107