DEV Community

Franco Balik
Franco Balik

Posted on

How I Started Organizing NoLimit City Game Data on the Frontend

A few days ago I was looking through a bunch of NoLimit City games and noticed something that I had never really paid attention to before.

Their games can get complicated pretty quickly.

You don't just have a game name and an image.

There are things like RTP, volatility, release date, maximum win, bonus modes, and then mechanics such as xWays, xNudge, xSplit and xBet.

At first I thought:

"This should be pretty easy to organize."

It wasn't.

Once the number of games starts growing, manually writing every card in HTML becomes annoying very fast.

So I started thinking about how I would structure the data if I wanted to build a simple game catalog.

Starting with a simple object

Instead of writing something like this repeatedly:

Game Name


RTP: 96%


Mechanic: xWays

I prefer keeping the information separate from the HTML.

Something simple like:

const games = [
{
name: "Example Game",
provider: "NoLimit City",
rtp: 96.0,
volatility: "High",
mechanics: ["xWays", "xNudge"]
},
{
name: "Another Game",
provider: "NoLimit City",
rtp: 96.1,
volatility: "High",
mechanics: ["xSplit"]
}
];

Then the frontend can generate the cards automatically.

games.forEach(game => {
const card = document.createElement("div");

card.className = "game-card";

card.innerHTML =
<h2>${game.name}</h2>
<p>${game.provider}</p>
<p>RTP: ${game.rtp}%</p>
<p>${game.mechanics.join(" / ")}</p>
;

document.querySelector("#games").appendChild(card);
});

Nothing complicated.

But even this small change makes maintaining the page much easier.

The interesting part was actually the mechanics

This was where things became more interesting for me.

NoLimit City games don't always follow exactly the same structure.

One game might heavily use xWays.

Another could combine xWays with xNudge.

Others introduce xSplit or completely different bonus features.

That means putting everything under one generic "feature" field doesn't really work.

Something like this is more flexible:

mechanics: [
"xWays",
"xNudge",
"xSplit"
]

Now I can filter games by mechanics.

For example:

const xWaysGames = games.filter(game =>
game.mechanics.includes("xWays")
);

That opens up some nice possibilities for the UI.

A visitor could select:

xWays
xNudge
xSplit
Bonus Buy
High Volatility

and instantly narrow down the catalog.

I also noticed that naming gets messy

Another small problem is inconsistent naming.

For example:

xways
XWAYS
xWays
xWays®

Technically those strings are different.

So before filtering anything, I like normalizing the values.

function normalizeMechanic(value) {
return value
.toLowerCase()
.replace("®", "")
.trim();
}

It's a tiny thing, but those tiny things usually become annoying later when your dataset gets bigger.

Looking at existing NoLimit City catalogs helped

I spent some time looking at how different websites organize information around the provider.

Some focus mostly on individual game pages.

Others organize games around things like mechanics, RTP or popularity.

While comparing them, I also came across slotnolimitcity.com, which is much closer to the type of niche catalog I had in mind.

That made me realize something:

the difficult part isn't necessarily displaying the games.

It's deciding how people should browse them.

A developer might naturally think:

"I'll just sort everything alphabetically."

But that's probably not how someone actually explores a game catalog.

They might be looking for a particular mechanic.

Or a newer release.

Or something with a specific style of gameplay.

So the data structure should support that from the beginning.

Adding a basic search

Once the data is structured properly, search becomes pretty straightforward.

const search = document.querySelector("#search");

search.addEventListener("input", event => {
const query = event.target.value.toLowerCase();

const results = games.filter(game =>
game.name.toLowerCase().includes(query) ||
game.mechanics.some(mechanic =>
mechanic.toLowerCase().includes(query)
)
);

console.log(results);
});

Now searching for either a game name or something like xWays can return relevant results.

Later this could obviously be improved with tags, sorting and proper UI updates.

Don't load every image immediately

Game catalogs tend to contain a lot of thumbnails.

Loading all of them at once isn't ideal.

For cards further down the page I normally use:

src="game-thumbnail.webp"
alt="Game thumbnail"
loading="lazy"
width="400"
height="250"
/>

That way the browser doesn't immediately download dozens of images that aren't even visible yet.

For the first few images above the fold, I usually don't lazy-load them.

What I'd change if the project became bigger

For a small project, a local JavaScript array is perfectly fine.

But once you're dealing with hundreds of entries, I'd probably move the data elsewhere.

Something like:

API

JSON

Frontend

Search / Filters / Sorting

It also makes updating releases much easier.

Instead of touching HTML every time a new game appears, the frontend simply consumes the updated data.

Final thoughts

This started as a pretty simple idea.

I just wanted to understand how I would organize a collection of NoLimit City games without hardcoding every single card.

But it turned into a useful little frontend exercise.

The biggest lesson for me wasn't actually about JavaScript.

It was about data structure.

If the data is messy, search becomes messy.

Filters become messy.

Updating content becomes messy.

But if you decide early what information each item needs and keep the structure consistent, the frontend becomes surprisingly simple.

I'm probably going to experiment next with combining multiple filters at once — for example filtering by mechanic, volatility and release year without turning the JavaScript into a giant collection of if statements.

That sounds like a fun problem for another weekend.

Top comments (0)