{"id":84,"date":"2025-09-22T22:10:00","date_gmt":"2025-09-22T22:10:00","guid":{"rendered":"https:\/\/blog.chessboardmagic.com\/?p=84"},"modified":"2025-09-28T22:11:43","modified_gmt":"2025-09-28T22:11:43","slug":"building-chess-solitaire","status":"publish","type":"post","link":"https:\/\/blog.chessboardmagic.com\/index.php\/2025\/09\/22\/building-chess-solitaire\/","title":{"rendered":"Building Chess Solitaire"},"content":{"rendered":"\n<p><strong>Exploring the design, analysis, and results behind my latest chess application<\/strong><\/p>\n\n\n\n<p>I\u2019m always on the lookout for fresh chess application ideas. Over time, I\u2019ve built more than 50 different tools (51 and counting!) and I\u2019ve set myself a symbolic goal of reaching 64 \u2014 one for every square on the board. Recently, someone in the community (shoutout to&nbsp;<strong>mattchess<\/strong>) asked if I had ever thought about building a&nbsp;<strong>Chess Solitaire<\/strong>&nbsp;game. Honestly, I had no idea what that was at first, but the concept immediately caught my attention once it was explained.<br>At first, I planned to just add it to my ever-growing backlog of \u201csomeday projects.\u201d But then I found myself with a few free evenings and thought \u2014 why not give it a shot?<br>In this blog, I\u2019ll walk you through my thought process, from the initial design stage to getting a working version of the game up and running.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>If you just want to see the application:&nbsp;<strong><a href=\"https:\/\/chessboardmagic.vercel.app\/solitaire\">Try Now<\/a><\/strong><\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note:<\/strong>&nbsp;This build is currently live on my&nbsp;<strong>test site<\/strong>, not yet on the main site. I like to experiment and gather feedback before rolling features out more broadly. So if you have any feedback, do let me know in the comments or on&nbsp;<strong><a href=\"https:\/\/discord.gg\/3SN7evwaKX\">Discord<\/a><\/strong><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#what-is-chess-solitaire\"><\/a>What is Chess Solitaire?<\/h2>\n\n\n\n<p>The idea behind&nbsp;<strong>Chess Solitaire<\/strong>&nbsp;is simple but surprisingly powerful. The goal is to replay a real game \u2014 usually from a strong master, a famous clash, or a historic encounter \u2014 and try to guess the moves as if you were the one sitting at the board.<br>Of course, you could just open up a PGN and click through the moves by yourself. That\u2019s why it\u2019s called \u201csolitaire\u201d \u2014 it\u2019s essentially a solo training exercise. But the twist is that after every move you play, the system gives you immediate feedback. If you chose the same move as the master, it\u2019s marked as a match, and if you went off track, you\u2019ll know right away.<br>The purpose of the exercise is two-fold. First, it gives you the chance to walk through and reflect on an instructive game, taking the time to understand each decision. Second, it challenges you to see how closely your thought process aligns with that of a grandmaster. In that sense, it becomes both a study tool and a fun test of your chess instincts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#application-design\"><\/a>Application Design<\/h2>\n\n\n\n<p>When I first sat down to think about how to build Chess Solitaire, my initial question was simple:&nbsp;<em>what components would this actually need?<\/em>&nbsp;At the very least, it would require an interactive chessboard where moves could be played, a PGN card to display the notation, some form of analysis during the game, and finally, a review system once the game ended.<br>From there, the flow began to take shape. The idea was that you could either load a PGN directly or choose a random game from a built-in collection \u2014 I decided to leverage my archive of every World Championship game for this. Once a game is loaded, you can start playing through it on the board. As you make moves, the PGN card updates in real time, and beneath it, in-game analysis shows how your choices compare to the original moves.<br>I also wanted to give players some flexibility with the controls. You can set how many attempts you want per move, which changes the difficulty depending on how strict you want the experience to be. You can also choose which side you\u2019re playing \u2014 White, Black, or both \u2014 so the game can adapt to whatever training focus you have in mind.<br>You can keep going until you reach the end of the game naturally, or hit an \u201cEnd Game\u201d button to jump straight to the review phase. The review itself offers a fuller picture of your performance: which moves you matched, where you went wrong, and whether your alternatives were still reasonable. In some cases, your move might even be an improvement over the grandmaster\u2019s choice \u2014 was it a book move, a hidden resource, or simply stronger according to the engine?<br>In the end, the workflow I had in mind was deliberately simple. Load a game, play through it as best you can, and then see the outcome laid out clearly in the review. Simple to follow, but rich enough to make the experience both a learning tool and an enjoyable test of skill.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note:<\/strong>&nbsp;Whenever I start a new application, I never jump straight into code. Instead, I begin with pen and paper, sketching out the layout and flow I have in mind. I\u2019ll iterate a few times, refining the look and structure until I\u2019m happy with it. Only then do I translate that design into actual code. This step saves me a lot of rework later and helps me stay clear on what I\u2019m trying to build.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#tech-stack\"><\/a>Tech Stack<\/h2>\n\n\n\n<p>For those interested in the nuts and bolts, the Chess Solitaire application is built with a lightweight and straightforward stack:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/react.dev\/\">React.js<\/a><\/strong>\u00a0\u2014 powering the UI, component state, and overall application structure.<\/li>\n\n\n\n<li><strong><a href=\"https:\/\/github.com\/Clariity\/react-chessboard\">React Chessboard<\/a><\/strong>\u00a0\u2014 for the interactive chessboard, move input, and piece rendering.<\/li>\n\n\n\n<li><strong><a href=\"https:\/\/github.com\/nmrugg\/stockfish.js\">Stockfish.js<\/a><\/strong>\u00a0\u2014 running chess engine analysis directly in the browser, with a worker pool for fast and parallel evaluations.<\/li>\n\n\n\n<li><strong>Plain JavaScript utilities<\/strong>\u00a0\u2014 additional helper functions and lightweight modules to tie everything together.<\/li>\n<\/ul>\n\n\n\n<p>I deliberately kept the stack minimal. By avoiding heavy frameworks or unnecessary dependencies, I could focus on performance, responsiveness, and building the exact features I wanted without bloat.<br>If you\u2019d like to dive deeper into how to build your own Chess Web Application from scratch, I\u2019ve written a dedicated series that walks you through the fundamentals \u2014 from setting up a React project to integrating a chessboard and handling PGN data. You can check it out here:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Programming Chess Web Apps: Part One:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-one-getting-started\/8ZKpwJU8\">Getting Started<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Two:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-two-stockfish\/PdeOTODf\">Stockfish<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Three:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-three-deploying-your-application\/J3GdsKZP\">Deploying your Application<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Four:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-four-chessboard-customisation\/Is0jxElj\">Chessboard Customisation<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Five:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-five-game-review\/32JsEsrs\">Game Review<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Six:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-six-essential-resources\/Yg5HxCt6\">Essential Resources<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Seven:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-seven-lichess-api\/6MgfKoeh\">Lichess API<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Eight:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-eight-chesscom-api\/mGHcVFEJ\">Chess.com API<\/a><\/strong><\/li>\n\n\n\n<li>Programming Chess Web Apps: Part Nine:\u00a0<strong><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/chess-web-programming-part-nine-chessground\/2RcZvKl8\">Chessground<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#running-analysis\"><\/a>Running Analysis<\/h2>\n\n\n\n<p>This was by far the most challenging part of building Chess Solitaire. The analysis needed to feel quick and responsive \u2014 ideally instant during the game \u2014 and the post-game review had to generate results in seconds, not minutes. That immediately raised the question: how do you achieve this level of speed without overwhelming the system?<br>For the engine, I chose to leverage&nbsp;<strong>Stockfish 17.1 Lite.js<\/strong>, which I already use across many of my other applications. It\u2019s freely available, reliable, and lightweight enough to run in the browser. The tricky part wasn\u2019t running Stockfish itself, but doing so efficiently. Imagine a situation where the player has unlimited guesses on a single move. If they tried twenty different moves and each one was evaluated at depth 15, that would mean running the engine twenty times in sequence. The feedback would be far too slow \u2014 the complete opposite of what I wanted.<br>To solve this, I created a&nbsp;<strong>pool of Stockfish workers<\/strong>. Instead of a single engine instance, I spun up eight in parallel. That way, multiple moves could be evaluated simultaneously, and feedback would arrive quickly enough to feel immediate. On most computers, this setup reaches depth 15 for all the moves almost instantly, which makes the in-game experience smooth and responsive.<br>The same approach worked for the post-game analysis. Once the game ends, I could send batches of positions to the worker pool and process them in parallel, giving the user a complete review of the entire game in just a few seconds. This part required a little extra care, though. The post-game review involved a&nbsp;<strong>two-pass system<\/strong>: first, attach Stockfish evaluations (as well as the principal variations for later comparison) to every move and every guess the player made; second, go back through those results and assign annotations. This ensured that when you navigate through the finished game, it\u2019s clear not only whether you matched the grandmaster\u2019s move, but also how your alternative compared \u2014 was it still playable, was it book theory, or did you somehow stumble on an improvement?<br>Getting this analysis pipeline running smoothly was the hardest technical challenge. Between synchronization issues, potential memory issues, and the complexity of managing multiple engine instances, this was the part where I suspect many hobbyist developers would get stuck. Once I solved it, though, the rest of the application became a matter of building out the components and fine-tuning the workflow to deliver the desired user experience.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note:<\/strong>&nbsp;One of the most important aspects of building chess applications that work with PGNs is deciding how to store the data. A raw PGN string might be fine for display, but it\u2019s not effective for analysis or interaction. For Chess Solitaire, I structured the data as a&nbsp;<strong>moves array with parent\u2013child relationships<\/strong>. This allowed me to traverse the entire move tree easily, while still being able to process each move individually and attach attributes such as evaluations, annotations, and user attempts.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#results\"><\/a>Results<\/h2>\n\n\n\n<p>Once the game is finished, the experience shifts from playing to reflecting. The&nbsp;<strong>Results<\/strong>&nbsp;phase is where everything comes together: you can see how well you matched the original game, where you went astray, and how your alternatives stacked up against the master\u2019s moves.<br>The review isn\u2019t just a list of right and wrong decisions. Each move is annotated based on Stockfish\u2019s evaluation and a comparison with the actual game. If you matched the grandmaster, it\u2019s marked clearly. If you chose something different, the system checks whether your move was still sound \u2014 was it a book move, a playable alternative, or even an improvement? In some cases, you\u2019ll discover that your idea wasn\u2019t so bad after all, and in rare cases, you might even \u201coutplay\u201d the original.<br>The results also provide an overall snapshot of your performance: how many moves were perfect matches, how many needed retries, and how many you missed entirely. This summary gives the exercise a sense of closure, but more importantly, it offers insight into your thinking process and areas for improvement.<br>For me, this was the part that made the game feel complete. The in-game feedback keeps you engaged move by move, but the results screen is what makes the whole exercise valuable as a training tool. It\u2019s here that you can step back, see the bigger picture, and measure how closely you managed to \u201cthink like a grandmaster.\u201d<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note (for the nerds):<\/strong>&nbsp;For categorizing moves, I didn\u2019t want to just say \u201cright\u201d or \u201cwrong\u201d \u2014 I wanted to give proper chess-style annotations based on the difference between the engine\u2019s best move and the player\u2019s move. Using Stockfish\u2019s evaluation as the baseline, here\u2019s the logic I used:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the move\u00a0<strong>matches the engine\u2019s best move<\/strong>\u00a0<code>*<\/code><\/li>\n\n\n\n<li>If it\u2019s\u00a0<strong>within 0.25 pawns<\/strong>\u00a0of the best\u00a0<code>!<\/code><\/li>\n\n\n\n<li>If the difference is\u00a0<strong>> 0.25<\/strong>\u00a0<code>?!<\/code>\u00a0(inaccuracy)<\/li>\n\n\n\n<li>If the difference is\u00a0<strong>> 0.75<\/strong>\u00a0<code>?<\/code>\u00a0(mistake)<\/li>\n\n\n\n<li>If the difference is\u00a0<strong>> 1.5<\/strong>\u00a0<code>??<\/code>\u00a0(blunder)<\/li>\n<\/ul>\n\n\n\n<p>These thresholds are, of course,&nbsp;<strong>arbitrary<\/strong>. They\u2019re not official or universally accepted cutoffs, but I found them to be a practical balance between being too strict and too lenient. The goal wasn\u2019t to replicate a grandmaster coach\u2019s intuition perfectly, but to provide clear, useful feedback that makes the post-game review more engaging and instructive.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#summary\"><\/a>Summary<\/h2>\n\n\n\n<p>Building Chess Solitaire turned out to be one of those projects that looks simple on the surface but hides a lot of interesting challenges under the hood. At its core, the idea is straightforward: load up a master game, try to play through it move by move, and get feedback along the way. But to make it truly engaging, I had to think carefully about design, responsiveness, and the overall flow from start to finish.<br>The design phase was about keeping things simple and intuitive: an interactive board, a PGN card, in-game feedback, and a clear results screen. Running analysis was the hardest technical hurdle \u2014 managing Stockfish in a way that felt instant and scalable required worker pools, parallel processing, and a two-pass review system. The results screen brought it all together, turning the exercise into both a training tool and a fun challenge.<br>For me, Chess Solitaire fits nicely into the larger theme of the applications I\u2019ve been building: tools that combine&nbsp;<strong>serious chess training value<\/strong>&nbsp;with a sense of play. It\u2019s a chance to step into the shoes of a grandmaster, even if just for one game, and measure how close your thought process comes to theirs.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>And here is the result&#8230; after around&nbsp;<strong>12 hours of building, testing, and tweaking<\/strong>, this is what I ended up with.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/image.lichess1.org\/display?fmt=png&amp;h=0&amp;op=resize&amp;path=ublogBody:wdcPRnZxGOA9:4LgK2I1C.png&amp;w=800&amp;sig=8ca1b8797a866165a0737a442c1dfda598e3cce1\" alt=\"image.png\"\/><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Note:<\/strong>&nbsp;Having built a large number of chess applications already, I\u2019ve accumulated an extensive library of reusable components \u2014 boards, PGN parsers, analysis panels, result cards, and more. This made the development process much smoother, since I could leverage pieces I\u2019d already refined in earlier projects. One of the joys of building a lot of chess tools is that each new project benefits from the groundwork of the previous ones.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><a href=\"https:\/\/lichess.org\/@\/HollowLeaf\/blog\/building-chess-solitaire\/9tI1wxHQ#note-one-of-the-most-important-aspects-of-building-any-application-is-to-get-feedback-and-the-community-supporting-me-is-awesome-in-giving-me-suggestions-and-tweaks-big-shout-out-to-mattchess-and-frahde-for-their-support-in-this-application\"><\/a><strong>Note<\/strong>: One of the most important aspects of building any application is to get feedback, and the community supporting me is awesome in giving me suggestions and tweaks. Big shout out to Mattchess and FRahde for their support in this application.<\/p>\n<\/blockquote>\n\n\n\n<p>Try it out yourself and see how closely you can follow a grandmaster\u2019s moves.&nbsp;<strong><a href=\"https:\/\/chessboardmagic.vercel.app\/solitaire\">Try Now<\/a><\/strong><br>Building chess applications is both fun and rewarding. If you\u2019re working on your own chess project and have questions \u2014 technical or design-related \u2014 feel free to reach out. I\u2019m always happy to talk shop and share ideas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Exploring the design, analysis, and results behind my latest chess application I\u2019m always on the lookout for fresh chess application ideas. Over time, I\u2019ve built more than 50 different tools (51 and counting!) and I\u2019ve set myself a symbolic goal of reaching 64 \u2014 one for every square on the board. Recently, someone in the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":85,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-84","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\/84","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=84"}],"version-history":[{"count":1,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/84\/revisions"}],"predecessor-version":[{"id":86,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/posts\/84\/revisions\/86"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/media\/85"}],"wp:attachment":[{"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/media?parent=84"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/categories?post=84"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.chessboardmagic.com\/index.php\/wp-json\/wp\/v2\/tags?post=84"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}