This is a documentation for Board Game Arena: play board games online !

Using Typescript and Scss

From Board Game Arena
Revision as of 15:40, 19 December 2025 by Thoun (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This page will help you set up your project to use Typescript client file and Scss style files, and automatically build Javascript (in ES5) files and CSS files so your project stay compatible to BGA framework requirements. You can use only TS or only SCSS part if you want, they are not linked.

The following document is geared towards setting up a custom project where you will be in charge of typing all components that you want to use. There is also untested 3rd party project that aims to automate some of the steps below, you can look at this instead BGA Type Safe Template.

Install and configure

Install dev stack

Install node/npm. Here is an example to activate auto-build in Visual Studio Code, if you use another tool I strongly recommend to find an equivalent so you don't have to launch build manually after each modification.

Configure package.json and tsconfig.json

Create a file named package.json on the root folder, not on the src folder.

package.json

 {
   "name": "yourgamename",
   "version": "1.0.0",
   "description": "",
   "main": "YourGameName.js",
   "scripts": {
     "build:ts": "rollup -c",
     "build:scss": "sass --no-source-map src/yourgamename.scss yourgamename.css",
     "watch:ts": "rollup -c -w",
     "watch:scss": "sass --watch src/yourgamename.scss yourgamename.css",
     "watch": "npm run watch:ts && npm run watch:scss",
     "build": "npm run build:ts && npm run build:scss"
   },
   "author": "yourname",
   "license": "MIT",
   "devDependencies": {
    "@rollup/plugin-typescript": "^12.3.0",
    "rollup": "^4.53.3",
    "sass": "^1.71.0",
    "tslib": "^2.8.1",
    "typescript": "^5.3.3"
   }
 }

Note: if you not using scss - remove corresponding scripts and deps.

When package.json is created, run npm i on the root folder to install builders (will generate a node_modules folder).

IMPORTANT: exclude node_modules/ subfolder from auto-sync to remote folder (whatever system you use for that).

For Typescript compilation we also need to set up rollup.config.mjs and tsconfig.json on the root folder.

rollup.config.mjs

  import typescript from '@rollup/plugin-typescript';

  export default {
    input: 'src/<yourgamename>.ts',
    output: {
      file: 'modules/js/Game.js',
      format: 'es',
      sourcemap: false,
      inlineDynamicImports: true,
    },
    plugins: [
      typescript({
        tsconfig: './tsconfig.json',
      }),
    ],
    treeshake: false,
  };

tsconfig.json

  {
    "compilerOptions": {
      "target": "ES2020",
      "module": "ES2022",
      "moduleResolution": "node",
      "lib": ["dom", "esnext"],
      "sourceMap": false,
      "rootDir": "src"
    },
    "include": [
      "*.d.ts",
      "src/**/*.d.ts",
      "src/**/*.ts"
    ]
  }

Create skeleton

When you create your game in BGA Studio, a JS and CSS file are generated. As we will overwrite them with autobuild. You can put the TS/SCSS files on a src folder to separate them from built files, but that's not mandatory. Note to myself: check if 'src' dir will be svn version control, if not cannot really use it (even if duplicated in git).

Note: if you're using SFTP and have "bga-framework.d.ts" in the ignore list - remove it and resync. You will need this file.

Typescript file skeleton

Typescript example here have been stripped down of all comments for clarity. Your TS code can be splitted in multiple files, you can have a look at castlecombo code for inspiration. To make this page concise, I removed comments and code samples. If it's your first game, well - don't do it if your first game - you won't be able to apply other code samples from docs, they all using dojo style and have to completely rewritten.

src/yourgamename.d.ts

interface YourGameNamePlayer extends Player {
    cards: Card[]; // any information you add on each result['players']
}

interface YourGameNameGamedatas extends Gamedatas<YourGameNamePlayer> {
    // Add here variables you set up in getAllDatas
    discardedCards: { [row: number]: Card[] };
    remainingCardsInDecks: { [row: number]: number };
    tableCards: { [row: number]: Card[] };
}

Not: the Generic typing is optional.

src/yourgamename.ts

class Game {

    public bga: Bga;
    private gamedatas: YourGameNameGamedatas;

     constructor(bga: Bga<YourGameNameGamedatas>) {
        this.bga = bga;
     }
     
     public setup(gamedatas: YourGameNameGamedatas) {
         this.gamedatas = gamedatas; 
         this.setupNotifications();
     } 
     public onEnteringState(stateName: string, args: any) {}
     public onLeavingState(stateName: string) {}
     public onUpdateActionButtons(stateName: string, args: any) {} 
     public setupNotifications() {}
}


Don't forget to sync the bga-framework.d.ts from your FTP folder regularly to get the last version.

SCSS file

Nothing special here, just write classic SCSS (will be compiled by Dart scss) and name it src/yourgamename.scss.

Example:

  @use 'variables' as v;


  /* the other files */
  @use "./Animations";
  @use "./Board";

  #ebd-body {
    background-image: url(img/woodbg.jpg);
    background-repeat: repeat;
  }
  @each $key, $val in v.$colors-list {
    .fgcolor#{$key} {
      color: #{$val};
  }


