How do I fix these issues?


Im using Cloudafre workers to talk to my Frontend but im hitting the wall. I added CORS headers in my workers js but nothing works!

this is my StreamersConfigTab.tsx:

import { useState, useEffect } from 'react';
import AppStatus from '../../components/AppStatus';
import { getStreamerStats } from '../../api/getStreamerStats';

type StreamerStats = {
    twitchUserId: string;
    challengesProposed: number;
    challengesCompleted: number;
    challengesFailed: number;
    totalBitsSpent: number;
    lastUpdated: string;
};

type ConfigStatCardProps = {
    label: string;
    value: number | string;
    loading: boolean;
};

function ConfigStatCard({ label, value, loading }: ConfigStatCardProps) {
    return (
        <div className="config-stat-card">
            <span className="config-stat-label">{label}</span>
            {loading ? (
                <div className="skeleton-item skeleton-config-value"></div>
            ) : (
                <span className="config-stat-value">
                    {typeof value === 'number' ? value.toLocaleString() : value}
                </span>
            )}
        </div>
    );
}

export default function StreamerConfigTab() {
    const [broadcasterId, setBroadcasterId] = useState<string | null>(null);
    const [authorized, setAuthorized] = useState(false);
    const [stats, setStats] = useState<StreamerStats | null>(null);
    const [status, setStatus] = useState<'checking' | 'connected' | 'disconnected'>('checking');
    const [riotId, setRiotId] = useState<string | null>(null);

    // ✅ Wait for Twitch.onAuthorized
    useEffect(() => {
        if (window.Twitch?.ext) {
            window.Twitch.ext.onAuthorized(auth => {
                setBroadcasterId(auth.channelId);
                setAuthorized(true);
            });
        } else {
            console.error('Twitch Helper not found.');
        }
    }, []);

    // 🔒 Gate rendering
    if (!authorized || !broadcasterId) {
        return <div className="config-container">Loading Twitch config...</div>;
    }

    // 📊 Fetch stats every 30s
    useEffect(() => {
        let mounted = true;

        const fetchStats = async () => {
            try {
                const data = await getStreamerStats(broadcasterId);
                if (mounted) setStats(data);
            } catch (e) {
                console.error(e);
            }
        };

        fetchStats();
        const id = setInterval(fetchStats, 30_000);
        return () => {
            mounted = false;
            clearInterval(id);
        };
    }, [broadcasterId]);

    // 🔌 Check PC App connection every 5s
    useEffect(() => {
        let mounted = true;

        const checkConn = async () => {
            try {
                const res = await fetch(`/status/connection?twitchUserId=${broadcasterId}`);
                const json = await res.json();
                if (mounted) setStatus(json.connected ? 'connected' : 'disconnected');
            } catch {
                if (mounted) setStatus('disconnected');
            }
        };

        checkConn();
        const id = setInterval(checkConn, 5_000);
        return () => {
            mounted = false;
            clearInterval(id);
        };
    }, [broadcasterId]);

    // 🧠 Fetch Riot ID if connected
    useEffect(() => {
        if (status !== 'connected') {
            setRiotId(null);
            return;
        }

        let mounted = true;

        const fetchRiot = async () => {
            try {
                const active = await fetch(`/match/active?twitchUserId=${broadcasterId}`).then(r => r.json());
                if (!mounted) return;

                if (active.sessionId) {
                    const detail = await fetch(`/match/${active.sessionId}/status`).then(r => r.json());
                    if (mounted) setRiotId(detail.riotId);
                } else {
                    setRiotId(null);
                }
            } catch {
                if (mounted) setRiotId(null);
            }
        };

        fetchRiot();
        return () => {
            mounted = false;
        };
    }, [status, broadcasterId]);

    return (
        <div className="config-container">
            <h1>Streamer Configuration</h1>

            <div className="config-section">
                <h2 className="config-section-title">Connection Status</h2>
                <div className="config-grid">
                    <div className="config-stat-card">
                        <span className="config-stat-label">PC Application</span>
                        <AppStatus status={status} />
                    </div>
                    {status === 'connected' && (
                        <div className="config-stat-card">
                            <span className="config-stat-label">Connected Riot ID</span>
                            <span className="config-stat-value">{riotId || 'N/A'}</span>
                        </div>
                    )}
                </div>
            </div>

            <div className="config-section">
                <h2 className="config-section-title">Lifetime Stats</h2>
                <div className="config-grid">
                    <ConfigStatCard label="Challenges Proposed" value={stats?.challengesProposed ?? 0} loading={!stats} />
                    <ConfigStatCard label="Challenges Completed" value={stats?.challengesCompleted ?? 0} loading={!stats} />
                    <ConfigStatCard label="Challenges Failed" value={stats?.challengesFailed ?? 0} loading={!stats} />
                    <ConfigStatCard label="Bits Spent" value={stats?.totalBitsSpent ?? 0} loading={!stats} />
                </div>
                {stats && (
                    <p className="last-updated-text">
                        Last updated: {new Date(stats.lastUpdated).toLocaleString()}
                    </p>
                )}
            </div>
        </div>
    );
}

Are you actually calling api.sprig.com or cloudflare workers?

I don’t think api.sprig.com is anything to do with your extension.

Since you say you are using cloudflare workers.
So this error is unrelated to your extension, especially as the parent “caller” is dashboard.twitch.tv and not your extension.

I don’t see anything obviouslly wrong in your provided front end code, so likely an api fault with your API?