'use client' import { useEffect } from 'react' export function ChatWidget() { useEffect(() => { let cancelled = false // Fetch the token at runtime from the server so it can come from the // container environment (compose env_file) instead of being inlined // into the client bundle at build time. fetch('/api/chatwoot') .then((res) => (res.ok ? res.json() : null)) .then((config: { token: string | null } | null) => { if (cancelled) return const chatwootToken = config?.token if (!chatwootToken) { console.warn('CHATWOOT_TOKEN not configured') return } // Match the site's dark theme. Chatwoot only supports 'light' and // 'auto' (follows prefers-color-scheme), so 'auto' is the darkest // available setting. Must be set before the SDK runs. ;(window as any).chatwootSettings = { ...(window as any).chatwootSettings, darkMode: 'auto' } // Load Chatwoot widget script const script = document.createElement('script') script.src = 'https://app.chatwoot.com/packs/js/sdk.js' script.async = true script.onload = () => { // Initialize Chatwoot after script loads if ((window as any).chatwootSDK) { ;(window as any).chatwootSDK.run({ websiteToken: chatwootToken, baseUrl: 'https://app.chatwoot.com' }) } } script.onerror = () => { console.error('Failed to load Chatwoot widget') } document.body.appendChild(script) }) .catch(() => { console.error('Failed to fetch Chatwoot config') }) return () => { cancelled = true // Cleanup is handled by Chatwoot itself // Don't remove the script as it manages its own lifecycle } }, []) return null }