Skip to content
game-client · vite · arpg

Standalone game clientARPG Web

A standalone Vite + React client for the ARPG, served as static files behind nginx at arpg.kbve.com. It is the single source of truth for the game — and the CDN that feeds the arcade page and Discord Activity embed.

One source, three surfaces

The game source, embed entries, and sprite art all live under apps/agones/arpg/web/. Three build modes share it — the standalone app, an embed IIFE for kbve.com/arcade, and a Discord Activity bundle.

  • CDN — arpg.kbve.com serves app, embed, Activity + LFS art.
  • No guest path — real Supabase login, verified by arpg-server.
arpg-webApp
Vite + ReactClient
kbve/arpg-webImage
betaStatus

What it gives you

Features

Single source of truth

The game source lives at apps/agones/arpg/web/src/game/; the arcade page and Discord embed consume a built bundle, not the source.

Three build modes

vite build emits the standalone app, an --mode embed IIFE bundle, and an --mode discord Activity bundle from one source.

CDN origin

arpg.kbve.com serves the app, embed bundle, Discord Activity, and the Git-LFS sprite art cross-origin with Access-Control-Allow-Origin: *.

Real Supabase auth

The client runs a real Supabase login; the session JWT is verified by arpg-server against GoTrue. Empty or invalid tokens are denied — no guest path.

Why it exists

Overview

arpg-web is a standalone Vite + React client for the ARPG, served as static files behind nginx. It is the single source of truth for the game — the source lives at apps/agones/arpg/web/src/game/. The two other play surfaces (the Astro page at kbve.com/arcade/arpg/ and the Discord Activity embed) consume a built bundle emitted from this app rather than the game source, so all three surfaces run one build.

Booting the full astro-kbve site (Starlight + hundreds of content pages + the proto/content pipeline) just to serve one game page is heavy. This app pulls only what the game needs, so it builds and boots fast, and gives arpg.kbve.com a real frontend instead of only the WebSocket endpoint.

The game source, embed entries, and sprite art all live under apps/agones/arpg/web/. The only cross-repo dependency is @kbve/laser (net + phaser helpers), aliased to its package source; the optional r3f layer is stubbed since the game never uses three.js. Three build modes share that one source:

  • default (vite build) → the standalone app for arpg.kbve.com (dist/)
  • --mode embedwindow.ArpgEmbed IIFE → dist/arpg-embed.js, served by arpg.kbve.com and loaded cross-origin by kbve.com/arcade/arpg
  • --mode discord → Discord Activity bundle → dist/discord/arpg/arpg.js (same arpg origin; the Activity portal proxies its page root to arpg.kbve.com/discord/arpg/)

arpg.kbve.com is the CDN: it serves the app, the embed bundle (/arpg-embed.js), the Discord Activity (/discord/arpg/), and the Git-LFS-tracked sprite art (public/assets/arcade/arpg/, blobs on git.kbve.com/KBVE/arpg.git). The other surfaces load the bundle, Activity page, and art cross-origin from it (nginx sends Access-Control-Allow-Origin: * on /assets/ and /arpg-embed.js). Nothing arpg-specific ships into the astro site.

Pipeline

Build, container & deploy

Terminal window
nx run arpg:web-build # app + embed bundle -> dist/ (arpg.kbve.com serves both)
nx run arpg:web-build-embed # embed bundle only -> dist/arpg-embed.js
nx run arpg:web-build-discord # Discord bundle -> dist/discord/arpg/arpg.js

web-build runs vite build && vite build --mode embed && vite build --mode discord, so apps/agones/arpg/web/dist holds the standalone app (index.html), the embed bundle (arpg-embed.js), and the Discord Activity bundle (discord/arpg/arpg.js). The container bakes all of it behind nginx, so arpg.kbve.com is the CDN.

Terminal window
nx run arpg:container-web

Multi-stage: a Node stage runs the Vite build with prod endpoints baked in (PUBLIC_ARPG_GAME_WS=wss://arpg.kbve.com/ws, PUBLIC_SUPABASE_URL=https://supabase.kbve.com), then an nginx:alpine stage serves the static dist on :5402 with an SPA fallback. CI publishes kbve/arpg-web.

Deployarpg.kbve.com routes split: /ws (and the WebSocket upgrade) → the arpg-server game pods on :7979; everything else → this static app on :5402. See apps/kube/agones/arpg/manifests/web-deployment.yaml and game-httproute.yaml.

Auth — the client runs the real Supabase login (buildNetConfigsrc/lib/auth.ts, a web-local Supabase session bridge); the resulting session JWT is verified by arpg-server against Supabase GoTrue (shared jedi JWT cache). An empty/invalid token is denied — there is no guest path.

Quality

Testing

Playwright e2e for the whole stack lives in apps/agones/arpg/arpg-e2e (Nx project arpg-e2e):

Terminal window
nx run arpg-e2e:e2e # boots arpg-server + this web app, runs server + web specs
nx run arpg-e2e:e2e:server # arpg-server only (handshake + live sim)
nx run arpg-e2e:e2e:web # this app via the Vite dev server (SPA shell, boot)
nx run arpg-e2e:e2e:cdn # the built nginx image — CORS, embed + Discord bundles
  • Server — signs a Supabase-style HS256 JWT (the server runs in local-secret mode) and drives the JSON wire from Node. Covers the handshake (Welcome carries PROTOCOL_VERSION 14 + the player/goblin/coin/dungeon-key registry; protocol / auth / empty-token / missing-username each emit a Reject) and the live sim: the admitted player shows up in the snapshot roster, the seeded world spawns goblins, a Step input advances the player tile, ticks + input_ack progress, a second login under the same username evicts the first (newest-wins), and two distinct players share the world on separate slots.
  • Web — boots the Vite dev server with the prod Supabase URL injected and asserts the app shell loads, mounts its root, serves the SPA fallback, and boots with no uncaught console error.
  • CDN (e2e:cdn) — runs the built kbve/arpg-web nginx image (needs Docker, so it’s the container tier like irc-e2e:e2e:docker) and asserts the real CDN headers the other surfaces depend on: Access-Control-Allow-Origin: * on /arpg-embed.js and /assets/, the Discord Activity page + bundle under /discord/arpg/, and the SPA fallback. Build the image first (nx run arpg:container-web).

Beta — local dev runs the full stack via nx run arpg:dev; production arpg.kbve.com serves this client once the image is baked and the HTTPRoute split lands.

Questions

Frequently asked

What is arpg-web?

arpg-web is a standalone Vite + React client for the ARPG, served as static files behind nginx at arpg.kbve.com. It is the single source of truth for the game, with source under apps/agones/arpg/web/src/game/.

How do the three ARPG play surfaces share one build?

The Vite source builds three modes — the standalone app for arpg.kbve.com, an embed IIFE bundle loaded cross-origin by kbve.com/arcade/arpg, and a Discord Activity bundle. arpg.kbve.com acts as the CDN that serves all of them plus the Git-LFS sprite art.

Does arpg-web support guest play?

No. The client runs a real Supabase login and the resulting session JWT is verified by arpg-server against Supabase GoTrue. An empty or invalid token is denied — there is no guest path.