Skip to content

Lichess UI Development

Jonathan Gamble edited this page Oct 23, 2022 · 17 revisions

Getting started

First, install the tools described on the main onboarding page.

There are three main types of code that UI contributors need to be aware of:

  • scala - see https://internet for help with this
  • javascript - mostly built from typescript sources with the .ts extension
  • css - compiled from SASS sources with the .scss extension

This guide will focus on javascript and css built from source in the top level ui directory in lila. This code is commonly referred to as the client.


Building the client

The main build script is ui/build. You run it, unsurprisingly, by typing ui/build from the lila root directory. It takes awhile to run. This wiki outlines the build process and the main tools involved but is mainly focused on ways to speed things up.

ui/bleep is a different way to build the client. It does everything that ui/build does but keeps watching source files - incrementally building any subsequent edits you make. When bleep is running, you can switch to your browser and press <shift> F5 (hard reload) just a few seconds after saving code changes to see them in action.

ui/bleep --help

Go ahead and monkey with the UI code while remaining completely ignorant of all dependencies - it's recommended by 9 out of 10 gastroenterologists.


Tools

You should learn about yarn. Meta™ forked yarn from npm many years ago, probably due to deep philosophical differences about usage of the word add versus install. Their capabilities are the same, but they do not like each other and get in unruly brawls about package lock files. So stick to yarn for lichess unless you know what you're doing.

Building the client involves tsc to compile typescript code to javascript, gulp to manage the compilation of *.scss SASS files into CSS, and rollup to compile the rest of the typescript (via typescript plugin) and bundle the result with its dependencies into a single javascript module suitable for linkage in an HTML <script> tag.

Building individual components

First get as much done as possible in your browser inspector. Tinker with css, inspect your js objects, click your buttons, click them all twice. When you're ready to apply changes to code:

  • css - From the ui directory, type yarn gulp css. You can also background that. Any changes you make to scss files will be incrementally compiled and the changes will be visible after a hard reload of your browser. You're done. If you just want to build the current scss without entering watch mode, yarn gulp css-dev will do that.

  • javascript - In many ui module subdirectories, you can simply type yarn run dev and see the changes immediately after a hard reload. Sometimes you need to run yarn run plugin-dev <plugin> (or yarn run all-dev where available). Inspect the "scripts" in package.json and if there are plugin targets, look in rollupconfig.mjs to discover their names. Currently analyse, site, round, chart, and mod are split into plugins. The rest you can bundle with yarn run dev.

For example, changes applied by the following commands will be usable after a hard browser reload or server restart:

  • cd <lila>/ui; yarn gulp css - watches all scss files in ui/* and rebuilds as needed
  • cd <lila>/ui/lobby; yarn run dev - builds the lobby module
  • cd <lila>/ui/site; yarn run all-dev - builds the site module (including all plugins)
  • cd <lila>/ui/chart; yarn run plugin-dev game - builds the game plugin in chart. yarn run dev won't cut it here.

Look ma, no hands!

At this point you might wonder, why do I have to run these yarn commands every time I change some typescript? Why can't I have incremental compilation just like yarn gulp css does for css, but without using bleep? You can. Add --watch to the end of your yarn command and it will keep running and trigger a fast recompile every time you change a source in that module. So the above examples become:

  • yarn run dev --watch (in lobby)
  • yarn run all-dev --watch (in site)
  • yarn run plugin-dev game --watch (in chart)

And so on. If you don't want to open multiple terminals, you can safely background one or more of those processes. Keep in mind that yarn ... --watch may not be available in dependency modules such as common, ceval, or chess. You must look at the package.json files in the root of each module directory to discover how they all work together. Pay attention to the "dependencies" object and build commands in the "scripts" object.


Customizing linked npm/yarn modules

How about when you need to make changes to a module from the npm registry such as chessground? For that, you can use yarn link.

In a nutshell, clone the repo you want to modify to <local-package-version>. Make your changes and recite whatever bizarre incantations are required to build it. If chickens must be sacrificed, ensure they are no-antibiotic free range chickens to comply with GPL3's guidelines on ritual sacrifice in a derived work. Then do the following:

  1. cd <local-package-version>
  2. yarn link
  3. cd <lila> - the main lila project directory (not ui)
  4. yarn link <name-of-the-package-in-package-json>

This creates a symlink to <local-package-version> in the secret ~/.config/yarn/link directory and creates a symlink in /node_modules/<name-of-package> that points to other symlink. You will also need to build whatever ui module(s) or plugin(s) that references the package. Note that bleep or yarn run ... --watch should pick up changes in the linked package and build dependencies so if you have things set up right, you might not need to do anything but hard reload to see new changes in your linked package.


Here are some useful links: