{"id":35,"date":"2024-11-26T21:00:00","date_gmt":"2024-11-26T21:00:00","guid":{"rendered":"https:\/\/blog.chessboardmagic.com\/?p=35"},"modified":"2025-09-28T21:38:31","modified_gmt":"2025-09-28T21:38:31","slug":"chess-web-programming-part-four-chessboard-customisation","status":"publish","type":"post","link":"https:\/\/blog.chessboardmagic.com\/index.php\/2024\/11\/26\/chess-web-programming-part-four-chessboard-customisation\/","title":{"rendered":"Chess Web Programming: Part Four: Chessboard Customisation"},"content":{"rendered":"\n<p><strong>Customising the Chessboard<\/strong><\/p>\n\n\n\n<p>I began my journey into modern web programming in October 2023, with&nbsp;<em><strong><a href=\"https:\/\/chessboardmagic.com\/\">Chessboard Magic<\/a><\/strong><\/em>&nbsp;as my first major project. Initially, it was just a simple exercise, but it quickly expanded, and now&nbsp;<em>Chessboard Magic<\/em>&nbsp;includes 34 unique chess-based applications! I\u2019ve learned a lot along the way and want to share my experiences with you, hoping it encourages you to try building your own applications.<br>In case you missed them, here are the previous articles in this series:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-one-getting-started\/8ZKpwJU8\">Part One: Getting Started<\/a><\/strong>\u00a0\u2013 We set up our development environment and built a basic chessboard using React, react-chessboard, and chess.js. This setup allowed us to create a fully functional chessboard with move validation according to chess rules, providing a strong foundation for building interactive chess features.<\/li>\n\n\n\n<li><strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf\">Part Two: Stockfish Integration<\/a><\/strong>\u00a0\u2013 We integrated Stockfish, a powerful open-source chess engine, enabling our app to go beyond basic move validation. With Stockfish, we added functionality to calculate the best moves and provide position evaluations, making the chessboard a tool that could play against the user and analyze moves for tactical insights.<\/li>\n\n\n\n<li><strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-three-deploying-your-application\/J3GdsKZP\">Part Three: Deploying Your Application<\/a><\/strong>\u00a0\u2013 We explored how to deploy our application using GitHub Pages, providing a free and accessible way to make our chess app available online. This section included setting up Git, creating a GitHub repository, and configuring deployment scripts, ensuring that all resource paths and assets load correctly in production.<\/li>\n<\/ul>\n\n\n\n<p>In this fourth part, we\u2019ll explore how to customize our chessboard\u2014adding custom pieces, custom square colour, square highlighting, and coloured arrows\u2014all building on the foundations from our first two posts.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Note: This blog is a continuation of part 1 and 2, so if you have not completed them, please do so and come back.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#adding-custom-pieces\"><\/a>Adding Custom Pieces<\/h2>\n\n\n\n<p>Customizing chess pieces is a great way to add a unique look to your application. In this section, we\u2019ll walk through setting up custom piece images, allowing you to personalize the visual style of your chessboard.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-1-set-up-the-pieces-folder\"><\/a>Step 1: Set Up the Pieces Folder<\/h4>\n\n\n\n<p>To get started, create a new folder in your project\u2019s public directory to store your custom piece images. This folder will be where we add our custom pieces so they can be easily accessed by the chessboard component.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public\/img\/pieces<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-2-download-the-minerva-piece-set\"><\/a>Step 2: Download the Minerva Piece Set<\/h4>\n\n\n\n<p>For this guide, we\u2019ll use the Minerva Piece set\u2014a custom-designed set that I created for another project. You can download the Minerva pieces from the following URL:&nbsp;<a href=\"https:\/\/github.com\/HollowLeaf1981\/ChessPieces\/tree\/main\/Minerva\">Minerva Piece Set on GitHub<\/a>.<br>Once downloaded, copy the images into the&nbsp;<code>public\/img\/pieces<\/code>&nbsp;folder you just created. Each file should be named according to the standard piece notation (e.g.,&nbsp;<code>wK.png<\/code>&nbsp;for the white king,&nbsp;<code>bQ.png<\/code>&nbsp;for the black queen) to ensure the chessboard component can correctly recognize and render each piece.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note<\/strong>: If you\u2019re interested in exploring more chess piece styles,&nbsp;<a href=\"https:\/\/github.com\/lichess-org\/lila\/tree\/master\/public\/piece\">Lichess.org offers a repository<\/a>&nbsp;of various piece designs. Feel free to explore and try different pieces to find a style that suits your application.<\/p>\n<\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-3-define-custom-pieces-logic\"><\/a>Step 3: Define Custom Pieces Logic<\/h4>\n\n\n\n<p>Now that the images are in place, we\u2019ll define a&nbsp;<code>customPieces<\/code>&nbsp;variable that maps each piece to its respective image. Each piece key should correspond to a unique component displaying the correct image with the appropriate size. Using the&nbsp;<code>squareWidth<\/code>&nbsp;property ensures each piece will fit perfectly within its square.<br>Here\u2019s how to set up the&nbsp;<code>customPieces<\/code>&nbsp;variable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Define the custom pieces logic\nconst customPieces = {\n  wP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Pawn\"\n    \/>\n  ),\n  wN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Knight\"\n    \/>\n  ),\n  wB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Bishop\"\n    \/>\n  ),\n  wR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Rook\"\n    \/>\n  ),\n  wQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Queen\"\n    \/>\n  ),\n  wK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White King\"\n    \/>\n  ),\n  bP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Pawn\"\n    \/>\n  ),\n  bN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Knight\"\n    \/>\n  ),\n  bB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Bishop\"\n    \/>\n  ),\n  bR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Rook\"\n    \/>\n  ),\n  bQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Queen\"\n    \/>\n  ),\n  bK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black King\"\n    \/>\n  ),\n};<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Pro Tip<\/strong>: You can take customization further by implementing multiple piece sets and allowing users to switch between them dynamically. For example, create additional folders within the&nbsp;<code>pieces<\/code>&nbsp;directory for each piece set, then add a dropdown to select between these sets. I implemented this approach in&nbsp;<em>Chessboard Magic<\/em>, making it easy for users to change piece styles on the fly.<\/p>\n<\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-4-integrate-custom-pieces-into-the-chessboard\"><\/a>Step 4: Integrate Custom Pieces into the Chessboard<\/h4>\n\n\n\n<p>Finally, use the&nbsp;<code>customPieces<\/code>&nbsp;variable within the&nbsp;<code>Chessboard<\/code>&nbsp;component to apply these custom pieces:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;Chessboard\n  position={game.fen()}\n  onPieceDrop={onDrop}\n  boardWidth={500}\n  customPieces={customPieces}\n\/><\/code><\/pre>\n\n\n\n<p>With this setup, your chessboard will display the custom Minerva pieces, adding a unique, personal touch to your application. This approach also makes it easy to adjust the pieces in the future\u2014simply update the&nbsp;<code>customPieces<\/code>&nbsp;variable or replace the images in your folder.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#full-code\"><\/a>Full Code<\/h4>\n\n\n\n<p>Here is the full code for integrating custom pieces, maintaining the Stockfish functionality and board interactions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React, { useState, useEffect } from \"react\"; \/\/ Import necessary React functions\nimport { Chessboard } from \"react-chessboard\"; \/\/ Import the chessboard component from react-chessboard\nimport { Chess } from \"chess.js\"; \/\/ Import the chess.js library for game logic\n\n\/\/ Function to extract the best move and evaluation from Stockfish's output message\nconst getEvaluation = (message, turn) => {\n  let result = { bestMove: \"\", evaluation: \"\" }; \/\/ Initialize result with empty values\n\n  \/\/ If the message contains \"bestmove\", extract the best move\n  if (message.startsWith(\"bestmove\")) {\n    result.bestMove = message.split(\" \")&#91;1]; \/\/ The best move is the second word in the message\n  }\n\n  \/\/ Check for \"info score\" in the message to extract the evaluation score\n  if (message.includes(\"info\") &amp;&amp; message.includes(\"score\")) {\n    const scoreParts = message.split(\" \"); \/\/ Split message into words\n    const scoreIndex = scoreParts.indexOf(\"score\") + 2; \/\/ \"cp\" or \"mate\" is two words after \"score\"\n\n    \/\/ If the score type is \"cp\" (centipawn), convert it to a pawn value\n    if (scoreParts&#91;scoreIndex - 1] === \"cp\") {\n      let score = parseInt(scoreParts&#91;scoreIndex], 10); \/\/ Parse the score value\n      if (turn !== \"b\") {\n        score = -score; \/\/ Invert the score if it's White's turn to match convention\n      }\n      result.evaluation = score \/ 100; \/\/ Convert centipawns to pawns (100 centipawns = 1 pawn)\n    } else if (scoreParts&#91;scoreIndex - 1] === \"mate\") {\n      \/\/ If the score type is \"mate\", indicate how many moves until mate\n      const mateIn = parseInt(scoreParts&#91;scoreIndex], 10);\n      result.evaluation = `Mate in ${Math.abs(mateIn)}`; \/\/ Absolute value for positive mate distance\n    }\n  }\n\n  return result; \/\/ Return the result containing bestMove and evaluation\n};\n\n\/\/ Define custom pieces with each piece pointing to its image\nconst customPieces = {\n  wP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Pawn\"\n    \/>\n  ),\n  wN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Knight\"\n    \/>\n  ),\n  wB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Bishop\"\n    \/>\n  ),\n  wR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Rook\"\n    \/>\n  ),\n  wQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Queen\"\n    \/>\n  ),\n  wK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White King\"\n    \/>\n  ),\n  bP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Pawn\"\n    \/>\n  ),\n  bN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Knight\"\n    \/>\n  ),\n  bB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Bishop\"\n    \/>\n  ),\n  bR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Rook\"\n    \/>\n  ),\n  bQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Queen\"\n    \/>\n  ),\n  bK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black King\"\n    \/>\n  ),\n};\n\nconst App = () => {\n  \/\/ State for tracking game state, Stockfish worker, best move, and evaluation score\n  const &#91;game, setGame] = useState(new Chess());\n  const &#91;stockfish, setStockfish] = useState(null);\n  const &#91;bestMove, setBestMove] = useState(\"\");\n  const &#91;evaluation, setEvaluation] = useState(\"\");\n\n  useEffect(() => {\n    \/\/ Initialize Stockfish as a Web Worker when the component mounts\n    const stockfishWorker = new Worker(`${process.env.PUBLIC_URL}\/js\/stockfish-16.1-lite-single.js`);\n\n    setStockfish(stockfishWorker);\n\n    \/\/ Clean up the worker when the component unmounts\n    return () => {\n      stockfishWorker.terminate();\n    };\n  }, &#91;]);\n\n  \/\/ Handle piece drop (move) on the chessboard\n  const onDrop = (sourceSquare, targetSquare) => {\n    const gameCopy = new Chess(game.fen()); \/\/ Clone the current game state\n\n    try {\n      const move = gameCopy.move({\n        from: sourceSquare,\n        to: targetSquare,\n        promotion: \"q\", \/\/ Auto-promote to a queen\n      });\n\n      \/\/ If the move is invalid, return false to prevent it\n      if (move === null) {\n        return false;\n      }\n\n      setGame(gameCopy); \/\/ Update the game state with the new move\n\n      \/\/ Send the updated position to Stockfish to get the best move and evaluation\n      if (stockfish) {\n        stockfish.postMessage(`position fen ${gameCopy.fen()}`); \/\/ Set the position in Stockfish\n        stockfish.postMessage(\"go depth 15\"); \/\/ Ask Stockfish to analyze to depth 15\n\n        \/\/ Listen for messages from Stockfish and update best move and evaluation\n        stockfish.onmessage = (event) => {\n          const { bestMove, evaluation } = getEvaluation(event.data, game.turn());\n          if (bestMove) setBestMove(bestMove); \/\/ Update the best move\n          if (evaluation) setEvaluation(evaluation); \/\/ Update the evaluation score\n        };\n      }\n\n      return true; \/\/ Return true if the move was successful\n    } catch (error) {\n      console.error(error.message); \/\/ Log error if an invalid move\n      return false;\n    }\n  };\n\n  return (\n    &lt;div>\n      &lt;h1>Chess Game with Stockfish&lt;\/h1>\n      {\/* Chessboard component with custom pieces and onDrop handler *\/}\n      &lt;Chessboard\n        position={game.fen()} \/\/ Current position from the game state\n        onPieceDrop={onDrop} \/\/ Function to handle piece drops\n        boardWidth={500} \/\/ Width of the chessboard in pixels\n        customPieces={customPieces} \/\/ Pass custom pieces variable\n      \/>\n      {\/* Display the best move and evaluation score *\/}\n      &lt;div>\n        &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n        &lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3>\n      &lt;\/div>\n    &lt;\/div>\n  );\n};\n\nexport default App; \/\/ Export the App component as the default export<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#explanation\"><\/a>Explanation<\/h4>\n\n\n\n<p>This full code example combines:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Custom Pieces<\/strong>: Using the\u00a0<code>customPieces<\/code>\u00a0variable, we display each custom image, sized to fit within each square.<\/li>\n\n\n\n<li><strong>Stockfish Integration<\/strong>: Moves are sent to Stockfish, which responds with the best move and evaluation, updating dynamically after each valid move.<\/li>\n\n\n\n<li><strong>Chessboard Interaction<\/strong>: Users can drag and drop pieces on the chessboard, with the app validating moves and applying custom piece styles.<\/li>\n<\/ul>\n\n\n\n<p>You should now see the following:<img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=webp&amp;h=0&amp;op=resize&amp;path=hollowleaf:ublogBody:xwRJxYsXgE77:FJRSzLV8.png&amp;w=800&amp;sig=bacc81c818b1ebeb98f1ff6a65ff393498abf481\" alt=\"image.png\"><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Yes, my graphic design skills are not the best.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#adding-custom-square-colour\"><\/a>Adding Custom Square Colour<\/h2>\n\n\n\n<p>Customizing the square colors on a chessboard can create a unique look and make your application stand out. In this section, we\u2019ll explore how to create a &#8220;White Stripe Theme&#8221; using CSS background colors and patterns. This guide will walk you through the steps, explaining each detail along the way.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-1-define-our-theme-styles\"><\/a>Step 1: Define Our Theme Styles<\/h4>\n\n\n\n<p>To achieve a striped effect on each square, we\u2019ll use a combination of background colors and patterns. We define these styles as JavaScript objects, which are later passed to our chessboard component. These styles control both the base color of each square (light or dark) and the overlay pattern.<br>Here\u2019s how to define the styles for our theme:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Define the White Stripe Theme with light and dark square patterns\nconst lightSquareStyle = {\n  backgroundColor: \"#FFFFFF\", \/\/ Base color for light squares\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Diagonal stripe pattern for light squares\n};\n\nconst darkSquareStyle = {\n  backgroundColor: \"#CCCCCC\", \/\/ Base color for dark squares\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Diagonal stripe pattern for dark squares\n};<\/code><\/pre>\n\n\n\n<p><strong>Explanation of CSS Properties<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>backgroundColor<\/code><\/strong>: This sets the base color for each square type (light or dark). Here, we\u2019re using a light grey for dark squares (<code>#CCCCCC<\/code>) and white (<code>#FFFFFF<\/code>) for light squares.<\/li>\n\n\n\n<li><strong><code>backgroundImage<\/code><\/strong>: This uses\u00a0<code>repeating-linear-gradient<\/code>\u00a0to create a diagonal striped effect on each square.\n<ul class=\"wp-block-list\">\n<li><strong><code>repeating-linear-gradient<\/code><\/strong>\u00a0allows us to create repeating patterns with linear gradients.<\/li>\n\n\n\n<li><strong>Parameters of the Gradient<\/strong>:\n<ul class=\"wp-block-list\">\n<li><code>-45deg<\/code>: This sets the angle of the stripes to 45 degrees for a diagonal effect.<\/li>\n\n\n\n<li><code>rgba(0, 0, 0, 0.1)<\/code>: This sets a very light, semi-transparent black color to use for the stripes.<\/li>\n\n\n\n<li>The subsequent numbers define the start and end of each line and gap, making a pattern where every 4px segment has a 2px line followed by a 2px transparent gap.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Experimenting with these parameters can yield different patterns, so feel free to adjust the colors and spacing for other effects!<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-2-apply-the-theme-to-the-chessboard\"><\/a>Step 2: Apply the Theme to the Chessboard<\/h4>\n\n\n\n<p>Once we have our styles defined, we\u2019ll pass them to the&nbsp;<code>Chessboard<\/code>&nbsp;component. The&nbsp;<code>Chessboard<\/code>&nbsp;component supports&nbsp;<code>customLightSquareStyle<\/code>&nbsp;and&nbsp;<code>customDarkSquareStyle<\/code>&nbsp;props, which we use to set the custom styles for light and dark squares, respectively.<br>Here\u2019s how to apply our theme to the&nbsp;<code>Chessboard<\/code>&nbsp;component:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;Chessboard\n  position={game.fen()}\n  onPieceDrop={onDrop}\n  boardWidth={500}\n  customPieces={customPieces}\n  customLightSquareStyle={lightSquareStyle} \/\/ Apply custom light square style\n  customDarkSquareStyle={darkSquareStyle}   \/\/ Apply custom dark square style\n\/><\/code><\/pre>\n\n\n\n<p>This code will render the chessboard with our Theme, giving each square a subtle striped pattern that enhances its appearance.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#full-code-1\"><\/a>Full Code<\/h4>\n\n\n\n<p>Below is the complete code for integrating our theme with the chessboard:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React, { useState, useEffect } from \"react\"; \/\/ Import React, useState, and useEffect hooks\nimport { Chessboard } from \"react-chessboard\"; \/\/ Import the Chessboard component\nimport { Chess } from \"chess.js\"; \/\/ Import the Chess library for game logic\n\n\/\/ Function to parse Stockfish's output and extract the best move and evaluation\nconst getEvaluation = (message, turn) => {\n  let result = { bestMove: \"\", evaluation: \"\" }; \/\/ Initialize result with default values\n\n  \/\/ If the message starts with \"bestmove\", extract the best move from the message\n  if (message.startsWith(\"bestmove\")) {\n    result.bestMove = message.split(\" \")&#91;1]; \/\/ The best move is the second word in the message\n  }\n\n  \/\/ Check for \"info score\" in the message to extract evaluation score\n  if (message.includes(\"info\") &amp;&amp; message.includes(\"score\")) {\n    const scoreParts = message.split(\" \"); \/\/ Split message into words\n    const scoreIndex = scoreParts.indexOf(\"score\") + 2; \/\/ \"cp\" or \"mate\" is two words after \"score\"\n\n    \/\/ If the score type is \"cp\" (centipawn), interpret it as a material advantage in pawns\n    if (scoreParts&#91;scoreIndex - 1] === \"cp\") {\n      let score = parseInt(scoreParts&#91;scoreIndex], 10); \/\/ Parse the score value\n      if (turn !== \"b\") {\n        score = -score; \/\/ Invert the score if it's White's turn\n      }\n      result.evaluation = score \/ 100; \/\/ Convert centipawns to pawns\n    } else if (scoreParts&#91;scoreIndex - 1] === \"mate\") {\n      \/\/ If the score type is \"mate\", indicate moves until checkmate\n      const mateIn = parseInt(scoreParts&#91;scoreIndex], 10);\n      result.evaluation = `Mate in ${Math.abs(mateIn)}`;\n    }\n  }\n\n  return result; \/\/ Return the best move and evaluation\n};\n\n\/\/ Define custom pieces mapping for each piece to its corresponding image\nconst customPieces = {\n  wP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Pawn\"\n    \/>\n  ),\n  wN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Knight\"\n    \/>\n  ),\n  wB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Bishop\"\n    \/>\n  ),\n  wR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Rook\"\n    \/>\n  ),\n  wQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Queen\"\n    \/>\n  ),\n  wK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White King\"\n    \/>\n  ),\n  bP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Pawn\"\n    \/>\n  ),\n  bN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Knight\"\n    \/>\n  ),\n  bB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Bishop\"\n    \/>\n  ),\n  bR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Rook\"\n    \/>\n  ),\n  bQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Queen\"\n    \/>\n  ),\n  bK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black King\"\n    \/>\n  ),\n};\n\n\/\/ Define custom square styles for the \"White Stripe Theme\"\nconst lightSquareStyle = {\n  backgroundColor: \"#FFFFFF\", \/\/ Light square base color\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Light square stripe pattern\n};\n\nconst darkSquareStyle = {\n  backgroundColor: \"#CCCCCC\", \/\/ Dark square base color\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Dark square stripe pattern\n};\n\nconst App = () => {\n  \/\/ State variables for chess game logic, Stockfish worker, best move, and evaluation\n  const &#91;game, setGame] = useState(new Chess()); \/\/ Chess game instance\n  const &#91;stockfish, setStockfish] = useState(null); \/\/ Stockfish Web Worker instance\n  const &#91;bestMove, setBestMove] = useState(\"\"); \/\/ Best move suggested by Stockfish\n  const &#91;evaluation, setEvaluation] = useState(\"\"); \/\/ Evaluation of the position by Stockfish\n\n  \/\/ useEffect hook to initialize the Stockfish Web Worker\n  useEffect(() => {\n    const stockfishWorker = new Worker(`${process.env.PUBLIC_URL}\/js\/stockfish-16.1-lite-single.js`);\n\n    setStockfish(stockfishWorker);\n\n    \/\/ Terminate the worker when the component unmounts\n    return () => {\n      stockfishWorker.terminate();\n    };\n  }, &#91;]);\n\n  \/\/ Function to handle piece drop events on the chessboard\n  const onDrop = (sourceSquare, targetSquare) => {\n    const gameCopy = new Chess(game.fen()); \/\/ Clone the current game state\n\n    try {\n      const move = gameCopy.move({\n        from: sourceSquare,\n        to: targetSquare,\n        promotion: \"q\", \/\/ Always promote to a queen for simplicity\n      });\n\n      \/\/ If the move is invalid, return false to prevent it\n      if (move === null) {\n        return false;\n      }\n\n      setGame(gameCopy); \/\/ Update the game state with the new move\n\n      \/\/ Send the updated position to Stockfish for analysis\n      if (stockfish) {\n        stockfish.postMessage(`position fen ${gameCopy.fen()}`); \/\/ Set the position in Stockfish\n        stockfish.postMessage(\"go depth 15\"); \/\/ Ask Stockfish to analyze to depth 15\n\n        \/\/ Listen for messages from Stockfish and update best move and evaluation\n        stockfish.onmessage = (event) => {\n          const { bestMove, evaluation } = getEvaluation(event.data, game.turn());\n          if (bestMove) setBestMove(bestMove); \/\/ Update the best move\n          if (evaluation) setEvaluation(evaluation); \/\/ Update the evaluation score\n        };\n      }\n\n      return true; \/\/ Return true if the move was valid\n    } catch (error) {\n      console.error(\"Invalid move:\", error.message); \/\/ Log error if an invalid move\n      return false;\n    }\n  };\n\n  return (\n    &lt;div>\n      &lt;h1>Chess Game with Stockfish&lt;\/h1>\n      {\/* Chessboard component with custom pieces and square styles *\/}\n      &lt;Chessboard\n        position={game.fen()} \/\/ Current position from the game state\n        onPieceDrop={onDrop} \/\/ Function to handle piece drops\n        boardWidth={500} \/\/ Width of the chessboard in pixels\n        customPieces={customPieces} \/\/ Custom pieces mapping\n        customLightSquareStyle={lightSquareStyle} \/\/ Apply custom light square style\n        customDarkSquareStyle={darkSquareStyle}   \/\/ Apply custom dark square style\n      \/>\n      {\/* Display the best move and evaluation score *\/}\n      &lt;div>\n        &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n        &lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3>\n      &lt;\/div>\n    &lt;\/div>\n  );\n};\n\nexport default App; \/\/ Export the App component as the default export<\/code><\/pre>\n\n\n\n<p>You should now see the following:<br><img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=webp&amp;h=0&amp;op=resize&amp;path=hollowleaf:ublogBody:6uXn8NUBgV9Y:1gjKExHP.png&amp;w=800&amp;sig=f5d0e00075da811c7cdc9ed4ff5138d9e248f43e\" alt=\"image.png\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#adding-custom-square-highlighting\"><\/a>Adding Custom Square Highlighting<\/h2>\n\n\n\n<p>Adding square highlighting for the last move provides visual feedback and helps users track recent moves on the board. In this section, we\u2019ll implement a feature to highlight the&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares of the last moved piece using different colors. This feature will be stored in&nbsp;<code>useState<\/code>&nbsp;so we can dynamically update the highlights after each move.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-1-add-state-for-tracking-the-last-move\"><\/a>Step 1: Add State for Tracking the Last Move<\/h4>\n\n\n\n<p>In React,&nbsp;<code>useState<\/code>&nbsp;is a hook that allows us to create and manage state within functional components. Here, we\u2019ll use&nbsp;<code>useState<\/code>&nbsp;to store the coordinates of the&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares of the last move. When a move is made, these states will be updated with the new&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares.<br>Add two new&nbsp;<code>useState<\/code>&nbsp;variables to manage the last move&#8217;s&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ State variables for tracking the last move's from and to squares\nconst &#91;fromSquare, setFromSquare] = useState(null); \/\/ Holds the starting square of the last move\nconst &#91;toSquare, setToSquare] = useState(null);     \/\/ Holds the destination square of the last move<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>fromSquare<\/code>: Tracks the starting square of the last moved piece.<\/li>\n\n\n\n<li><code>toSquare<\/code>: Tracks the destination square of the last moved piece.<\/li>\n<\/ul>\n\n\n\n<p>Each time a move is made, we\u2019ll update these states to reflect the squares involved.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-2-update-fromsquare-and-tosquare-in-the-ondrop-function\"><\/a>Step 2: Update&nbsp;<code>fromSquare<\/code>&nbsp;and&nbsp;<code>toSquare<\/code>&nbsp;in the&nbsp;<code>onDrop<\/code>&nbsp;Function<\/h4>\n\n\n\n<p>The&nbsp;<code>onDrop<\/code>&nbsp;function is triggered every time a piece is moved on the board. It takes two parameters:&nbsp;<code>sourceSquare<\/code>&nbsp;(the square the piece is moved from) and&nbsp;<code>targetSquare<\/code>&nbsp;(the square the piece is moved to).<br>After validating the move, we\u2019ll use&nbsp;<code>setFromSquare<\/code>&nbsp;and&nbsp;<code>setToSquare<\/code>&nbsp;to update these values.<br>Add this code to the&nbsp;<code>onDrop<\/code>&nbsp;function, after a move is confirmed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const onDrop = (sourceSquare, targetSquare) => {\n  const gameCopy = new Chess(game.fen()); \/\/ Clone the current game state\n\n  try {\n    const move = gameCopy.move({\n      from: sourceSquare,\n      to: targetSquare,\n      promotion: \"q\", \/\/ Always promote to a queen for simplicity\n    });\n\n    if (move === null) {\n      return false; \/\/ If the move is invalid, return false to prevent it\n    }\n\n    setGame(gameCopy); \/\/ Update the game state with the new move\n\n    \/\/ Update last move states for highlighting\n    setFromSquare(sourceSquare); \/\/ Update the starting square of the last move\n    setToSquare(targetSquare);   \/\/ Update the destination square of the last move\n\n    \/\/ Send the updated position to Stockfish for analysis\n    if (stockfish) {\n      stockfish.postMessage(`position fen ${gameCopy.fen()}`);\n      stockfish.postMessage(\"go depth 15\");\n\n      stockfish.onmessage = (event) => {\n        const { bestMove, evaluation } = getEvaluation(event.data, game.turn());\n        if (bestMove) setBestMove(bestMove);\n        if (evaluation) setEvaluation(evaluation);\n      };\n    }\n\n    return true;\n  } catch (error) {\n    console.error(error.message); \/\/ Log error if an invalid move\n    return false;\n  }\n};<\/code><\/pre>\n\n\n\n<p>Here\u2019s what each part does:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Move Validation<\/strong>: If the move is invalid, we return\u00a0<code>false<\/code>\u00a0and exit the function.<\/li>\n\n\n\n<li><strong>Updating the Game State<\/strong>: After confirming a valid move, we update the game state.<\/li>\n\n\n\n<li><strong>Updating Highlight States<\/strong>: We update\u00a0<code>fromSquare<\/code>\u00a0and\u00a0<code>toSquare<\/code>\u00a0using\u00a0<code>setFromSquare<\/code>\u00a0and\u00a0<code>setToSquare<\/code>\u00a0to store the coordinates of the last move.<\/li>\n\n\n\n<li><strong>Stockfish Analysis<\/strong>: If Stockfish is running, we send the new position to Stockfish for analysis.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-3-define-custom-styles-for-the-highlighted-squares\"><\/a>Step 3: Define Custom Styles for the Highlighted Squares<\/h4>\n\n\n\n<p>Now, let\u2019s define the colors for the&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares. For example, we can set a light blue for the&nbsp;<code>from<\/code>&nbsp;square and a light green for the&nbsp;<code>to<\/code>&nbsp;square.<br>We\u2019ll create a helper function&nbsp;<code>getSquareStyles<\/code>&nbsp;to dynamically return these styles based on&nbsp;<code>fromSquare<\/code>&nbsp;and&nbsp;<code>toSquare<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const getSquareStyles = () => {\n  const styles = {}; \/\/ Initialize an empty object for square styles\n  if (fromSquare) {\n    styles&#91;fromSquare] = { backgroundColor: \"rgba(173, 216, 230, 0.8)\" }; \/\/ Light blue for the from-square\n  }\n  if (toSquare) {\n    styles&#91;toSquare] = { backgroundColor: \"rgba(144, 238, 144, 0.8)\" }; \/\/ Light green for the to-square\n  }\n  return styles; \/\/ Return the styles object\n};<\/code><\/pre>\n\n\n\n<p><strong>Explanation<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>fromSquare<\/code>\u00a0and\u00a0<code>toSquare<\/code><\/strong>: If these states contain values, we apply a color style to the respective squares.<\/li>\n\n\n\n<li><strong>Returning the styles<\/strong>: This function generates an object where each key is a square (e.g.,\u00a0<code>\"e2\"<\/code>) and the value is the CSS style to apply to that square.<\/li>\n<\/ul>\n\n\n\n<p><strong>Customizing the Styles<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You can modify the colors or other CSS properties to create unique square highlights. Here are some ideas:\n<ul class=\"wp-block-list\">\n<li><strong>Different Colors<\/strong>: Use any color by changing the\u00a0<code>backgroundColor<\/code>\u00a0property.<\/li>\n\n\n\n<li><strong>Border Effects<\/strong>: Add a border to the squares, such as\u00a0<code>{ border: \"2px solid yellow\" }<\/code>.<\/li>\n\n\n\n<li><strong>Opacity Adjustments<\/strong>: Control transparency with\u00a0<code>rgba<\/code>\u00a0values to blend or darken colors as desired.<\/li>\n\n\n\n<li><strong>Additional Effects<\/strong>: CSS properties like\u00a0<code>boxShadow<\/code>\u00a0can add depth (e.g.,\u00a0<code>{ boxShadow: \"0px 0px 10px rgba(0,0,0,0.5)\" }<\/code>).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>By customizing&nbsp;<code>getSquareStyles<\/code>, you can fully control the appearance of the highlighted squares, making it easier to track moves in a style that suits your application\u2019s aesthetic.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-4-pass-the-square-styles-to-the-chessboard-component\"><\/a>Step 4: Pass the Square Styles to the Chessboard Component<\/h4>\n\n\n\n<p>Now, we\u2019ll use the&nbsp;<code>customSquareStyles<\/code>&nbsp;prop on the&nbsp;<code>Chessboard<\/code>&nbsp;component to apply our highlights. This prop takes an object of styles, so we\u2019ll pass the result of&nbsp;<code>getSquareStyles()<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;Chessboard\n  position={game.fen()}\n  onPieceDrop={onDrop}\n  boardWidth={500}\n  customPieces={customPieces}\n  customLightSquareStyle={lightSquareStyle}\n  customDarkSquareStyle={darkSquareStyle}\n  customSquareStyles={getSquareStyles()} \/\/ Apply last move highlight styles\n\/><\/code><\/pre>\n\n\n\n<p>This setup will dynamically highlight the&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares of the last move with custom colors, making it easier for users to track recent moves.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#full-code-2\"><\/a>Full Code<\/h4>\n\n\n\n<p>Below is the complete code with the new custom square highlighting feature added.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React, { useState, useEffect } from \"react\"; \/\/ Import React and React hooks\nimport { Chessboard } from \"react-chessboard\"; \/\/ Import the Chessboard component\nimport { Chess } from \"chess.js\"; \/\/ Import the Chess library for game logic\n\n\/\/ Function to parse Stockfish's output and extract the best move and evaluation\nconst getEvaluation = (message, turn) => {\n  let result = { bestMove: \"\", evaluation: \"\" }; \/\/ Initialize result with default values\n\n  \/\/ If the message starts with \"bestmove\", extract the best move from the message\n  if (message.startsWith(\"bestmove\")) {\n    result.bestMove = message.split(\" \")&#91;1]; \/\/ The best move is the second word in the message\n  }\n\n  \/\/ Check for \"info score\" in the message to extract evaluation score\n  if (message.includes(\"info\") &amp;&amp; message.includes(\"score\")) {\n    const scoreParts = message.split(\" \"); \/\/ Split message into words\n    const scoreIndex = scoreParts.indexOf(\"score\") + 2; \/\/ \"cp\" or \"mate\" is two words after \"score\"\n\n    \/\/ If the score type is \"cp\" (centipawn), interpret it as a material advantage in pawns\n    if (scoreParts&#91;scoreIndex - 1] === \"cp\") {\n      let score = parseInt(scoreParts&#91;scoreIndex], 10); \/\/ Parse the score value\n      if (turn !== \"b\") {\n        score = -score; \/\/ Invert the score if it's White's turn\n      }\n      result.evaluation = score \/ 100; \/\/ Convert centipawns to pawns\n    } else if (scoreParts&#91;scoreIndex - 1] === \"mate\") {\n      \/\/ If the score type is \"mate\", indicate moves until checkmate\n      const mateIn = parseInt(scoreParts&#91;scoreIndex], 10);\n      result.evaluation = `Mate in ${Math.abs(mateIn)}`;\n    }\n  }\n\n  return result; \/\/ Return the best move and evaluation\n};\n\n\/\/ Define custom pieces mapping for each piece to its corresponding image\nconst customPieces = {\n  wP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Pawn\"\n    \/>\n  ),\n  wN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Knight\"\n    \/>\n  ),\n  wB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Bishop\"\n    \/>\n  ),\n  wR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Rook\"\n    \/>\n  ),\n  wQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Queen\"\n    \/>\n  ),\n  wK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White King\"\n    \/>\n  ),\n  bP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Pawn\"\n    \/>\n  ),\n  bN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Knight\"\n    \/>\n  ),\n  bB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Bishop\"\n    \/>\n  ),\n  bR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Rook\"\n    \/>\n  ),\n  bQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Queen\"\n    \/>\n  ),\n  bK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black King\"\n    \/>\n  ),\n};\n\n\/\/ Define custom square styles for the \"White Stripe Theme\"\nconst lightSquareStyle = {\n  backgroundColor: \"#FFFFFF\", \/\/ Light square base color\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Light square stripe pattern\n};\n\nconst darkSquareStyle = {\n  backgroundColor: \"#CCCCCC\", \/\/ Dark square base color\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Dark square stripe pattern\n};\n\nconst App = () => {\n  \/\/ State variables for chess game logic, Stockfish worker, best move, and evaluation\n  const &#91;game, setGame] = useState(new Chess()); \/\/ Chess game instance\n  const &#91;stockfish, setStockfish] = useState(null); \/\/ Stockfish Web Worker instance\n  const &#91;bestMove, setBestMove] = useState(\"\"); \/\/ Best move suggested by Stockfish\n  const &#91;evaluation, setEvaluation] = useState(\"\"); \/\/ Evaluation of the position by Stockfish\n\n  \/\/ State variables for tracking the last move's from and to squares\n  const &#91;fromSquare, setFromSquare] = useState(null); \/\/ Holds the starting square of the last move\n  const &#91;toSquare, setToSquare] = useState(null);     \/\/ Holds the destination square of the last move\n\n  \/\/ useEffect hook to initialize the Stockfish Web Worker\n  useEffect(() => {\n    const stockfishWorker = new Worker(`${process.env.PUBLIC_URL}\/js\/stockfish-16.1-lite-single.js`);\n\n    setStockfish(stockfishWorker);\n\n    \/\/ Terminate the worker when the component unmounts\n    return () => {\n      stockfishWorker.terminate();\n    };\n  }, &#91;]);\n\n  \/\/ Function to handle piece drop events on the chessboard\n  const onDrop = (sourceSquare, targetSquare) => {\n    const gameCopy = new Chess(game.fen()); \/\/ Clone the current game state\n\n    try {\n      const move = gameCopy.move({\n        from: sourceSquare,\n        to: targetSquare,\n        promotion: \"q\", \/\/ Always promote to a queen for simplicity\n      });\n\n      \/\/ If the move is invalid, return false to prevent it\n      if (move === null) {\n        return false;\n      }\n\n      setGame(gameCopy); \/\/ Update the game state with the new move\n\n      \/\/ Update last move states for highlighting\n      setFromSquare(sourceSquare); \/\/ Update the starting square of the last move\n      setToSquare(targetSquare);   \/\/ Update the destination square of the last move\n\n      \/\/ Send the updated position to Stockfish for analysis\n      if (stockfish) {\n        stockfish.postMessage(`position fen ${gameCopy.fen()}`); \/\/ Set the position in Stockfish\n        stockfish.postMessage(\"go depth 15\"); \/\/ Ask Stockfish to analyze to depth 15\n\n        \/\/ Listen for messages from Stockfish and update best move and evaluation\n        stockfish.onmessage = (event) => {\n          const { bestMove, evaluation } = getEvaluation(event.data, game.turn());\n          if (bestMove) setBestMove(bestMove); \/\/ Update the best move\n          if (evaluation) setEvaluation(evaluation); \/\/ Update the evaluation score\n        };\n      }\n\n      return true; \/\/ Return true if the move was valid\n    } catch (error) {\n      console.error(error.message); \/\/ Log error if an invalid move\n      return false;\n    }\n  };\n\n  \/\/ Function to define custom styles for the last move's from and to squares\n  const getSquareStyles = () => {\n    const styles = {}; \/\/ Initialize an empty object for square styles\n    if (fromSquare) {\n      styles&#91;fromSquare] = { backgroundColor: \"rgba(173, 216, 230, 0.8)\" }; \/\/ Light blue for the from-square\n    }\n    if (toSquare) {\n      styles&#91;toSquare] = { backgroundColor: \"rgba(144, 238, 144, 0.8)\" }; \/\/ Light green for the to-square\n    }\n    return styles; \/\/ Return the styles object\n  };\n\n  return (\n    &lt;div>\n      &lt;h1>Chess Game with Stockfish&lt;\/h1>\n      {\/* Chessboard component with custom pieces and square styles *\/}\n      &lt;Chessboard\n        position={game.fen()} \/\/ Current position from the game state\n        onPieceDrop={onDrop} \/\/ Function to handle piece drops\n        boardWidth={500} \/\/ Width of the chessboard in pixels\n        customPieces={customPieces} \/\/ Custom pieces mapping\n        customLightSquareStyle={lightSquareStyle} \/\/ Apply custom light square style\n        customDarkSquareStyle={darkSquareStyle} \/\/ Apply custom dark square style\n        customSquareStyles={getSquareStyles()} \/\/ Apply last move highlight styles\n      \/>\n      {\/* Display the best move and evaluation score *\/}\n      &lt;div>\n        &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n        &lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3>\n      &lt;\/div>\n    &lt;\/div>\n  );\n};\n\nexport default App; \/\/ Export the App component as the default export<\/code><\/pre>\n\n\n\n<p>You should now see the following:<br><img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=webp&amp;h=0&amp;op=resize&amp;path=hollowleaf:ublogBody:jqUC0mgw7Svt:krG0Boxv.png&amp;w=800&amp;sig=7a0781f4ada313cbb090969c8c42dd821e7849ed\" alt=\"image.png\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#adding-coloured-arrows\"><\/a>Adding Coloured Arrows<\/h2>\n\n\n\n<p>Adding an arrow to the chessboard based on the best move suggested by the chess engine can enhance the user experience by visually guiding them through the optimal move. In this section, we\u2019ll walk through how to display an arrow between squares on the board using&nbsp;<code>react-chessboard<\/code>\u2019s&nbsp;<code>customArrows<\/code>&nbsp;and&nbsp;<code>customArrowColor<\/code>&nbsp;properties.<br>The best move returned by Stockfish comes as a string of four characters, where the first two characters represent the starting square (e.g.,&nbsp;<code>\"e2\"<\/code>) and the last two characters represent the ending square (e.g.,&nbsp;<code>\"e4\"<\/code>). We\u2019ll extract these values and use them to create an arrow on the board.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-1-set-up-state-for-the-arrow\"><\/a>Step 1: Set Up State for the Arrow<\/h4>\n\n\n\n<p>To store the coordinates of the arrow, we\u2019ll create a&nbsp;<code>useState<\/code>&nbsp;variable. This variable will be an array containing the starting and ending squares of the best move.<br>Add this to your component:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ State to hold the best move's starting and ending squares for the arrow\nconst &#91;bestMoveArrow, setBestMoveArrow] = useState(&#91;]);<\/code><\/pre>\n\n\n\n<p>Here,&nbsp;<code>bestMoveArrow<\/code>&nbsp;will store the arrow information as an array where each entry represents an arrow with&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-2-update-arrow-state-based-on-best-move\"><\/a>Step 2: Update Arrow State Based on Best Move<\/h4>\n\n\n\n<p>Whenever the best move from Stockfish updates, we\u2019ll extract the&nbsp;<code>from<\/code>&nbsp;and&nbsp;<code>to<\/code>&nbsp;squares from the best move string and use these values to update&nbsp;<code>bestMoveArrow<\/code>.<br>In the function where you handle the best move, update&nbsp;<code>bestMoveArrow<\/code>&nbsp;as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if (bestMove) {\n  \/\/ Extract starting and ending squares from the best move\n  const fromSquare = bestMove.slice(0, 2); \/\/ First two characters\n  const toSquare = bestMove.slice(2, 4);   \/\/ Last two characters\n\n  \/\/ Update the arrow state to draw an arrow for the best move\n  setBestMoveArrow(&#91;&#91;fromSquare, toSquare]]);\n}<\/code><\/pre>\n\n\n\n<p>In this code:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>fromSquare<\/code>\u00a0and\u00a0<code>toSquare<\/code><\/strong>\u00a0are derived from the best move string.<\/li>\n\n\n\n<li><strong><code>setBestMoveArrow<\/code><\/strong>\u00a0sets these values as an arrow on the board, which\u00a0<code>react-chessboard<\/code>\u00a0will render as soon as\u00a0<code>bestMoveArrow<\/code>\u00a0updates.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-3-set-the-arrow-color-with-customarrowcolor\"><\/a>Step 3: Set the Arrow Color with&nbsp;<code>customArrowColor<\/code><\/h4>\n\n\n\n<p>To make the arrow more visually distinct, we can add the&nbsp;<code>customArrowColor<\/code>&nbsp;property in the&nbsp;<code>Chessboard<\/code>&nbsp;component. This property accepts a CSS color value like&nbsp;<code>#FF0000<\/code>&nbsp;or&nbsp;<code>rgba(0, 0, 255, 0.6)<\/code>, which will be applied to all arrows on the board.<br>For example, we\u2019ll define a semi-transparent blue color for our arrow:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const arrowColor = \"rgba(0, 0, 255, 0.6)\"; \/\/ Define custom arrow color<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#step-4-use-customarrows-and-customarrowcolor-in-the-chessboard-component\"><\/a>Step 4: Use&nbsp;<code>customArrows<\/code>&nbsp;and&nbsp;<code>customArrowColor<\/code>&nbsp;in the&nbsp;<code>Chessboard<\/code>&nbsp;Component<\/h4>\n\n\n\n<p>Finally, add&nbsp;<code>customArrows={bestMoveArrow}<\/code>&nbsp;and&nbsp;<code>customArrowColor={arrowColor}<\/code>&nbsp;to the&nbsp;<code>Chessboard<\/code>&nbsp;component to render the arrow with the specified color.<br>Your&nbsp;<code>Chessboard<\/code>&nbsp;component setup should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;Chessboard\n  position={game.fen()} \/\/ Current board position from the game state\n  onPieceDrop={onDrop} \/\/ Function to handle piece drops\n  boardWidth={500} \/\/ Set the board width\n  customPieces={customPieces} \/\/ Custom pieces if you have them\n  customLightSquareStyle={lightSquareStyle} \/\/ Style for light squares\n  customDarkSquareStyle={darkSquareStyle} \/\/ Style for dark squares\n  customArrows={bestMoveArrow} \/\/ Pass the best move arrow to render on the board\n  customArrowColor={arrowColor} \/\/ Set the custom arrow color\n\/><\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#full-code-3\"><\/a>Full Code<\/h4>\n\n\n\n<p>Here&#8217;s the complete implementation of this feature in the context of the full component:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React, { useState, useEffect } from \"react\"; \/\/ Import React and React hooks\nimport { Chessboard } from \"react-chessboard\"; \/\/ Import the Chessboard component\nimport { Chess } from \"chess.js\"; \/\/ Import the Chess library for game logic\n\n\/\/ Function to parse Stockfish's output and extract the best move and evaluation\nconst getEvaluation = (message, turn) => {\n  let result = { bestMove: \"\", evaluation: \"\" }; \/\/ Initialize result with default values\n\n  \/\/ If the message starts with \"bestmove\", extract the best move from the message\n  if (message.startsWith(\"bestmove\")) {\n    result.bestMove = message.split(\" \")&#91;1]; \/\/ The best move is the second word in the message\n  }\n\n  \/\/ Check for \"info score\" in the message to extract evaluation score\n  if (message.includes(\"info\") &amp;&amp; message.includes(\"score\")) {\n    const scoreParts = message.split(\" \"); \/\/ Split message into words\n    const scoreIndex = scoreParts.indexOf(\"score\") + 2; \/\/ \"cp\" or \"mate\" is two words after \"score\"\n\n    \/\/ If the score type is \"cp\" (centipawn), interpret it as a material advantage in pawns\n    if (scoreParts&#91;scoreIndex - 1] === \"cp\") {\n      let score = parseInt(scoreParts&#91;scoreIndex], 10); \/\/ Parse the score value\n      if (turn !== \"b\") {\n        score = -score; \/\/ Invert the score if it's White's turn\n      }\n      result.evaluation = score \/ 100; \/\/ Convert centipawns to pawns\n    } else if (scoreParts&#91;scoreIndex - 1] === \"mate\") {\n      \/\/ If the score type is \"mate\", indicate moves until checkmate\n      const mateIn = parseInt(scoreParts&#91;scoreIndex], 10);\n      result.evaluation = `Mate in ${Math.abs(mateIn)}`;\n    }\n  }\n\n  return result; \/\/ Return the best move and evaluation\n};\n\n\/\/ Define custom pieces mapping for each piece to its corresponding image\nconst customPieces = {\n  \/\/ White pieces with images and styles\n  wP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Pawn\"\n    \/>\n  ),\n  wN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Knight\"\n    \/>\n  ),\n  wB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Bishop\"\n    \/>\n  ),\n  wR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Rook\"\n    \/>\n  ),\n  wQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White Queen\"\n    \/>\n  ),\n  wK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/wK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"White King\"\n    \/>\n  ),\n  \/\/ Black pieces with images and styles\n  bP: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bP.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Pawn\"\n    \/>\n  ),\n  bN: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bN.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Knight\"\n    \/>\n  ),\n  bB: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bB.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Bishop\"\n    \/>\n  ),\n  bR: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bR.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Rook\"\n    \/>\n  ),\n  bQ: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bQ.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black Queen\"\n    \/>\n  ),\n  bK: ({ squareWidth }) => (\n    &lt;img\n      src=\"\/img\/pieces\/bK.png\"\n      style={{ width: squareWidth, height: squareWidth }}\n      alt=\"Black King\"\n    \/>\n  ),\n};\n\n\/\/ Define custom square styles for the \"White Stripe Theme\"\nconst lightSquareStyle = {\n  backgroundColor: \"#FFFFFF\", \/\/ Light square base color\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Light square stripe pattern\n};\n\nconst darkSquareStyle = {\n  backgroundColor: \"#CCCCCC\", \/\/ Dark square base color\n  backgroundImage:\n    \"repeating-linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 0, rgba(0, 0, 0, 0.1) 2px, transparent 2px, transparent 4px)\", \/\/ Dark square stripe pattern\n};\n\nconst App = () => {\n  \/\/ State variables for chess game logic, Stockfish worker, best move, and evaluation\n  const &#91;game, setGame] = useState(new Chess()); \/\/ Chess game instance\n  const &#91;stockfish, setStockfish] = useState(null); \/\/ Stockfish Web Worker instance\n  const &#91;bestMove, setBestMove] = useState(\"\"); \/\/ Best move suggested by Stockfish\n  const &#91;evaluation, setEvaluation] = useState(\"\"); \/\/ Evaluation of the position by Stockfish\n  const &#91;bestMoveArrow, setBestMoveArrow] = useState(&#91;]); \/\/ Stores arrow based on best move\n  const arrowColor = \"rgba(0, 0, 255, 0.6)\"; \/\/ Custom arrow color\n\n  \/\/ State variables for tracking the last move's from and to squares\n  const &#91;fromSquare, setFromSquare] = useState(null); \/\/ Holds the starting square of the last move\n  const &#91;toSquare, setToSquare] = useState(null); \/\/ Holds the destination square of the last move\n\n  \/\/ useEffect hook to initialize the Stockfish Web Worker\n  useEffect(() => {\n    const stockfishWorker = new Worker(`${process.env.PUBLIC_URL}\/js\/stockfish-16.1-lite-single.js`);\n\n    setStockfish(stockfishWorker);\n\n    \/\/ Terminate the worker when the component unmounts\n    return () => {\n      stockfishWorker.terminate();\n    };\n  }, &#91;]);\n\n  \/\/ Function to handle piece drop events on the chessboard\n  const onDrop = (sourceSquare, targetSquare) => {\n    const gameCopy = new Chess(game.fen()); \/\/ Clone the current game state\n\n    try {\n      const move = gameCopy.move({\n        from: sourceSquare,\n        to: targetSquare,\n        promotion: \"q\", \/\/ Always promote to a queen for simplicity\n      });\n\n      \/\/ If the move is invalid, return false to prevent it\n      if (move === null) {\n        return false;\n      }\n\n      setGame(gameCopy); \/\/ Update the game state with the new move\n\n      \/\/ Update last move states for highlighting\n      setFromSquare(sourceSquare); \/\/ Update the starting square of the last move\n      setToSquare(targetSquare); \/\/ Update the destination square of the last move\n\n      \/\/ Send the updated position to Stockfish for analysis\n      if (stockfish) {\n        stockfish.postMessage(`position fen ${gameCopy.fen()}`); \/\/ Set the position in Stockfish\n        stockfish.postMessage(\"go depth 15\"); \/\/ Ask Stockfish to analyze to depth 15\n\n        \/\/ Listen for messages from Stockfish and update best move and evaluation\n        stockfish.onmessage = (event) => {\n          const { bestMove, evaluation } = getEvaluation(\n            event.data,\n            game.turn()\n          );\n          if (bestMove) {\n            setBestMove(bestMove); \/\/ Update the best move\n            setBestMoveArrow(&#91;&#91;bestMove.slice(0, 2), bestMove.slice(2, 4)]]); \/\/ Set arrow for best move\n          }\n          if (evaluation) setEvaluation(evaluation); \/\/ Update the evaluation score\n        };\n      }\n\n      return true; \/\/ Return true if the move was valid\n    } catch (error) {\n      console.error(error.message); \/\/ Log error if an invalid move\n      return false;\n    }\n  };\n\n  \/\/ Function to define custom styles for the last move's from and to squares\n  const getSquareStyles = () => {\n    const styles = {}; \/\/ Initialize an empty object for square styles\n    if (fromSquare) {\n      styles&#91;fromSquare] = { backgroundColor: \"rgba(173, 216, 230, 0.8)\" }; \/\/ Light blue for the from-square\n    }\n    if (toSquare) {\n      styles&#91;toSquare] = { backgroundColor: \"rgba(144, 238, 144, 0.8)\" }; \/\/ Light green for the to-square\n    }\n    return styles; \/\/ Return the styles object\n  };\n\n  return (\n    &lt;div>\n      &lt;h1>Chess Game with Stockfish&lt;\/h1>\n      {\/* Chessboard component with custom pieces, square styles, and custom arrow *\/}\n      &lt;Chessboard\n        position={game.fen()} \/\/ Current position from the game state\n        onPieceDrop={onDrop} \/\/ Function to handle piece drops\n        boardWidth={500} \/\/ Width of the chessboard in pixels\n        customPieces={customPieces} \/\/ Custom pieces mapping\n        customLightSquareStyle={lightSquareStyle} \/\/ Apply custom light square style\n        customDarkSquareStyle={darkSquareStyle} \/\/ Apply custom dark square style\n        customSquareStyles={getSquareStyles()} \/\/ Apply last move highlight styles\n        customArrows={bestMoveArrow} \/\/ Draws the best move arrow on the board\n        customArrowColor={arrowColor} \/\/ Set the custom arrow color\n      \/>\n      {\/* Display the best move and evaluation score *\/}\n      &lt;div>\n        &lt;h3>Best Move: {bestMove || \"Calculating...\"}&lt;\/h3>\n        &lt;h3>Evaluation: {evaluation || \"Evaluating...\"}&lt;\/h3>\n      &lt;\/div>\n    &lt;\/div>\n  );\n};\n\nexport default App; \/\/ Export the App component as the default export<\/code><\/pre>\n\n\n\n<p>You should now see the following:<br><img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=webp&amp;h=0&amp;op=resize&amp;path=hollowleaf:ublogBody:4tAknhqiG5P8:xOiOQ5dq.png&amp;w=800&amp;sig=47e7b49277bcb4ef8303dbe77315727e09908ca9\" alt=\"image.png\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#summary\"><\/a>Summary<\/h2>\n\n\n\n<p>In this blog, we explored how to customize a chessboard application with interactive features using React and the&nbsp;<code>react-chessboard<\/code>&nbsp;library. Starting from setting up a functional chessboard, we added powerful enhancements to bring the game to life.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Custom Chess Pieces and Board Styling<\/strong>: We demonstrated how to create a unique look for the chessboard by applying custom images for each piece and adding a striped theme to the board squares.<\/li>\n\n\n\n<li><strong>Move Tracking with Square Highlights<\/strong>: To enhance gameplay visibility, we implemented square highlighting for the last move, using distinct colors to show the starting and ending squares. This feature makes it easy to follow the most recent moves in a visually engaging way.<\/li>\n\n\n\n<li><strong>Best Move Arrows Using Stockfish<\/strong>: By integrating Stockfish, a powerful chess engine, we enabled the chessboard to analyze positions and return the best move. We took this output and dynamically rendered an arrow pointing from the starting square to the destination square, making the engine\u2019s recommendations easy to visualize.<\/li>\n<\/ol>\n\n\n\n<p>Each of these features enhances the chess experience, making it more interactive and visually appealing. With custom styling, real-time engine suggestions, and intuitive move tracking, this guide provides a strong foundation for creating a sophisticated and engaging chess application.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj#learn-more\"><\/a><strong>Learn more<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/reactjs.org\/\">React<\/a>\u00a0\u2013 A JavaScript library for building user interfaces.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.npmjs.com\/package\/react-chessboard\">react-chessboard<\/a>\u00a0\u2013 A React component for rendering a chessboard.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.npmjs.com\/package\/chess.js\">chess.js<\/a>\u00a0\u2013 A library for handling chess game rules and move validation.<\/li>\n\n\n\n<li><a href=\"https:\/\/stockfishchess.org\/\">Stockfish<\/a>\u00a0\u2013 A powerful open-source chess engine.<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/nmrugg\/stockfish.js\">stockfish.js<\/a>\u00a0\u2013 A JavaScript and WebAssembly version of Stockfish for web applications.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.w3schools.com\/css\/\">CSS<\/a>\u00a0\u2013 A styling language used to design and customize HTML elements.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Customising the Chessboard I began my journey into modern web programming in October 2023, with&nbsp;Chessboard Magic&nbsp;as my first major project. Initially, it was just a simple exercise, but it quickly expanded, and now&nbsp;Chessboard Magic&nbsp;includes 34 unique chess-based applications! I\u2019ve learned a lot along the way and want to share my experiences with you, hoping it [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":36,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-35","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/35","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/comments?post=35"}],"version-history":[{"count":1,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/35\/revisions"}],"predecessor-version":[{"id":37,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/35\/revisions\/37"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/media\/36"}],"wp:attachment":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/media?parent=35"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/categories?post=35"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/tags?post=35"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}