import { useState, useEffect, useRef, createContext, useContext, type ReactElement, type ReactNode } from 'react'; import type { UserResource } from '@clerk/types'; import * as Sentry from '@sentry/react'; import { motion } from 'motion/react'; import { Globe, ShieldAlert, Zap, Terminal, Database, Send, MessageCircle, Mail, MessageSquare, ChevronDown, ArrowRight, Check, Lock, Server, Cpu, Layers, Bell, Brain, Key, Plug, PanelTop, ExternalLink, BarChart3, Clock, Radio, Ship, Plane, Flame, Cable, Wifi, MapPin, TrendingUp, Filter, Lightbulb, SlidersHorizontal, Telescope, LineChart, Search, Shield, Building2, Landmark, Fuel } from 'lucide-react'; import { t } from './i18n'; import { ensureClerk, tryResumeCheckoutFromUrl } from './services/checkout'; import { scheduleClerkLoad, subscribeClerkLoaded } from './services/clerk'; import { startClerkUserStateSync, type ClerkUserState } from './services/clerk-user-state'; import { hasLiveClientSession } from './services/clerk-session'; import { PricingSection } from './components/PricingSection'; import { SoonBadge } from './components/SoonBadge'; import { Logo } from './components/Logo'; import { WiredBadge } from './components/WiredBadge'; import { Footer } from './components/Footer'; import { DASHBOARD_SCREENSHOT_JPG, DASHBOARD_SCREENSHOT_AVIF_SRCSET, DASHBOARD_SCREENSHOT_WEBP_SRCSET, } from './assets/dashboard-screenshot'; import { ensureTurnstileScript } from './turnstile'; import wiredLogo from './assets/wired-logo.svg'; import { DASHBOARD_EMBED_PREVIEW_URL, DASHBOARD_PATH, DASHBOARD_URL, } from './routes'; const API_BASE = 'https://api.worldmonitor.app/api'; const TURNSTILE_SITE_KEY = '0x4AAAAAACnaYgHIyxclu8Tj'; declare global { interface Window { turnstile?: { render: (container: string | HTMLElement, opts: Record) => string; getResponse: (widgetOrId?: string | HTMLElement) => string | undefined; reset: (widgetOrId?: string | HTMLElement) => void; }; } } export function renderTurnstileWidgets(): number { if (!window.turnstile) return 0; let count = 0; document.querySelectorAll('.cf-turnstile:not([data-rendered])').forEach(el => { const widgetId = window.turnstile!.render(el, { sitekey: TURNSTILE_SITE_KEY, size: 'flexible', callback: (token: string) => { el.dataset.token = token; }, 'expired-callback': () => { delete el.dataset.token; }, 'error-callback': () => { delete el.dataset.token; }, }); el.dataset.rendered = 'true'; el.dataset.widgetId = String(widgetId); count++; }); return count; } function getRefCode(): string | undefined { const params = new URLSearchParams(window.location.search); return params.get('ref') || undefined; } /** * Carry the current visit's referral code into a dashboard-target URL. * Ensures `/pro?ref=X` → hero "try the dashboard" click propagates the * code to the dashboard, where captureReferralFromUrl() in App.ts * persists it to localStorage for a later in-dashboard upgrade. Writes * with the `wm_referral=` name because the dashboard uses that going * forward; the /pro page itself still accepts `ref=` for inbound * compatibility with existing share links. * * Validates against the same charset as the dashboard's `isValidCode` * (alphanumeric + `-` + `_`, ≤64 chars) so a hostile `/pro?ref=` value * doesn't briefly appear in the dashboard URL on arrival before the * dashboard-side validator strips it. Invalid codes return the URL * unchanged so the link still works without attribution. */ const REFERRAL_CODE_REGEX = /^[a-zA-Z0-9_-]+$/; function isValidRefCode(code: string): boolean { return code.length > 0 && code.length <= 64 && REFERRAL_CODE_REGEX.test(code); } function appendRefToUrl(url: string, refCode: string | undefined): string { if (!refCode || !isValidRefCode(refCode)) return url; const sep = url.includes('?') ? '&' : '?'; return `${url}${sep}wm_referral=${encodeURIComponent(refCode)}`; } function openSignIn(): void { ensureClerk().then(c => c.openSignIn()).catch((err) => { console.error('[auth] Failed to open sign in:', err); Sentry.captureException(err, { tags: { surface: 'pro-marketing', action: 'open-sign-in' } }); }); } /** * Lightweight /pro auth state. The live __session JWT gives us an immediate * signed-in signal without loading Clerk; the real Clerk user is filled in only * after the SDK is loaded from an auth action or an idle signed-in load. * * Used by the Navbar to swap the SIGN IN button for Clerk's UserButton avatar * once the visitor is authenticated, and by the Hero to hide its redundant * SIGN IN CTA. Single source of truth for "is the /pro visitor signed in". */ function useClerkUser(): ClerkUserState { const [state, setState] = useState(() => ({ user: null, isLoaded: true, signedIn: hasLiveClientSession(), })); useEffect(() => { return startClerkUserStateSync(setState, { hasLiveClientSession, subscribeClerkLoaded, scheduleClerkLoad, onLoadError(err) { console.error('[auth] Failed to load Clerk for nav auth state:', err); Sentry.captureException(err, { tags: { surface: 'pro-marketing', action: 'load-clerk-for-nav' } }); setState({ user: null, isLoaded: true, signedIn: false }); }, }); }, []); return state; } /** * Entitlement state shared across /pro — `isPro: true` when the signed-in * visitor has an active Pro entitlement, either via Clerk pro role OR a * Convex Dodo subscription (tier >= 1). The provider below performs * exactly one /api/me/entitlement fetch per page load and makes the * result available via useProEntitlement(); Navbar and Hero (and any * future caller) share a single source of truth, so the nav and hero * can't disagree on transient failures. * * Defaults to `{ isPro: false, isChecked: false }` for consumers that * render without a provider (e.g. tests) — matches the closed-by-default * stance for unpaid visitors. */ type ProEntitlementState = { isPro: boolean; isChecked: boolean }; const ProEntitlementContext = createContext({ isPro: false, isChecked: false }); function ProEntitlementProvider({ children }: { children: ReactNode }): ReactElement { const { user, signedIn } = useClerkUser(); const userId = user?.id ?? null; const [state, setState] = useState({ isPro: false, isChecked: false }); useEffect(() => { if (!signedIn) { setState({ isPro: false, isChecked: true }); return; } if (!userId) { setState({ isPro: false, isChecked: false }); return; } let cancelled = false; (async () => { try { const clerk = await ensureClerk(); // Clerk can expose `user` before its session-token endpoint is // ready; a first null return is a known transient, not a final // "no token." Retry once after a 2s gap — same pattern as // services/checkout.ts:getAuthToken. Without the retry, a real // Pro user hitting /pro on a cold Clerk load gets a permanent // isPro=false for the whole session. let token = await clerk.session?.getToken().catch(() => null); if (!token) { await new Promise((r) => setTimeout(r, 2000)); token = await clerk.session?.getToken().catch(() => null); } if (!token) { if (!cancelled) setState({ isPro: false, isChecked: true }); return; } const resp = await fetch(`${API_BASE}/me/entitlement`, { headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(8_000), }); if (!resp.ok) { if (!cancelled) setState({ isPro: false, isChecked: true }); return; } const data = await resp.json() as { isPro?: boolean }; if (!cancelled) setState({ isPro: data.isPro === true, isChecked: true }); } catch (err) { console.error('[auth] Failed to check pro entitlement:', err); Sentry.captureException(err, { tags: { surface: 'pro-marketing', action: 'check-entitlement' } }); if (!cancelled) setState({ isPro: false, isChecked: true }); } })(); return () => { cancelled = true; }; }, [signedIn, userId]); return {children}; } function useProEntitlement(): ProEntitlementState { return useContext(ProEntitlementContext); } /** * Mounts Clerk's native UserButton (avatar + dropdown with profile + sign * out) into a DOM node. Using Clerk's built-in widget avoids reimplementing * a signed-in UI from scratch and inherits theming from the existing * clerk.load() appearance options in services/checkout.ts. */ function ClerkUserButton({ user }: { user: UserResource | null }): ReactElement { const ref = useRef(null); useEffect(() => { if (!user) return; if (!ref.current) return; const el = ref.current; let unmounted = false; ensureClerk() .then((clerk) => { if (unmounted || !el) return; clerk.mountUserButton(el, { afterSignOutUrl: 'https://www.worldmonitor.app/pro', }); }) .catch((err) => { console.error('[auth] Failed to mount user button:', err); Sentry.captureException(err, { tags: { surface: 'pro-marketing', action: 'mount-user-button' } }); }); return () => { unmounted = true; ensureClerk().then((clerk) => { if (el) clerk.unmountUserButton(el); }).catch(() => { /* mount path already failed */ }); }; }, [user]); return (
{!user && (
); } const SlackIcon = () => ( ); /* ─── 0. Navbar ─── */ const Navbar = () => { const { user, isLoaded, signedIn } = useClerkUser(); const { isPro, isChecked } = useProEntitlement(); // Show "Go to Dashboard" instead of "Upgrade to Pro" once we confirm // the visitor is already a paying customer. Until the entitlement // check completes we keep the upgrade CTA in place — a signed-in // free user would see a one-frame flash otherwise, which is less // annoying than showing "Go to Dashboard" for half a second to a // visitor who hasn't paid. const showGoToDashboard = isLoaded && signedIn && !!user && isChecked && isPro; return ( ); }; /* ─── 1. Hero — Less noise, more signal ─── */ const SignalBars = () => { const total = 60; const center = total / 2; const signalRadius = 8; const jitter = (index: number, salt: number) => { const x = Math.sin(index * 12.9898 + salt * 78.233) * 43758.5453; return x - Math.floor(x); }; return (
); }; const Hero = () => { const { user, isLoaded, signedIn } = useClerkUser(); const { isPro, isChecked } = useProEntitlement(); // Showing "Sign In" to an already-signed-in user wastes a CTA slot. // Hide it once auth state confirms; falls back to just the "Choose Plan" // CTA which is the relevant action for returning users anyway. const showSignIn = isLoaded && !signedIn; // Swap "Choose Plan" for "Go to Dashboard" once we confirm the visitor // is already Pro — same reasoning as the nav swap, and also removes // the #pricing anchor jump which is actively misleading for a paying // customer. const showGoToDashboard = isLoaded && signedIn && !!user && isChecked && isPro; return (

{t('hero.noiseWord')} {t('hero.signalWord')}

{t('hero.valueProps')}

{showGoToDashboard ? ( {t('hero.goToDashboard')} ) : ( {t('hero.choosePlan')} )} {showSignIn && ( )}
); }; /* ─── 2. Social proof (current — WIRED badge already in hero) ─── */ const SocialProof = () => (
{[ { value: "2M+", label: t('socialProof.uniqueVisitors') }, { value: "421K", label: t('socialProof.peakDailyUsers') }, { value: "190+", label: t('socialProof.countriesReached') }, { value: "500+", label: t('socialProof.liveDataSources') }, ].map((stat, i) => (

{stat.value}

{stat.label}

))}

"{t('socialProof.quote')}"

); /* ─── 3. Two-path split (new — from draft) ─── */ const TwoPathSplit = () => (

Plans

{t('twoPath.proTitle')}

{t('twoPath.proDesc')}

    {[t('twoPath.proF1'), t('twoPath.proF2'), t('twoPath.proF3'), t('twoPath.proF4'), t('twoPath.proF5'), t('twoPath.proF6'), t('twoPath.proF7'), t('twoPath.proF8'), t('twoPath.proF9')].map((f, i) => (
  • ))}
{t('twoPath.choosePlan')}

{t('twoPath.entTitle')}

{t('twoPath.entDesc')}

  • {t('twoPath.entF1')}
  • {[t('twoPath.entF2'), t('twoPath.entF3'), t('twoPath.entF4'), t('twoPath.entF5'), t('twoPath.entF6'), t('twoPath.entF7'), t('twoPath.entF8'), t('twoPath.entF9'), t('twoPath.entF10'), t('twoPath.entF11')].map((f, i) => (
  • ))}
{t('twoPath.entCta')}
); /* ─── 4. Why Upgrade (new — from draft) ─── */ const WhyUpgrade = () => { const items = [ { icon: