Architecture

Some familiarity with JavaScript modules as well as with Symfony's Asset Mapper component is recommended in order to follow this section.

The ChesslaBlab website is a multi-page application (MPA) that is not adhering to the MVC architectural pattern. The controller actions are basically sending an HTML document to the browser on each request. The business logic is implemented in the chess server.

In this website architecture in particular, there is no model layer (M) and as a result the Controller layer (C) remains quite basic as in the following example. The main reason behind a multi-page architecture like this one as opposed to a single-page architecture is that we want the pages to be indexed by web crawlers.

<?php

namespace App\Controller\Pages\Play;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class ComputerController extends AbstractController
{
    public function index(): Response
    {
        retarurn $this->render('pages/play/computer/index.html.twig');
    }
}

As a rule of thumb, there is a .twig.html file and a .js file associated to each controller action. So the structure of the App\Controller\Pages namespace is mirroring the structure of both the templates/pages folder and the assets/js/pages folder.

This naming convention allows developers to reduce memorization because given one file name, the name of the remaining two can be inferred.

Each page's JavaScript file is then set up as an entrypoint in the importmap.php config file. The main point of the entrypoint script is to update the DOM on user interaction and data change.

So the JavaScript code in the assets/js/pages/play/computer/index.js file basically boils down to initialization because the business logic is implemented in WebSocket ESM modules. When the web browser retrieves the response from the WebSocket server, the ESM components are updated with the new data.

import { playComputerModal } from './PlayComputerModal.js';
import { binaryWebSocket } from '../../../websockets/binary/BinaryWebSocket.js';
import { stockfishWebSocket } from '../../../websockets/game/StockfishWebSocket.js';

try {
  await Promise.all([
    binaryWebSocket.connect(),
    stockfishWebSocket.connect()
  ]);
} catch {}

playComputerModal.props.modal.show();

WebSocket Connections

The ChesslaBlab website is integrated with PHP Chess Server, an asynchronous WebSocket server that provides functionality to play chess online over a WebSocket connection.

The environment variables required for the chess server can be found in the assets/env.example.js file.

As described in the docs, these are the game modes available:

  • analysis is used to start games for further analysis.
  • play allows to play chess online with other players.
  • stockfish allows to play chess against the computer.

The WebSocket ESM modules are implemented based on this same separation of concerns and abstraction: