// VEXEL — Home, Tournaments, Tournament detail, Live const { useState: _u, useEffect: _e, useMemo: _m } = React; // ─── Tournament card ───────────────────────────────────────────────────────── function TournamentCard({ t, go, variant = "default", currency = "AED" }) { const g = gameById(t.game); const price = currency === "AED" ? fmtAED(t.prize) : fmtUSD(t.prize); return (
go("tournament", { id: t.id })} style={{ cursor: "pointer", position: "relative" }}>
{t.status === "live" && } {t.status === "upcoming" && Upcoming} {t.status === "past" && Past}
{g.name.toUpperCase()} · {t.format.toUpperCase()}
{t.name}
Prize Pool
{price}
Dates
{t.date}
{t.teams} TEAMS · {t.region} {t.status === "live" ? ( Watch ) : t.status === "upcoming" ? ( Register ) : ( Results )}
); } // ─── HOME ──────────────────────────────────────────────────────────────────── function HomePage({ go, currency }) { const featured = TOURNAMENTS.find(t => t.featured) || TOURNAMENTS[0]; const liveT = TOURNAMENTS.filter(t => t.status === "live"); const thisWeek = TOURNAMENTS.slice(0, 8); const topTeam = TEAMS[1]; // Falcons const topPlayer = PLAYERS[0]; return (
{/* ─── HERO ──────────────────────────── */}
{/* bg layers */}
{/* Side numbers */}
VXL // DUBAI · GULF · 2026
LIVE · {liveT.length} EVENTS
SEASON 03 · OPEN BRACKET
SIGN-UPS OPEN
Vexel · Season 03 · Spring–Summer 2026

Where the Gulf plays.

The competitive home for the region's strongest rosters. Tournaments, rankings, broadcasts, and a player pipeline built out of Dubai — not flown in for it.

{/* Stat strip */}
{[ ["12,400", "Active players"], [currency === "AED" ? "AED 4.2M" : "$1.14M", "Prize pool '26"], ["38", "Tournaments running"], ["7", "Partner publishers"], ].map(([n, l], i) => (
{n}
{l}
))}
{/* ─── 3-TILE FEATURED ───────────────── */}

The Spotlight.

Updated 11 minutes ago
{/* Next tournament */}
go("tournament", { id: featured.id })} className="card lift" style={{ cursor: "pointer", position: "relative", overflow: "hidden", aspectRatio: "1/1.05" }}>
Next on the calendar
{featured.status === "live" && }
{featured.name}
Prize Pool
{currency === "AED" ? fmtAED(featured.prize) : fmtUSD(featured.prize)}
{/* Top team */}
go("team", { id: topTeam.id })} className="card lift" style={{ cursor: "pointer", position: "relative", overflow: "hidden", aspectRatio: "1/1.05" }}>
Top team · this week
{topTeam.name}
{topTeam.region} · {topTeam.members} active players
Win rate
{topTeam.winRate}%
Streak
W7
Rank
#1
{/* Player of the week */}
go("player", { id: topPlayer.id })} className="card lift" style={{ cursor: "pointer", position: "relative", overflow: "hidden", aspectRatio: "1/1.05" }}>
Player of the week
#{topPlayer.rank} · {gameById(topPlayer.game).name.toUpperCase()}
{topPlayer.handle}
{topPlayer.realName} · {teamById(topPlayer.team).tag}
K/D
{topPlayer.kd}
Win %
{topPlayer.winRate}%
Rating
{topPlayer.points}
{/* ─── THIS WEEK GRID ─────────────────── */}
Live + Upcoming

Tournaments running this week

{thisWeek.map(t => )}
{/* ─── TEAM SPOTLIGHT ─────────────────── */}
Team spotlight · May

Apex
Esports

"{TEAMS[0].motto}" — Six titles in eight months, the deepest bench in the GCC, and a Valorant roster currently sitting at world #14 on the official VCT ladder.

{[["6", "Titles '26"], ["AED 1.4M", "Earnings YTD"], ["78%", "Win rate"], ["#14", "VCT World"]].map(([v, l]) => (
{v}
{l}
))}
{/* ─── NEWS PREVIEW ───────────────────── */}
The Drop · Journal

News & long-form

{NEWS.slice(0, 6).map(n => (
go("article", { id: n.id })} className="card lift" style={{ cursor: "pointer" }}>
{n.category} · {n.read}

{n.title}

{n.author.toUpperCase()} · {n.date}
))}
{/* ─── DUBAI PROMO STRIP ──────────────── */}
Built in Dubai

The Gulf gaming scene is about to explode.

