Clicker Incremental Games with Svelte 5
My developer experience with Svelte 5 features
I am doing an incremental clicker game with Svelte 5 and it is getting out of hand.
Incremental clicker games have something unique that other genres don’t offer—an intense dopaminergic effect. Just watch a progress bar promise you some money in a short time, and you’ll understand.
You buy more units, you get more money.
You buy upgrades, and you earn money faster.
The Story Behind the Game
I’m currently working at a German newspaper, and I thought it would be fun to create a game with a similar backdrop. In the game, you’re the manager of a freshly inherited business that’s on the brink of bankruptcy. You have to start from scratch and prove that your business degree, which has been gathering dust behind your office door, was worth it after all.
What began as a simple “let’s see how it goes” project has turned into an unexpectedly delightful coding experience—so much so that even I find myself getting trapped in the clicks. Initially, I planned to use just local storage to save user data, but, as I mentioned, it’s getting out of hand.
Leaderboard with Clerk Authentication and Turbo DB
I’ve used these two tools in a few projects already, and the development experience is, honestly, amazing. With Clerk, you don’t have to worry about authentication, providers, or asking Papa Google for permissions—Clerk handles all that for you. And Turso, combined with Drizzle ORM, makes querying data a breeze, bringing it to life in my database.
To be honest, the biggest challenge was adapting my code from Svelte 4 to Svelte 5, but I’m happy to say that’s done. You’ll see more $ signs in my Svelte components than in my Qwik ones, and that’s saying something. But now, with out-of-the-box reactive states and derived states—especially the latter, which is crucial for an incremental game—the game is coming together beautifully.
Here you can see how I’m calculating the time to earn money. At the beginning, it’s 10 seconds, but with each improvement that you bought that has the property speed_increase
, the time decreases.
let BASE_TIME_TO_EARN = 10000;
let timeToEarn = $derived(
BASE_TIME_TO_EARN -
[...improvements, ...improvementsPRO].reduce((acc, improvement) => {
if (improvement.bought && improvement.speed_increase) {
return acc + improvement.speed_increase;
}
return acc;
}, 0)
);
A very similar issue happens with the multiplier. The more units you buy, the more money you earn. However, I had to find a way so that people would not create an army of the same unit and earn money too fast. So the more units you have of the same type, the less the multiplier is worth.
let INITIAL_MULTIPLIER = 1.5;
let finalMultiplier = $derived(
INITIAL_MULTIPLIER +
professions.reduce((acc, profession) => {
return acc + profession.units * profession.multiplyer * (1 / (1 + profession.units * 0.1));
}, 0)
);
Cool, right? Of course, none of this would matter if the UI was boring.
Svelte 5 with TailwindCSS and Shadcn/Svelte
Coming from the React/Next.js world, I’ve used Shadcn a few times. There’s an unofficial library that adapts everything for Svelte, so you can have amazing UI components in no time. And to be honest, when I’m iterating and experimenting with fun ideas, I’m not too concerned about downloading an unnecessary component or two. TailwindCSS makes everything extremely easy, and the great thing about Shadcn is their documentation. I needed to extend a couple of components for i18n reasons, and the docs made it simple to modify the component primitives.
The Future of This Incremental Clicker Svelte Game
Let’s see where this goes. I’m planning to add proper authentication and data storage, paywalls, and different levels. I want to maintain the humor that’s woven into the game—right now, it’s full of inside jokes about my current company—but I could easily make each level feel like a completely different company and experience!
You can check out the game here. I hope you enjoy it as much as I do!
Share article