How lagiga.info reads GigaBracket's results live
TL;DR
lagiga.info, the GIGA'GAMES website, stores no tournament standings in its CMS. It reads them from a public GigaBracket route, embeds the bracket in an iframe and falls back to a static podium when the route doesn't answer. This article follows what moves from one product to the other, and in which direction.
Two repositories, three data sources
GIGA'GAMES Federation Guadeloupe eSports runs two applications. GigaBracket, launched in June 2026, manages tournaments: the article on GigaBracket covers its formats and stack. lagiga.info is the public site: calendar, disciplines, news, directories and results.
The site splits its content across three sources, depending on who produces it:
- Payload CMS: what the association writes, in a dedicated Postgres database, edited from
/admin. - PocketBase: what users create, such as accounts, player profiles and teams. GigaBracket owns the instance and the schema.
- The code: fixed pages and fallback content, in
src/lib/data.ts.
Payload and PocketBase never intersect. Without either of them, the site still starts and serves its static content.
The contract: a public read-only route
Standings depend on the tournament format, and only GigaBracket knows how to compute them. In elimination formats, they follow elimination depth rather than win count. lagiga recomputes nothing: it receives the result.
For this, GigaBracket exposes a route with no authentication, like its spectator views:
GET /api/public/results/:shareId
The shareId is the 12-character public identifier that /spectate links already use. The route answers with JSON whose key order stays stable, shortened here to a few fields:
{
"shareId": "dEYzqldL00VY",
"gameName": "street-fighter-6",
"format": "double-elimination",
"status": "completed",
"playerCount": 11,
"standings": [
{
"rank": 1,
"playerName": "100scrupuls",
"played": 5,
"wins": 4,
"points": 4
}
]
}
An unknown shareId returns a 404 with not_found. A PocketBase outage returns a 503, an unexpected error a 500.
A single field makes the join
The full contract has 11 fields, and the results page displays only one: standings. The title, venue, date and player count come from Payload or the static fallback. The written report and the gallery exist only in Payload.
The join is the shareId field of the tournament-results Payload collection. A signed-in member fills it in from the admin. It feeds both the standings and the embedded bracket; when it is empty, neither appears.
Live: two speeds on the same page
The word "live" covers two different mechanisms on a results page:
- The standings: GigaBracket's route caches nothing, but lagiga keeps its response for 300 seconds (
revalidate: 300). The standings table can therefore lag by about five minutes. - The embedded bracket: the iframe loads
/embed/:shareId. This view subscribes to matches through PocketBase realtime and refreshes on every change.
During a running tournament, the bracket can therefore be one score ahead of the standings displayed just above it.
GigaBracket restricts where the embedding can happen. /embed/ routes declare lagiga's domains in frame-ancestors. Every other page answers frame-ancestors 'none' and X-Frame-Options: DENY.
When GigaBracket doesn't answer
fetchLiveResults never throws. It returns null if the shareId is empty, the response fails, the JSON is invalid or the network drops. The page then picks one of three displays:
- The live standings: rank, player, matches, wins and points.
- The static podium from
data.ts: rank and player only, with a discreet note. - The "standings coming soon" message, if neither exists.
Payload follows the same principle. If its database is missing or a migration hasn't run, the read fails cleanly and the site switches to the static fallback.
What also moves through PocketBase
The results route isn't the only link. Both applications share the same PocketBase instance, and I recorded the rule in a project decision: the schema lives in GigaBracket, to avoid two sources of truth.
Data moves in both directions:
- From GigaBracket to lagiga: the game catalog (
games) and player statistics (player_stats), recomputed by GigaBracket and read by lagiga. - From lagiga to GigaBracket: profiles (
player_profiles). Only lagiga creates and edits them; GigaBracket selects existing profiles for its teams and brackets. - Awards votes: lagiga writes them, and GigaBracket's voting page redirects to it.
A second public route, /api/public/map-tournaments, feeds the /carte map with tournaments declared visible (mapVisible). The browser calls it when the visitor changes the filter, hence the open CORS headers.
This rule has a cost, also written in the decision: any new collection on the lagiga side goes through GigaBracket.
Three languages, not the same ones everywhere
lagiga.info offers French, English and Spanish. Guadeloupean Creole stays served on /gcf/, outside the language switcher and the sitemap. Each layer covers a different scope:
- Dictionaries and static content: French, English and Spanish.
- Payload: French and English, falling back to French. On
/es/, a written report displays in English. - GigaBracket: French, English and Creole, without Spanish.
The results route gets through this gap unharmed, because it returns data rather than sentences: names, ranks, numbers. Column labels come from lagiga's dictionary, so they follow the page language.
The iframe takes the hit. Its URL carries no language and GigaBracket picks its own: a browser asking for Spanish gets the bracket in French, inside a page in Spanish.
What the 2026 #GCD shows
The #GCD, the federation's flagship event, brought together 7 tournaments and 143 participants on July 25 and 26, 2026 in Sainte-Anne. Those tournaments ran on start.gg and Challonge, and six later joined GigaBracket through import scripts: four from start.gg, two from Challonge. For this edition, the route therefore serves closed results.
The seventh, Domino Clash, was played on site. Its shareId is null: its page never calls GigaBracket and shows 13 participants and a static podium of three names.