Your SCSS code can be (should be) splitted in multiple files, for example:


variables.scss

$colors-list: (
  _6cd0f6: #6cd0f6, // blue
  _ef58a2: #ef58a2, // pink
  _ffcc02: #ffcc02, // yellow
  _a0d28c: #a0d28c // green
);

Auto build and auto upload

Auto build JS and CSS files

To build and watch (i.e. re-build continuously changed files) run in terminal:

 npm run watch

Alternately you can make vscode to do it for you by installing Run on Save extension, see details in Setting_up_BGA_Development_environment_using_VSCode

Note: to build without watch

 npm run build

Auto-upload generated files

You can setup standard file sync or use vscode SFTP extension, see details in Setting_up_BGA_Development_environment_using_VSCode

Make sure that your sftp.json file has a "watcher" section to detect and upload changes made outside of the VSCode IDE.

    "watcher": {
        "files": "**/*.{js,css}",
        "autoUpload": true,
        "autoDelete": true
    }

Exclusions from auto-upload

Make sure .vscode and node_modules are in .gitignore if you commit your project somewhere.

Code completion

To have a code completion for framework classes, dojo, stock, etc, you'll need to make sure bga-framework.d.ts file is added to your tsconfig.

Using the new libs

To use the new front libs (bga-autofit, bga-score-sheet, ...), it's recommended to created a dedicated file that will be responsible of all imports, than you'll import when you need it

libs.ts

import type { BgaAnimations as BgaAnimationsType } from "../bga-animations";
import type { BgaCards as BgaCardsType } from "../bga-cards";

const BgaAnimations: typeof BgaAnimationsType = await globalThis.importEsmLib('bga-animations', '1.x');
const BgaCards: typeof BgaCardsType = await globalThis.importEsmLib('bga-cards', '1.x');

export { BgaAnimations, BgaCards };

Then you can use them in your files using import:

import { BgaCards } from './libs';
export class MyCardManager extends BgaCards.Manager<Card> { ... }

For class property typings, use:

    public animationManager: InstanceType<typeof BgaAnimations.Manager>;

    // in your setup:
    this.animationManager = new BgaAnimations.Manager({ ... });

If you need to load old libs, you can do it this way:

const [Counter, Stock] = await importDojoLibs(["ebg/counter", "ebg/stock"]);

export { Counter, Stock };

migrating from old way (ES5 build to gamename.js)

the new setup described in this page use explicit import/export that were not used before. But we don't need to explicitely list all files anymore.

For example, if you have a file for MyCardManager and a file for MyGame, you'll need to do this:

MyCardManager.ts

export class MyCardManager { ... }

MyGame.ts

import { MyCardManager } from "./MyCardManager";

export class Game implements Bga {
    public cardManager: MyCardManager;

Referenced Projects