SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
4 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
4.4 KB · 107 lines typescript
Raw Blame History
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