Vexel is the operating system for what comes next — a region-first platform, owned and operated out of the UAE.

); } // ─── TOURNAMENTS LIST ──────────────────────────────────────────────────────── function TournamentsPage({ go, currency }) { const [game, setGame] = _u("all"); const [status, setStatus] = _u("all"); const [format, setFormat] = _u("all"); const [region, setRegion] = _u("all"); const [view, setView] = _u("grid"); const [sort, setSort] = _u("prize"); const [page, setPage] = _u(1); let list = TOURNAMENTS.filter(t => (game === "all" || t.game === game) && (status === "all" || t.status === status) && (format === "all" || t.format.toLowerCase().includes(format.toLowerCase())) && (region === "all" || t.region === region)); if (sort === "prize") list = [...list].sort((a, b) => b.prize - a.prize); if (sort === "soon") list = [...list].sort((a, b) => (a.status === "live" ? -1 : 1)); const featured = TOURNAMENTS.find(t => t.featured); return (
{/* Featured banner */}
LIVE NOW · DAY 6
{gameById(featured.game).name.toUpperCase()} · BEST-OF-FIVE BRACKET

{featured.name}

Prize Pool
{currency === "AED" ? fmtAED(featured.prize) : fmtUSD(featured.prize)}
Teams
{featured.teams}
Viewers
{/* Sidebar filters */} {/* Results */}
SHOWING {list.length} OF {TOURNAMENTS.length} TOURNAMENTS
Sort
{[["grid", "▦"], ["list", "≡"]].map(([k, ic]) => ( ))}
{view === "grid" ? (
{list.map(t => )}
) : (
{list.map((t, i) => (
go("tournament", { id: t.id })} className="sweep" style={{ display: "grid", gridTemplateColumns: "60px 1fr 1fr 1fr 1fr auto", padding: "16px 20px", borderBottom: i < list.length - 1 ? "1px solid var(--line)" : "none", gap: 16, alignItems: "center", cursor: "pointer", position: "relative" }}>
{t.name}
{gameById(t.game).name.toUpperCase()} · {t.format}
{currency === "AED" ? fmtAED(t.prize) : fmtUSD(t.prize)}
{t.date}
{t.teams} teams · {t.region}
{t.status === "live" && } {t.status === "upcoming" && Upcoming} {t.status === "past" && Past}
))}
)} {/* Pagination */}
{[1, 2, 3, "…", 8].map((p, i) => ( ))}
); } function FilterGroup({ label, options, value, onChange }) { return (
{label}
{options.map(([k, l]) => ( ))}
); } // ─── TOURNAMENT DETAIL ─────────────────────────────────────────────────────── function TournamentDetailPage({ params, go, currency }) { const t = TOURNAMENTS.find(x => x.id === params.id) || TOURNAMENTS[0]; const g = gameById(t.game); const [tab, setTab] = _u("overview"); return (
{/* Cinematic hero */}
{t.status === "live" && LIVE · DAY 6 OF 11} {t.status === "upcoming" && UPCOMING} {t.status === "past" && CONCLUDED · WINNER: {t.winner}} {t.date.toUpperCase()} · {g.name.toUpperCase()}

{t.name}

