32рдле

Posted on February 23, 2024

Almost all my career I’ve been mostly a backend guy. Even when I was working with mobile platforms it usually was related to different background services. And I’m ok with that. Well, sometimes it might be difficult to explain people what are you actually doing, but I still prefer this things just because it’s more interesting for me, and, to be honest, I’m pretty bad in drawing, choosing colors, etc.

However, some time ago I played Duotrigordle and I thought what it would be great to have it in Russian. And that lead me to another pet project in a very uncommon environment for me. It’s a pure client word guessing game. Of course, I could use Scala.js for that, but I wanted to keep it light, and also, to have a little bit practice in the common frontend tools. It took couple of months for me to create it from scratch. It still have a nasty hard to reproduce bug, but it’s available at 32.limansky.me, so you can play it. Here I’d like to share some details and thoughts about this project development.

I decide to use pure React because, to be honest, I have a little experience with it already. While we developed Продажи.рф at 1-OFD, we all participated in frontend development a little bit. But, since 32rdle is a pure client side game, I decided not to use any React based frameworks. I chose wouter for routing and zustand for state management, because both of them are simple and lightweight libraries. Also I used Vite and Vitest because it’s easy to setup and fast. Of course, I used TypeScript for coding, because I have no idea how and why people write any code without of types.

Fortunately I already had Neovim setup (my dotfiles) with LSP, so I’ve been kind of ready to start.

Here is a list of top 5 problems I faced with from hard to easy:

  1. CSS.
  2. More CSS.
  3. Algorithms.
  4. React itself.
  5. Components organization.

This list is not that I initially expected. Well, I knew what CSS is hard, but I didn’t expect it to be that hard. Secondly, I expected React to be a bigger problem for me. I still have some problems with understanding hooks, and what and when, should I use, but it is not the major problem. The two last points are related. At some point I’ve found that I put to much business logic into the components. In my case that lead to the calculation duplication. For example boards can calculate their state themselves according to the entered words and the guessed word. However, these states are also required for the status bar component. So I had to change the interface of the components several times to avoid unnecessary calculation repetitions.

Some pieces of code I wrote still looks weird for me, and I feel like I do something wrong way. For example I need a path parameter to be a number.

const gameParser = (path: string, loose?: boolean): { pattern: RegExp, keys: string[] } => {
  if (path === "/daily/:id") {
    const named = parse(/^\/daily\/(?<id>[0-9]+)$/);
    return { pattern: named.pattern, keys: ['id'] };
  }

  return parse(path, loose);
};

This condition is looks ugly for me, but it works, and I have no idea how to make it better.

The whole code is available at github.