npm update within existing semver ranges: nanoid 3.3.19, postcss 8.5.28, vite 6.4.3 (kingmaker). Fixes CVE-2026-67213, CVE-2026-67214, CVE-2026-73646, CVE-2026-69153, CVE-2026-53571, CVE-2026-53632. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scouting.gateway-gamers.net
BCP Roster Scout: paste a Best Coast Pairings (BCP) event link and get instant roster stats for that event. For team events, it can also generate a pre-filled Google Sheets matchup matrix for each opposing team.
What it serves
A single page (index.html). Enter an event URL or ID (it's also read from
?event=<id>, so scouted events can be linked) and the page shows:
- Summary: event name and dates, player and team counts, checked-in rate, lists submitted.
- Insights and faction distribution: faction spread, with each faction's most-used dispositions (Purge the Foe, Take and Hold and so on).
- Roster, with ITC rank (Warhammer Global Rankings 2026) and career win %
for every player:
- team events: grouped by team, with a search box
- singles events: a flat player table
- Generate Matrix (team events): pick your team and the page:
- copies the team's Google Sheets matchup-matrix template once per opposing team
- fills in each opponent's name, faction and career win %, plus their army list cleaned up by the vendored 40k Compactor
- links you to the new spreadsheet
Data sources
| Data | Source |
|---|---|
| Event, roster, team players | BCP events/{id} and related endpoints |
| ITC rank | BCP placings for the ITC league and region |
| Career W–L–T | BCP placings?userId=… for each player |
| Army lists | BCP armylists/{id} (needs a subscriber token) |
| Matrix | Google Drive and Sheets APIs, as the signed-in viewer |
All requests come from the viewer's browser. There's no backend and nothing is stored on the server.
Optional BCP token
BCP often leaves faction or disposition blank on the roster. A viewer with a BCP subscription can paste their BCP auth token; the page then fetches each submitted list and pulls the missing faction and disposition out of it. Disposition names are fuzzy-matched so typos don't create duplicate entries. The same token is used to fetch lists for the matrix.
The token is kept only in that browser's localStorage (bcp_auth_token) and
only sent to BCP's own API. The page includes step-by-step instructions for
finding it. BCP tokens expire after about an hour.
Google sign-in (matrix only)
Google Identity Services opens an OAuth popup and the viewer signs in with their own account. It requests these scopes:
drive.readonly: read the template so it can be copieddrive.file: create the copiesspreadsheets: write into the copies
The OAuth client ID and template file ID are constants at the top of
src/matrix.js.
Files
index.html,src/main.js,src/style.css: the page, BCP data loading, stats and renderingsrc/matrix.js: Google sign-in, template copying and list cleaning for Generate Matrixsrc/vendor/40k-compactor/: vendored copy of Desjani's 40k Compactor (MIT), used to reformat army lists. It isn't on npm. See itsNOTICE.mdfor where it came from, the license and how to update it.nav.html: this site's header nav entries (see the root README)scouting.gateway-gamers.net.conf: reference nginx config for the live server block. Its Content-Security-Policy allows BCP's API and Google's auth, Drive and Sheets hosts. Calling a new external host from the page means adding it there too.
Deploy
.gitea/workflows/deploy-scouting.yml builds the site and rsyncs dist/ to
/var/www/domains/gateway-gamers.net/scouting/ on every push to main that
touches sites/scouting/ or shared/. See the root README for local dev
commands and the shared header, footer and images.