Platform for playing multiplayer board games on the web, powered by Typescript, NodeJS, Socket.io, and React.
Owner: dicksontsai
Hosted at: http://boardgames.dicksontsai.com
NOTE: Hosting can be taken down at any time.
This repository is a public fork of my private repo without all the games seen in my website. It contains all of the platform code. I am not accepting any changes to this repository at this time.
The server is in the server directory. README
The client is in the client directory. README
For a simple example, see how TicTacToe is implemented in the above READMEs.
package.json declares this project's dependencies. Running npm install will
create a node_modules directory with the actual dependency code and a
package-lock.json file with the actual dependency version numbers.
Ensure you have NodeJS installed.
- Run
npm installin theclientdirectory. - Run
npm installin theserverdirectory.
- In one terminal, go to the
serverdirectory.- Inside the
serverdirectory, runnpm run syncfe, which compiles server Typescript and outputs types to the client. - Run
npm start.
- Inside the
- In another terminal, run
npm startin theclientdirectory. NOTE: You must run the server first, because the server will generate Typescript types used by the client. - You can now open multiple tabs on
localhost:3000
The server's npm run syncfe generates Typescript types and enums, then copies them
to client/src/serverTypes. See the Enums section below for details.
Additional server commands:
npm run syncfe: Remove existing Typescript cache and runtsc. Guaranteed to output types for the frontend.npm run build: Simply runtsc. Not guaranteed to output types for the frontend.npm test: Run tests.npm test -- src/EXAMPLE_tictactoe: Run tests whose path matchessrc/EXAMPLE_tictactoe.
To play with your backend code without having to implement a frontend, navigate
to localhost:3000/debug/<game_id>/<num_players>, for example
localhost:3000/debug/TicTacToe/5. In this view, you can see the state as
observed by each participant. You can also send UI Actions.
CI triggers when you label your PR. I have added a dummy runCIForPR label for
this specific purpose. Please invoke CI right before you merge, unless the
only changes since the last CI run are just documentation changes.
Pushing directly to master will also run CI.
- Set up Heroku CLI.
- Create a new app. You should get an ID like
some-words-12345. - Create a
boardgames-deploydirectory at the top level of this repo (same level asclientandserver). - Within
boardgames-deploy:- Run
heroku login. - Run
git initto create a new sub-repo that will match Heroku's deployment. - Run
heroku git:remote -a some-words-12345to connect with Heroku's repo.
- Run
- Return to the top level directory and run
deploy.sh. This will deploy your code to Heroku. - Setting up a custom domain:
- Run
heroku domains:add subdom.yourwebsite.com - Run
heroku domainsand locate the DNS target, which should end withherokudns.com. - With your domain provider (e.g. Namecheap), add a CNAME Record pointing the host
subdomto the DNS target.
- Run
After you have set up boardgames-deploy, run ./deploy.sh for each subsequent deployment.
In the client or server directory, you can run the following to format your
files automatically:
./node_modules/.bin/prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}"
For those newly cloning the repo, if you see type errors at HEAD, it could
be that your npm is not respecting the package-lock.json files in the
respective client and server directories.
package-lock.json ensures that dependencies remain constant. However, it can
fall behind the actual versions declared by package.json. The owner of the
repo shall run npm upgrade from time to time.
Most dependencies in package.json should look like ^10.1.0. The ^ means
that package.json should use the latest minor version. CAUTION: Sometimes,
minor version updates can accidentally introduce breaking changes.
In the backend, put your enums in the src/shared/enums directory. The build
step will handle copying the .ts files in that directory to the frontend.
We can't simply rely on the declaration files (d.ts), because the Javascript
code might actually use those values. d.ts files cannot be imported as
vanilla JS modules. The use of const enum isn't supported by create-react-app,
because create-react-app depends on --isolatedModules.
Maps should be favored over objects, since they play better with type checking.
Exception: Maps do not serialize into JSON as expected! (e.g. when sending
an object from server to client). Maps cannot serialize into JSON because the
keys are not restricted to string types. Use objectFromMap or mapFromObject
before sending maps through the socket.
See the full list at client/src/allGames.ts
Special thanks to contributors:
- Nicolas Arquie (our resident Cupertino board game guru)
- Wells Santo
- Evi
- Kelly Hong
- codenames.plus (original inspiration for this project)