Prize Pool
{currency === "AED" ? fmtAED(t.prize) : fmtUSD(t.prize)}
Teams
{t.teams}
Format
{t.format} · Bo5
Region
{t.region}
{t.status === "live" &&
Viewers
}
{t.status === "live" && } {t.status === "upcoming" && }
{/* Tabs */}
{["overview", "bracket", "schedule", "teams", "stats", "stream"].map(k => ( ))}
{tab === "overview" && } {tab === "bracket" && } {tab === "schedule" && } {tab === "teams" && } {tab === "stats" && } {tab === "stream" && }
{/* Sponsors strip */}
Tournament Sponsors
{["Emirates", "DP World", "Logitech G", "Red Bull", "HyperX", "ASUS ROG", "Pepsi", "Lenovo"].map(s => (
{ e.currentTarget.style.color = "var(--cyan)"; e.currentTarget.style.borderColor = "var(--cyan)"; }} onMouseLeave={e => { e.currentTarget.style.color = "var(--text-dim)"; e.currentTarget.style.borderColor = "var(--line)"; }}>{s.toUpperCase()}
))}
); } function TournamentOverview({ t, go, setTab }) { return (

About the event

{t.name} is a {t.format.toLowerCase()} {gameById(t.game).name} event hosting {t.teams} teams across an eleven-day double-elimination bracket. The grand final will be played live in front of a sold-out crowd at the Coca-Cola Arena in Dubai, broadcast in English, Arabic and Turkish.

The winner secures the trophy, a guaranteed seat in Vexel's Summer Invitational, and the lion's share of an AED {(t.prize/1000).toFixed(0)}k prize pool. Sign-ups closed twelve hours after they opened.

{/* Live match widget */} {t.status === "live" && (
LIVE · MAP 2 · ASCENTSEMI-FINAL · BO5
13:24 ELAPSED · ROUND 19
{TEAMS[0].name}
{TEAMS[0].tag} · WORLD #14 · MAPS 1-0
13 : 11
SCORE · MAP 2
{TEAMS[1].name}
{TEAMS[1].tag} · WORLD #08 · MAPS 0-1
{["Apex", "ZeroCool", "alZayed", "Mehari", "Astra"].map((p, i) => (
{p}
{14 - i} / {6 + i} / {4 + i}
))}
{["FalconX", "k1rito", "DUNE", "Sphinx", "Mirage"].map((p, i) => (
{p}
{12 - i} / {8 + i} / {3 + i}
))}
)} {/* Mini schedule preview */}

Coming up

{SCHEDULE[0].matches.map((m, i) => (
{m.time}
{m.a} vs {m.b}
{m.round.toUpperCase()}
{m.live ? : }
))}
{/* Side */}
); } function BracketView() { return (

Upper bracket

16-TEAM · DOUBLE ELIMINATION · UPDATED LIVE
{BRACKET.map((round, ri) => (
{round.round}
{round.matches.map((m, mi) => { const isLive = m.live; const isUpcoming = m.upcoming; const winnerA = m.sa !== null && m.sa > m.sb; const winnerB = m.sb !== null && m.sb > m.sa; return (
{isLive &&
LIVE NOW · MAP {(m.sets && m.sets.length) || 1}
}
); })}
))}
); } function Slot({ name, score, winner, live }) { return (
{name} {score ?? "—"}
); } function ScheduleView() { return (

Schedule

{SCHEDULE.map((day, i) => (
{day.day}
{day.matches.map((m, mi) => (
{m.time}
{m.round.toUpperCase()}
{m.a} vs {m.b}
{m.live ? : }
))}
))}
); } function TeamsGrid({ go }) { return (

Participating teams · 16

{TEAMS.map(t => (
go("team", { id: t.id })} className="card lift" style={{ padding: 16, textAlign: "center", cursor: "pointer", aspectRatio: "1" }}>
{t.name}
{t.region}
))}
); } function StatsLeaderboard() { return (

Top performers

#PLAYERTEAMK/DACSHS%RATING
{PLAYERS.slice(0, 12).map(p => (
{String(p.rank).padStart(2, "0")} {p.handle} {teamById(p.team).tag} {p.kd} {260 - p.rank * 4} {(34 - p.rank * 0.3).toFixed(1)}% {(1.4 - p.rank * 0.018).toFixed(2)}
))}
); } function StreamView({ t }) { return (
{/* Player overlay */}
LIVE · 48,200 VEXEL · EN
SETTINGS · 1080p60
{/* Scoreboard overlay */}
APEX
13 : 11
FLCN
{/* Bottom controls */}
1:24:08 / LIVE
HD CC
{t.name} · Semi-final Apex vs Falcons
VEXEL OFFICIAL · ENGLISH · 48,200 WATCHING
); } // Reusable chat panel function ChatPanel({ compact }) { const msgs = [ ["sandstorm", "var(--cyan)", "let's go apex!!"], ["k1rito_fan", "var(--magenta)", "kirito clutch incoming"], ["DubaiGamer", "var(--lime)", "this is so good"], ["pulse_", "var(--orange)", "the wallbang though"], ["AyaSL_official", "var(--magenta)", "from the team — gg wp"], ["faroe", "var(--gold)", "13-11 incoming"], ["DUNE", "var(--cyan)", "watching from doha"], ["Astra", "var(--lime)", "VEX FOR THE WIN"], ["Cobra", "var(--magenta)", "they fumbled b site so bad"], ["BurnerX", "var(--cyan)", "the new vyse rework is wild"], ["alZayed", "var(--gold)", "1 round from match point"], ["pixel", "var(--orange)", "huge w for apex"], ["Storm99", "var(--lime)", "GG GG GG"], ]; return ( ); } // ─── LIVE ──────────────────────────────────────────────────────────────────── function LivePage({ go }) { const live = TOURNAMENTS.filter(t => t.status === "live"); const [active, setActive] = _u(0); const [gameFilter, setGameFilter] = _u("all"); const filtered = gameFilter === "all" ? live : live.filter(t => t.game === gameFilter); const main = filtered[active] || filtered[0] || live[0]; return (
LIVE NOW · {live.length} TOURNAMENTS · 248K WATCHING
UPDATED EVERY 12 SECONDS · NEXT REFRESH 00:08

Live broadcasts

Every Vexel match, live in one place. Pick a stream, drop into chat.

{/* Game chips */}
{GAMES.map(g => ( ))}
{/* 4-up grid */}
{filtered.slice(0, 4).map((t, i) => (
setActive(i)} style={{ position: "relative", cursor: "pointer", aspectRatio: "16/9", overflow: "hidden", border: i === active ? "2px solid var(--cyan)" : "1px solid var(--line)", borderRadius: 4 }}>
LIVE
{gameById(t.game).name.toUpperCase()}
{t.name}
{/* Mini scoreboard */}
{TEAMS[i*2 % TEAMS.length].tag} {13 - i} ● {String(20 + i)}:{String(14 + i*3).padStart(2,"0")} {11 - i} {TEAMS[(i*2+1) % TEAMS.length].tag}
))}
{/* Featured stream */}
LIVE · 48,200 WATCHING
APEX
13 : 11
FLCN
1:24:08 / LIVE
HD · 1080p60
{main.name}
{gameById(main.game).name.toUpperCase()} · SEMI-FINAL · BO5
); } Object.assign(window, { HomePage, TournamentsPage, TournamentDetailPage, LivePage });