spb/company-atlas
Public
Python 66.3%
TypeScript 22.7%
JavaScript 8.6%
HTML 1.4%
CSS 0.7%
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