gbl-uzh is the code repository of the Game-Based Learning project (https://www.gbl.uzh.ch/) developed at the Department of Finance of the University of Zurich.
Game-based learning has many benefits for lecturers and students. However, it can be difficult to get started with developing learning games and integrating games with other curricular activities. We want to foster the application of game-based learning in the university context by providing foundational resources for game usage and development based on what we have learned on our own journey.
For more details on our future plans, have a look at our Roadmap.
The gbl-uzh project consists of the following key components:
- The
GBL Website(located in theapps/websitedirectory), a Next.js web application that summarizes all of the outputs of our project on a single site. TheGBL Websiteis hosted publicly on https://www.gbl.uzh.ch. - The
GBL Knowledge Base(located in thekbdirectory as a Git submodule), an Obsidian knowledge graph that contains the knowledge on gamification and game-based learning that we gather and curate throughout this and other projects. The knowledge base also serves as a Content Management System (CMS) for theGBL Website. TheGBL Knowledge Baseis publicly accessible on https://www.gbl.uzh.ch/kb. - The
GBL Advisor(located in theapps/advisordirectory), an advisory wizard for getting started in the space of Game-Based Learning as a teacher. The advisor is built on the Twinery text-based serious game engine. - The
GBL Platform(located in thepackages/platformdirectory), a code framework for building round-based simulations with Next.js and React. Documentation for building games on the platform (written for humans and AI coding agents) lives indocs/, with matching agent skills in.agents/skills/.
Want to build a learning game on the platform? docs/getting-started.md takes you from zero to a running local environment with an AI assistant that does the technical work — no coding experience needed. The same starter devcontainer also gives developers a zero-setup environment; the devrouter-based configuration for running many projects side by side is described in .devcontainer/README.md.
All three modes share the same OIDC mock config, database image, and schema/seed (one-click admin login, no Auth0 account needed); they differ in where the app process runs, how it is reached, and which script bootstraps it (the devcontainers use .devcontainer/post-create.sh, native mode uses pnpm bootstrap). Run bash .devcontainer/smoke.sh on the native host or inside the selected app container; probe a devrouter HTTPS route separately from the host.
| Mode | For | Setup |
|---|---|---|
| Starter devcontainer | First-time users, game builders — works natively with the VS Code Dev Containers extension | Open in VS Code, pick GBL Starter; app on http://localhost:3000 (walkthrough) |
| Devcontainer + devrouter | Maintainers running many projects side by side | dev up, then dev workspace ensure . for a linked worktree; use dev ls for its namespaced URL (details) |
Native pnpm dev |
Developers who prefer the host toolchain (Node 24+, PNPM 11) | Native quickstart below; app on http://localhost:3000 |
- Make sure Docker is running and ports 5432, 8090, 3000 are free.
- Get the pinned pnpm (
11.6.0) — an older pnpm exits fine but leaves a stalenode_modulesbehind:- Volta (team default): Volta's pnpm support is behind a feature flag — add
export VOLTA_FEATURE_PNPM=1to your shell profile, otherwise Volta silently runs its default pnpm and ignores the repo pin. - No Volta:
corepack enablehonors thepackageManagerfield. - Either way, verify:
pnpm --versioninside the repo must print11.6.0.
- Volta (team default): Volta's pnpm support is behind a feature flag — add
pnpm installpnpm bootstrap— starts Postgres and the local login mock (replaces Auth0, no account needed), builds the shared packages, then prepares and seeds the database. Run it once per game.pnpm dev— also brings the two services back up if they are not running.- Open http://localhost:3000/admin/login and click the login button — no password; you are the dev admin
gbl-dev@df.uzh.ch. - If something seems off,
bash .devcontainer/smoke.shtells you whether the login mock, the app, or your setup is at fault. Its third argument names the game, so an example game isbash .devcontainer/smoke.sh '' '' central-bank.
Both commands take the game as an argument; without one they run the demo game. Everything else is identical — same Docker stack, same mock login. Prisma creates that game's database on the first push, so nothing extra has to be provisioned:
| Game | Bootstrap (once) | Start |
|---|---|---|
| Demo game | pnpm bootstrap |
pnpm dev |
| Central Bank | pnpm bootstrap central-bank |
pnpm dev central-bank |
| Rate Wars | pnpm bootstrap rate-wars |
pnpm dev rate-wars |
pnpm dev runs exactly one game, plus the watch builds of @gbl-uzh/platform and @gbl-uzh/ui so edits to the shared packages reach it. One at a time is the point: all three games bind port 3000 and hardcode http://localhost:3000 in their .env.development, so a second game started in parallel silently lands on 3001 with authentication URLs pointing at the first one. Running two side by side means overriding PORT and its three app-side URLs for the second one (see below). Each game keeps its own database (prisma, central_bank, rate_wars) on the shared Postgres, so switching between them does not wipe the others.
The scripts also accept GBL_GAME_TARGET instead of the argument, which is how the devcontainers select their game; an explicit argument wins over the variable.
If a default port is taken, every override needs its app-side counterpart (each game reads its defaults from its own .env* files): GBL_DB_PORT also needs DATABASE_URL/SHADOW_DATABASE_URL, GBL_OIDC_PORT also needs GBL_MOCK_OIDC_ISSUER, and PORT also needs NEXTAUTH_URL/NEXT_PUBLIC_APP_URL/NEXT_PUBLIC_API_URL — see the header of docker-compose.yml. Pass the resulting URLs to the diagnostic, for example bash .devcontainer/smoke.sh http://localhost:13000 http://localhost:18090/default. Login against a real Auth0 tenant instead of the mock requires GBL_AUTH_MODE=auth0 in the game's .env.local (see .env.local.template).
- Building a game with the starter devcontainer: only Docker Desktop, VS Code, and the Dev Containers extension — see Getting Started.
- Working on the codebase outside a devcontainer: Docker / Podman, Node.js 24+, PNPM 11. The repo pins both (
voltafield andpackageManager); see step 2 of the native quickstart for making the pnpm pin actually apply (Volta needsVOLTA_FEATURE_PNPM=1).
We welcome any contributions to the project. If you would like to contribute to the code base, please create an Issue beforehand to ensure that your goals align with our project vision. If you would like to give us feedback or have any requests regarding content of the website or knowledge base, please add a new entry in Discussions.
The GBL Website and Knowledge Base, as well as other published subcomponents, are licensed under the AGPLv3.