its-janghoon/open-games

An open, growing collection of original browser games. TypeScript + Vite + Phaser 3 in one npm workspaces monorepo, all deployed to a single GitHub Pages site.

★ 0Forks 0TypeScriptGitHub ↗Compare

Project website ↗

2d-gamebrowser-gamegame-collectiongame-developmenthtml5-gamesopen-source-gamesphaserphaser3typescriptvitewebgl

README

open-games

A monorepo of original browser games, built with TypeScript + Vite and deployed together to a single GitHub Pages site. The repo uses npm workspaces: one root npm install, one root lockfile, and shared hoisted dependencies across every game.

Not affiliated with any game studio. All names, characters, abilities, items, and lore in these projects are original works inspired only by generic genre archetypes.


The games

Each game lives in its own workspace under packages/, described by a game.json next to its package.json. That file is the single source of truth: the table below, the landing page, and the deploy workflow are all generated from it.

Package Game Genre Stack Summary
packages/champs Arena Champions (아레나 챔피언스) MOBA Vite + React 18 + TypeScript + Phaser 3.80 A three-lane 5v5 MOBA with champion select, turrets and inhibitors, minion waves, major neutral objectives, and a 2.5D vector battle view.
packages/whiteout Frosthold: Last Ember (서리성채: 마지막 불씨) Survival City-Builder Vite + TypeScript + Phaser 3.80 A frozen-survival city-builder: keep the central furnace burning, run idle resource buildings, and repel escalating cold-season sieges.
packages/gridfall Gridfall (그리드폴) Local-network Raycast Shooter Vite + TypeScript + Phaser 3.80 A two-player shooter rendered by raycasting a tile grid into vertical columns — no textures, no models, no 3D scene. Built on the same rollback core as Ringout so two people on one network can play with no server between them.
packages/kingshot Kingdom Rise (킹덤 라이즈) Strategy / Idle Vite + TypeScript + Phaser 3.80 A medieval kingdom builder with idle resource output, a town-center-gated building tree, troop training queues, and wave-based combat.
packages/lastwar LAST SQUAD (라스트 스쿼드) Squad Auto-Battler Vite + TypeScript + Phaser 3.80 A survival base-builder and squad auto-battler with a story campaign, endless horde defense, and a lane gate-runner mini-game.
packages/ringout Ringout (링아웃) Two-player Geometric Fighter Vite + TypeScript + Phaser 3.80 A two-body fighter drawn entirely from geometric parts, with no sprite sheets and no animation frames — every pose is computed. Built to be rolled back, so two people on the same network can fight with no server between them.
packages/wirework Wirework (Wirework) Top-down Ring Defense Action Vite + TypeScript + Phaser 3.80 Tether through a capacitor city and cut rear cooling nodes to stop autonomous siege machines.

Every game ships with its own README.md, tests, and (where applicable) asset generators under tools/. Some games add libraries of their own on top of the shared Vite + TypeScript + Phaser 3 base - the Stack column above lists what each one actually uses.

The original single-game Arena Champions README now lives at packages/champs/README.md.


Repository layout

open-games/
├── package.json              # root: npm workspaces + fan-out scripts
├── package-lock.json         # single lockfile for all workspaces
├── LICENSE                   # single Apache-2.0 license for the whole repo
├── CONTRIBUTING.md           # repo-wide rules + new-game checklist
├── .gitignore                # consolidated ignore rules
├── scripts/
│   ├── lib/games.mjs         # loads + validates every packages/*/game.json
│   ├── gen-readme.mjs        # regenerates the tables in this README
│   └── new-game.mjs          # scaffolds packages/<slug> from the template
├── site/
│   ├── index.template.html   # landing-page markup (no game data in it)
│   └── build.mjs             # renders the landing page from every game.json
├── packages/
│   ├── _template/            # starter for a new game; not a workspace
│   └── <slug>/               # one workspace per game, each with a game.json
└── .github/workflows/deploy.yml   # builds every workspace + landing page, deploys to Pages

Nothing outside packages/<slug>/ names an individual game or counts how many there are.


Getting started

Requires Node 22 and npm 11.

Install everything with a single root install - npm workspaces hoist and share dependencies across all games, and produce one root package-lock.json:

npm install            # from the repo root; installs all workspaces

Do not run npm install inside individual packages - the workspaces setup handles them.


Working on one game

Use npm's -w (workspace) flag to target a single package, where <slug> is any directory under packages/:

npm run dev -w packages/<slug>        # start the Vite dev server for one game
npm run build -w packages/<slug>      # type-check + production build for one game
npm run test -w packages/<slug>       # run one game's unit tests
npm run typecheck -w packages/<slug>  # type-check only, no emit

Each game builds with Vite and emits to packages/<slug>/dist.


Root scripts

The root package.json fans out across all workspaces via --workspaces --if-present:

npm run build        # build every game, then generate the landing page
npm run build:games  # build every game only
npm run build:site   # generate the landing page into _site/ only
npm run test         # run every game's tests
npm run typecheck    # type-check every game
npm run docs:readme  # regenerate the tables in this README from game.json
npm run docs:check   # verify those tables are up to date (no writes)
npm run new-game     # scaffold a new game; see below
npm run thumbs       # re-capture the landing-page thumbnails (maintainer tool)

Adding a new game

Four steps, none of which touch a shared file:

  1. Scaffold it. npm run new-game -- --slug foo --title "Foo Quest" copies packages/_template to packages/foo and substitutes the placeholders.
  2. Describe it. Fill in packages/foo/game.json (genre, summaries, stack) and set status to playable when it is ready to list.
  3. Wire the install. Run npm install from the root so the new workspace is linked.
  4. Verify. npm run typecheck && npm run test && npm run build, then npm run docs:readme to refresh the tables above. Run npm run thumbs once the game renders, so the landing page shows a real screenshot instead of a placeholder tile.

The landing page, the tables in this README, and .github/workflows/deploy.yml all pick the game up on their own. See CONTRIBUTING.md for the full checklist and the original-naming rules.


Deployment & subpath scheme

Every game deploys to a single GitHub Pages site at:

https://savagemanage.github.io/open-games/

The Pages workflow at .github/workflows/deploy.yml builds every workspace, collects each packages/<slug>/dist into a <slug>/ subpath by globbing (no game is named in the workflow), generates the root landing page, and publishes them together. Each subpath matches the base configured in that game's vite.config.ts (production base /open-games/<slug>/, dev base /):

URL Source
https://savagemanage.github.io/open-games/ root landing page (site/index.template.html + site/build.mjs)
https://savagemanage.github.io/open-games/champs/ packages/champs
https://savagemanage.github.io/open-games/whiteout/ packages/whiteout
https://savagemanage.github.io/open-games/gridfall/ packages/gridfall
https://savagemanage.github.io/open-games/kingshot/ packages/kingshot
https://savagemanage.github.io/open-games/lastwar/ packages/lastwar
https://savagemanage.github.io/open-games/ringout/ packages/ringout
https://savagemanage.github.io/open-games/wirework/ packages/wirework

Enable Pages once under Settings → Pages → Build and deployment → Source: GitHub Actions.


Contributing

See CONTRIBUTING.md for repo-wide rules: the new-game checklist, the checks a change has to pass, and the original-naming policy. Individual games may add their own guide on top - for example packages/wirework/CONTRIBUTING.md.


License

This project is licensed under the Apache License 2.0. A single LICENSE file at the repo root applies to every workspace; each package's package.json also declares "license": "Apache-2.0".

© 2026 Janghoon Lee

Contributors

kiro-agentits-janghoonclaude

Issues