Can I Vibe Code a Real Online Casino Game (Part 4)

Previous entries in this series: Part 1 · Part 2 · Part 3

In last week’s article, I wrote about how I spent many, many frustrating hours working on improving the graphics and animation of my vibe-coded casino game, PlinkoVibe. Eventually, I got to a point where it was difficult to improve without getting real graphics designers involved, people with genuine expertise, so I decided to move on and work on some more fun parts of the experiment.

Background Music

Last week I concluded that the people who work on the graphics, animations and visuals for online casino games add a lot more value than I first thought. But another part of what makes a casino game feel good to play is the sound effects and background music. So far, PlinkoVibe has been silent besides the tinkling of the balls as they fall down the board into the slots beneath. To be truly professional, my game needs a soundtrack.

AI has already disrupted music far more than you might think. Streaming services have a surprising amount of AI-generated content already – my kids often listen to songs that I am almost certain are AI-generated. I say almost certain, because it’s genuinely hard to tell.

To create my background music, I use Suno. Suno is the leading AI music creation model and it is really very impressive the first time you use it. Describe the song you want, and Suno produces two versions of a full song which you can download for free (but cannot use commercially without upgrading to a paid subscription).

To create the song I use AI to prompt AI. I feed Perplexity all the articles I’ve written so far and some of the assets I’ve produced, and ask it to create a prompt for Suno to create background music for the game. Then I enter this into Suno and the results are pretty great. My background music, ‘Lucky Loop Lanes’, is a certified banger.

Actually, one of the songs is too much of a banger. This is background music, after all, I don’t want it to be distracting. I pick the version that is a little more chilled out, and ask Cursor to implement it as background music in the game, at a low volume relative to the sound effects and with a volume control for those who want to dial it up or down to their taste.

There’s one final challenge. Modern browsers prevent websites from automatically playing audio unless the user interacts with the page, so my background music doesn’t start until the player clicks somewhere. To solve this, I implement a splash screen with a brief overview of the rules, which I need to do anyway. When the user clicks on the call-to-action, the music starts.

At the time I write this, I’ve been humming the background music around the house for days.

Deploying to Live

So far, everything has run locally on my machine. But this exercise is supposed to be somewhat realistic, and in a real online casino environment, things are much more complicated:

  • The casino has a website which launches the game, usually in an iFrame or canvas
  • The player account (most importantly their account balance) is held on a casino system called the PAM (Player Account Management system), which is usually not hosted on the same infrastructure as the website.

The casino game itself is split into two:

  • a backend – the Remote Gaming Server, which handles all of the game logic and is not accessible to the public at all
  • the frontend, which by its very nature, is entirely accessible to the public – and therefore, cannot contain anything sensitive at all

So there are four components, all potentially hosted on different infrastructure, which need to talk to each other securely and with high performance.

I’ve built my app with this in mind from the very beginning, but to keep things simple, so far I have only split the app into two parts – a frontend and backend. I’ll do the PAM later.

Choosing where to deploy the frontend is easy – I pick Cloudflare. It’s free, incredibly performant, and I already have it setup on my website for DDOS protection and CDN. I’m a huge Cloudflare fan and setting up the project in Cloudflare Pages is ridiculously easy.

To be honest, I would have used Cloudflare for the backend as well, but for realism I want to deploy elsewhere, so choose Render. There is, unfortunately, a downside to this. On their free plan, Render puts your service in a ‘sleep mode’ if it’s inactive for 15 minutes or more, and it can take up to a minute to start up again. Obviously, this would be a huge issue for a real project, but for my personal experiment, I just make sure the frontend can gracefully handle this slow startup. I implement a ‘connecting’ screen that explains the situation and even has a link to donate money to buy better servers!

Before going live for the first time, I ask Opus 4.6 to run a thorough security audit, and then implement them with Sonnet. It implements some useful security hardening which would be important in the real world, such as rate limiting, a CORS policy, XSS prevention, enforcing TLS 1.3 at a minimum, and more.

I also explore a couple of other hardening options. I can’t stop the player being able to read the API calls, for example – even interfere with them potentially, since they have access to the local machine. I make sure the server doesn’t accept invalid requests, for safety. It’s already designed so that nothing the player does on the frontend can change the outcome on the backend, but I validate this anyway, just to be safe. I could also obfuscate everything on the frontend. But I stop short of doing this just yet – it should really be the final step in any deployment, as it will make maintaining the app very difficult.

The game breaks immediately in two important ways. First, any bet with multiple balls plays out with a huge delay between each ball drops. The first ball drops. You wait an age. The second ball drops… it’s unplayable.

Secondly, any time you play more than 30 balls at once, the RGS immediately disconnects and the whole game fails.

My first instinct is that instead of sending the bet as a single request that includes the number of balls, the front-end is sending a single request for each ball. I inspect the API calls and my suspicions are confirmed – each bet is a single API request, and when your bet is for 30 balls or more, 30 or more requests are sent immediately after one another and the rate limit that I just added for security is exceeded.

Fixing this is easy, thankfully. Cursor quickly rebuilds the bet request to include the number of balls, and increases the rate limit a little for good measure. The problem is resolved.

Now, everything is live! You can play the game here: https://plinkovibe.scott.co.im

Try your best to break it and let me know your experience.

What Next

I’m getting close to my objective now. The next step to make this more realistic is to split the infrastructure into three parts – PAM, RGS and frontend. I don’t actually need a real PAM to get to the end goal (a casino game that could plausibly be deployed live with a real casino operator), I just need to be able to simulate one so that the way my RGS interacts with a PAM is realistic. I’ll need a simple player account, a way to manage the balance, and support for some popular currencies. Based on my experience so far I don’t think this will be very difficult to implement, but there might be some issues that crop up when I deploy the thing on three different servers.

The hard part will be making PlinkoVibe a game that players would actually want to play. There are probably a hundred Plinko games on the market right now, why would players choose mine?

I have some ideas on that though, and an old friend does as well. More on that in the next article!

Want to Contribute?

If you want to contribute or help me work through issues, clone the repo and get in touch! https://github.com/AlexScott72o/PlinkoVibe

If you’d like to help me buy the Render premium plan, go here: https://buymeacoffee.com/alexscott

Of course if you just want to play the game and send me your feedback, go here: https://plinkovibe.scott.co.im (you might have to wait patiently for the game to start up from sleep).