Skip docs navigation
A reproducible detached-repository path for building, bundling, registering, and launching a TPG game.

External Game Repo Workflow

This workflow is the reproducible path for a game that lives outside the TPG monorepo but still builds, registers, and launches through the platform.

Use it when you want to prove that an author-owned repository depends only on public packages, bundle files, and registry API endpoints.

For a supported starting point outside the monorepo, use npm create @tpgames/game@latest. If @tpgames/sdk-dev-kit is already installed, tpgames init <target-dir> creates the same starter. The package embeds and customizes templates/game-kit-starter/. The examples/external-game-repo/ directory remains the proof fixture for detached package install and registry upload behavior.

What the Workflow Proves

  • the game repository can be copied away from the monorepo and still run its own package scripts
  • the public @tpgames/game-kit authoring package can be installed into that detached repository
  • TypeScript host/controller surfaces can be built before packaging
  • npm run bundle produces a registry-ready zip archive without requiring a host-installed zip binary
  • npm run register -- --mode publish --yes uploads, submits, publishes, and verifies the game through registry HTTP APIs with a scoped creator API key
  • the shell discovers the published manifest and loads the published host and controller assets from the registry asset origin
  • authors can exercise the same shell and websocket room flow on multiple physical devices before any registry upload

Reference Fixture

The checked-in fixture is the current reference implementation:

The fixture intentionally keeps the public repository contract small:

  • package.json declares the public TPG packages the game needs.
  • src/host.ts and src/controller.ts use @tpgames/game-kit, which owns iframe postMessage setup and runtime bootstrap.
  • tpgames bundle reads tpgames.json, renders dist/manifest.json, copies the package-backed HTML templates plus Vite-built surface assets, and writes the zip.
  • tpgames register safely stops after upload by default; tpgames register --mode publish --yes also submits, creator-publishes, and verifies the manifest against the production registry or an explicit override.
  • .github/workflows/register-game.yml first resolves a ci-skip: head commit subject, plus Cloudflare-compatible skip subjects such as [CI Skip], as a green early exit. It then runs pull request checks without registry secrets and uploads the generated dist/*.zip file as a registry-bundle Actions artifact for review. It runs npm run register -- --mode publish --yes only for configured main branch or manual publish events.

Starter Template

The author-facing starter lives at:

Create a customized project from any directory with:

It has the same browser-authenticated local and API-key CI registration contract as the fixture, but uses author-facing naming, a surfaces/ folder, flat starter HTML, and a tiny typed host/controller game that demonstrates shared state and player state through @tpgames/game-kit. The scaffold command sets the package name, game id, title, and version defaults while keeping iframe messaging behind @tpgames/game-kit. The generated workflow runs the shared npm run check contract on pull requests to main, then keeps the generated dist/*.zip bundle available as a registry-bundle Actions artifact. Upload/publish still requires configured TPG_API_KEY secret on a main push or manual dispatch. npm run publish:dry-run proves the intended archive and registry operation locally without credentials.

Generated projects also include AGENTS.md and a self-contained tpg-game-development skill. Compatible coding agents can use it without access to this monorepo.

Multi-device development without uploading

The starter and reference fixture configure tpgWorkbench(...), so their local Vite surfaces can be attached to a real shell room:

tpgames starts the local server, creates a temporary Cloudflare Quick Tunnel, and opens a random room at https://play.tp.games. The host fetches a bounded development manifest once, validates its game ID and same-origin entry base, and places the normalized manifest—not the source URL—in the authoritative room snapshot. Controllers and spectators therefore mount the same local surface URLs without accessing the registry.

Requirements are Node 24, the normal public author packages, the Vite workbench plugin, and cloudflared. If another tunnel is already running, pass its HTTPS origin with --public-url; use --shell-url http://127.0.0.1:<port> when testing an unreleased shell locally, or --no-open to print the host link. Each room's development selection expires eight hours after launch and receives the unreviewed iframe capability baseline. Treat the generated host link as private because it contains the temporary development-manifest descriptor. Quick Tunnels expose the local Vite server and source modules publicly, so share only the room QR or controller invite, keep .env files, credentials, and private assets outside Vite's served root, and stop the command and tunnel after the test.

To use a Quick Tunnel you manage, run both commands and keep the port identical:

For a named tunnel, configure the public hostname's ingress service as http://127.0.0.1:5173, run cloudflared tunnel run <name>, then pass the hostname to --public-url. The CLI does not own or stop a tunnel supplied this way. It opens the host link first; the room QR and controller invite are created after the shell connects. In a headless environment, --no-open prints that host link.

Local Reproduction

Build public package artifacts from the TPG repo first when testing unreleased workspace changes:

Then copy the example outside the repository and install dependencies from that detached location:

The copied .npmrc uses the public npm registry. No package credential is required.

Render a bundle:

The output should include:

Start the registry and browser approval shell from the TPG repository in two terminals:

Register the game from the detached external repository:

The shell runs at http://127.0.0.1:3000 and the registry at http://127.0.0.1:4020. The default mode is upload; use --mode submit to place the exact bundle in the review queue. After accessibility certification, an approved version can be published from the portal or creator endpoint. The interactive login opens the local shell, requires explicit approval, and saves a session scoped to the exact loopback registry origin. Run npm exec -- tpgames whoami --registry-url http://127.0.0.1:4020 to verify it and npm exec -- tpgames logout --registry-url http://127.0.0.1:4020 to revoke it.

The tpgames browser approval page showing the terminal code, signed-in account, requested permissions, and approve or deny actions.

For unattended CI, create TPG_API_KEY from the creator portal. The key needs games:read, games:write, games:submit, and games:publish for the full publish path.

CI Contract

External repositories should keep CI aligned with the same package scripts:

Keep TPG_API_KEY in CI secrets. Demo creator tokens are only for local key creation and preview verification; external CI should not store reviewer tokens. Pull request runs should retain the generated dist/*.zip bundle as a registry-bundle Actions artifact so reviewers can inspect the exact upload candidate before creator registry secrets are enabled or a main publish runs.

Verification in This Repo

The repository locks this workflow with integration coverage in apps/web-shell/src/platform/registry.integration.test.ts.

That test copies examples/external-game-repo into a detached temp directory, installs packed public TPG packages, runs the example's own package scripts under a restricted PATH, and verifies:

  • registry upload, submit, and creator-owned publish succeed with a scoped API key
  • discovery returns the published game
  • the published manifest has a registry entryBaseUrl
  • host.html and Vite-built host.js are served from /published-assets/:gameId/:version, without low-level runtime vendor files

Run the proof directly:

Remaining Boundaries

This workflow proves a separate repository can scaffold, build, and register a TPG game. It is not a separate moderation product or a self-hosted discovery system. Today, the registry remains the publication and asset-serving boundary for uploaded games.