SPB Git forge
28commits 1branches 0releases
7.7 MBsize
maindefault branch
10 days agolast push
Python 66.3% TypeScript 22.7% JavaScript 8.6% HTML 1.4% CSS 0.7%
7.3 KB · 186 lines typescript
Raw Blame History
1/** Site-wide constants: names, URLs, navigation, route builders. Server- and client-safe (no 'use client'). */23export const SITE_NAME = 'Company Atlas';4export const TAGLINE = 'The Live Atlas of Global Companies';5export const DESCRIPTION =6  'Company Atlas continuously observes the public web to track how companies evolve — products, hiring, pricing, leadership, locations, technology, strategy and more.';7export const ALT_TAGLINE = 'Thousands of companies. Millions of observations. One continuously growing historical record.';89export const SITE_URL = (process.env.NEXT_PUBLIC_SITE_URL ?? 'https://www.company-atlas.co').replace(/\/$/, '');10export const PUBLIC_API_BASE = `${SITE_URL}/api/v1`;1112export const AUTHOR_NAME = 'Simon-Pierre Boucher';13export const CONTACT_EMAIL = 'contact@spboucher.ai';14export const HOST_NAME = 'MacLustr';15export const HOST_URL = 'https://www.maclustr.io';16export const BOT_UA = 'CompanyAtlasBot';1718export const THEME_LIGHT = '#f7f7f4';19export const THEME_DARK = '#0a0d12';2021export type NavItem = { href: string; label: string; hint?: string };2223export const primaryNav: NavItem[] = [24  { href: '/', label: 'Home' },25  { href: '/live', label: 'Live' },26  { href: '/companies', label: 'Companies' },27  { href: '/events', label: 'Events' },28  { href: '/rankings', label: 'Rankings' },29  { href: '/industry', label: 'Industries' },30  { href: '/country', label: 'Countries' },31];3233export const footerGroups: { label: string; items: NavItem[] }[] = [34  {35    label: 'Atlas',36    items: [37      { href: '/companies', label: 'Companies' },38      { href: '/events', label: 'Events' },39      { href: '/live', label: 'Live feed' },40      { href: '/rankings', label: 'Rankings' },41      { href: '/industry', label: 'Industries' },42      { href: '/country', label: 'Countries' },43      { href: '/company/compare', label: 'Compare' },44    ],45  },46  {47    label: 'Data',48    items: [49      { href: '/api', label: 'API & exports' },50      { href: '/methodology', label: 'Methodology' },51      { href: '/system', label: 'System status' },52      { href: '/watchlist', label: 'Watchlist' },53    ],54  },55  {56    label: 'About',57    items: [58      { href: '/about', label: 'About Company Atlas' },59      { href: '/bot', label: 'Our crawler' },60      { href: `mailto:${CONTACT_EMAIL}`, label: 'Contact' },61    ],62  },63];6465export const EXAMPLE_QUERIES = ['companies hiring AI engineers in Canada', 'pricing changes in SaaS this month', 'new offices opened in Germany', 'Stripe'];6667const enc = encodeURIComponent;68export const routes = {69  home: () => '/',70  live: (q?: Record<string, string | undefined>) => withQuery('/live', q),71  companies: (q?: Record<string, string | undefined>) => withQuery('/companies', q),72  company: (slug: string, tab?: string) => (tab && tab !== 'overview' ? `/company/${enc(slug)}?tab=${tab}` : `/company/${enc(slug)}`),73  compare: (slugs: string[] = []) => (slugs.length ? `/company/compare?companies=${slugs.map(enc).join(',')}` : '/company/compare'),74  events: (q?: Record<string, string | undefined>) => withQuery('/events', q),75  event: (id: string) => `/events/${enc(id)}`,76  change: (id: string) => `/change/${enc(id)}`,77  sensor: (id: string) => `/sensor/${enc(id)}`,78  snapshot: (id: string) => `/snapshot/${enc(id)}`,79  snapshotDiff: (id: string, other: string) => `/snapshot/${enc(id)}/diff/${enc(other)}`,80  rankings: (kind?: string, window?: string) => withQuery('/rankings', { kind, window }),81  industries: () => '/industry',82  industry: (slug: string) => `/industry/${enc(slug)}`,83  countries: () => '/country',84  country: (code: string) => `/country/${enc(code.toLowerCase())}`,85  search: (q: string) => `/search?q=${enc(q)}`,86  watchlist: () => '/watchlist',87  system: () => '/system',88  about: () => '/about',89  methodology: () => '/methodology',90  api: () => '/api',91  bot: () => '/bot',92  admin: (module?: string) => (module ? `/admin/${module}` : '/admin'),93};9495export function withQuery(base: string, q?: Record<string, string | number | undefined | null>): string {96  if (!q) return base;97  const p = new URLSearchParams();98  for (const [k, v] of Object.entries(q)) if (v !== undefined && v !== null && v !== '') p.set(k, String(v));99  const s = p.toString();100  return s ? `${base}?${s}` : base;101}102103export const CONFIDENCE_LABELS: Record<string, string> = {104  VERIFIED: 'Verified',105  HIGH_CONFIDENCE: 'High confidence',106  LIKELY: 'Likely',107  INFERRED: 'Inferred',108  LOW_CONFIDENCE: 'Low confidence',109};110111export const METRIC_LABELS: Record<string, string> = {112  activity_score: 'Activity Score',113  hiring_momentum_7d: 'Hiring Momentum 7d',114  hiring_momentum_30d: 'Hiring Momentum 30d',115  hiring_momentum_90d: 'Hiring Momentum 90d',116  open_jobs: 'Open jobs',117  ai_adoption: 'AI Adoption',118  product_velocity: 'Product Velocity',119  geo_expansion: 'Geographic Expansion',120  developer_momentum: 'Developer Momentum',121  communication_activity: 'Communication Activity',122  pricing_activity: 'Pricing Activity',123  leadership_activity: 'Leadership Activity',124  corporate_change_index: 'Corporate Change Index',125  anomaly_score: 'Anomaly Score',126  historical_coverage: 'Historical coverage',127};128export const METRIC_SHORT: Record<string, string> = {129  activity_score: 'Activity',130  hiring_momentum_30d: 'Hiring 30d',131  product_velocity: 'Product velocity',132  ai_adoption: 'AI adoption',133  corporate_change_index: 'CCI',134  geo_expansion: 'Geo expansion',135  developer_momentum: 'Developer',136  open_jobs: 'Open jobs',137};138139export const RANKING_KINDS: { id: string; label: string; short: string; unit: 'score' | 'pct' | 'count' }[] = [140  { id: 'most_active', label: 'Most Active', short: 'Active', unit: 'score' },141  { id: 'hiring_growth', label: 'Fastest Hiring Growth', short: 'Hiring ↑', unit: 'pct' },142  { id: 'hiring_decline', label: 'Fastest Hiring Decline', short: 'Hiring ↓', unit: 'pct' },143  { id: 'product_velocity', label: 'Highest Product Velocity', short: 'Product', unit: 'score' },144  { id: 'ai_active', label: 'Most AI-Active', short: 'AI', unit: 'score' },145  { id: 'geo_expansion', label: 'Fastest Geographic Expansion', short: 'Geo', unit: 'score' },146  { id: 'developer_momentum', label: 'Highest Developer Momentum', short: 'Developer', unit: 'score' },147  { id: 'pricing_changes', label: 'Most Pricing Changes', short: 'Pricing', unit: 'count' },148  { id: 'unusual_activity', label: 'Most Unusual Activity', short: 'Unusual', unit: 'score' },149];150export const RANKING_WINDOWS = ['24h', '7d', '30d', '90d', '1y'] as const;151152export const TIMELINE_FILTERS = ['all', 'products', 'jobs', 'pricing', 'leadership', 'locations', 'legal', 'news', 'developer'] as const;153154export const SENSOR_TIER_LABELS: Record<string, string> = { A: '5–15 min', B: '30–60 min', C: '6 h', D: '24 h', E: '3–7 days' };155156export const SURFACE_LABELS: Record<string, string> = {157  homepage: 'Homepage',158  about: 'About',159  careers: 'Careers',160  jobs: 'Jobs',161  newsroom: 'Newsroom',162  press: 'Press',163  blog: 'Blog',164  products: 'Products',165  pricing: 'Pricing',166  leadership: 'Leadership',167  team: 'Team',168  locations: 'Locations',169  investor_relations: 'Investor relations',170  documentation: 'Documentation',171  developer: 'Developer',172  api: 'API',173  changelog: 'Changelog',174  legal: 'Legal',175  terms: 'Terms',176  privacy: 'Privacy',177  security: 'Security',178  status: 'Status page',179  sustainability: 'Sustainability',180  partners: 'Partners',181  customers: 'Customers',182  sitemap: 'Sitemap',183  feed: 'Feed',184  other: 'Other',185};186