Writing a custom overlay with React
Tags: node, react, showdev
Published: 2021-02-23 11:38:50

Whenever I have ideas for personal projects and I don't trash them completely because either they're impossible for me to carry out reasonably well, or they have already been done by everyone and their mother, they tend to be oriented towards content creation or videogame competitions, usually as a result of me finding out a chore that may be automated is being performed manually.

Obviously, I don't blame anyone for not commissioning a programmer to code a tool or a bot to help them with those, mostly because it's normally on the low end where I find these sorts of hiccups, and considering the little money (if any) that will move around those environments, it's unlikely investing into a fancier workflow will be a wise decision to their eyes. However, even if I know my projects will probably go unnoticed by those people, it's still a good chance for me to try out a somewhat original idea and generate some code that doesn't consist of doing the same thing you've already seen a million times on the web for anyone to take a look at.

# The idea

That said, I'd like to tell you how I came up with this overlay idea. I was watching one of the streamers I tend to watch on Twitch on a somewhat regular basis, except that day, they were broadcasting a little tournament under a charity event. A link was provided to pledge some money for the cause, and between rounds and matches, the streamer would get to the campaign's website and copy new donations to a textbox in one of their scenes manually.

That brought up a question to my mind: "isn't there a bot for that?". As I imagined, no one was aware of such a thing in the stream. The service used as the basis for the campaign was [Tiltify,](https://tiltify.com/) and the first thing I tried upon figuring out the name of the website was searching `tiltify api`, and sure enough, [there's an HTTP API for it.](https://tiltify.github.io/api/)

![One of many campaigns held on Tiltify](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djik9i859tvvxaiuuvth.png)

Having those docs handy, it's clear I can create a relatively simple overlay using the [React](https://reactjs.org/) library and the default template it provides with the Node script `create-react-app` as a starting point. The purpose of that is to try it out some and practice working with [RxJS.](https://github.com/ReactiveX/rxjs) I already have some experience with it as a result of having been working with Angular's HTTP client in the development of an application made with Angular.

Unlike what I first thought, I decided to end up using [Redux](https://redux.js.org/) as well to carry the configuration to the components that need it and not have to either pass the parameters manually or transform them inside the component. Its Angular equivalent is NgRx, although that one works quite a bit differently from Redux, which only makes sense because NgRx is made to suit the way Angular works best. Redux by itself (and a helper package) seems to be better suited to React.

# The layout

Being a simple overlay that consumes an API, the application has only two views: the `Overlay` itself, which will be loaded by the `App` if the necessary configuration in the query parameters is present, and a `LinkGenerator` that should make it easier for streamers to paste the required information and do further configuration if they want, then get a link copied to the clipboard that will get the display view loaded into their scene.

![The link generator](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ndh7kzlvlskxurrwz5ym.png)

The `Overlay` component's job is to get the data from Tiltify's API and render each item of the list as a `Donation` instance, showing its name and amount. They may be displayed in the order the API yields them (sorted from latest to oldest donation) or sorted descendingly by price, showing the greatest amounts donated on top.

The amount is further delegated into the `AmountDisplay`, which makes sure to layout the donated amount according to the configured position for it and desired currency. For example, a price in euros has the euro sign placed to the right (eg. 100€), while a price in dollars is written the opposite way (eg $100). Only adjusting the specific parameters is needed so that the display isn't dependant on CSS styles. This should allow the same styles to be used with different currencies.

![A diagram of how the components are related to each other](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uq100ww930en5wp51gqe.png)

# The limitations

As you might imagine, most of the *limitations* came from the Tiltify API itself, simply because it is quite bare at the moment and the documentation is also lacking. The most significant issue for my purposes was the fact that there's no WebSocket option. In short, WebSocket keeps a communication channel open for longer than a regular HTTP request, thus allowing the sender and receiver to keep sending messages to each other. That way, for example, the application would get updates from the API without having to send another request. Since that wasn't an option, the next better possibility was setting up an observable which calls the code responsible for fetching all the donations every minute.

Also related to the API itself, as of the moment of writing this article, no options to sort the donations seem to be provided, and since that has to be done manually, I think it's best to fetch them all regardless of whether they will be displayed as they are fetched or sorted by amount descendingly. Besides, the tokens I generated to test the overlay with real data were constantly banned in a matter of hours for some reason; I do suspect it's because I accessed multiple campaigns from other people with them. After all, when I try just one campaign with one token, it keeps working all the time.

As I didn't want to create a sample campaign without a proper way to add test donations that didn't involve spending real money, and because there's no easy way of finding a campaign that is getting a lot of new donations regularly, I decided to add a *test mode* that should allow anyone else making custom styles to test how everything should look without continuously fetching data from Tiltify. It can be triggered in dev mode if you add `&test=1`, or basically a `test` query parameter with any value that is truthy to any URL the `LinkGenerator` makes.

![How the test mode looks with default styles](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85ripjabwx3hqx8ss5mn.png)

My desire to add unit tests to all the code I wrote caused some unexpected changes as well. Particularly in the overlay, which is actually exposed by itself in a module and connected to the store in another. That's because I couldn't fake the timers needed to test the observable created as a result of the mapping from the state to the component. Besides, even if I pulled it off, all the mocking necessary to make the test suite work correctly would have made it excessively complicated. Thus, I tested the overlay without any connection, separated the code responsible for bringing the current list of donations to its own *service*, thus testing it by itself, too, and left the connection to the store untested due to the timers' problem I described before.

# The result

The finished overlay application is available to try out [here.](https://jmmedina00.github.io/tiltify-donors-overlay/) The source code and documentation about its usage and customization can be found in the repo below.

{% github jmmedina00/tiltify-donors-overlay %}

Feel free to ask me any questions about anything in the code or regarding my *design decisions* and I'll try to give the best reply I can provide.