Building a mini casual game with Next.js
Tags: nextjs, framermotion, webdev, firebase
Published: 2024-01-17 14:40:00

---
title: Building a mini casual game with Next.js
published: true
description: Process I used to build this new casual mini-game
tags: nextjs, framermotion, webdev, firebase
cover_image: https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/main-showcase-lansolo.devto-cover.jpg
---

*___As a quick reminder___: this post is not a step-by-step tutorial on how I built this game, but just a review of how I approached this project during this journey.*

## The game

First and foremost, here is the [playable live game](https://findechantier.pommeclic.com/) this post is about.

## Goal

I took this game as an opportunity to improve on my technical skill and some creative processes.
We (with [Pommeclic](https://pommeclic.com/)) decided to communicate early as a way to celebrate the new year by publicly offering a game contest with prizes to win.

## Previously

I didn't start from scratch. I previously released a pretty similar game one year ago called [Blackout](https://blackout.pommeclic.com/).

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/first-sveltkit-project-with-blackout.jpg" alt="Blackout game" class="w-full">

The theme was the deep energy concern that occurs in Europe with the Ukrainian/Russian conflict.

It takes the "whac a mole" concept and adapt it to electrical units to turn off as soon as they turn on.

I decided to reuse most of the layout and principles in order to save time and focus more on the design and game logic.

## New Concept

I kept the same isometric gameboard to support the action. After a bit, I was inspired by the story of the controversial [A69 highway](https://www.connexionfrance.com/article/French-news/Controversial-new-A69-motorway-in-southern-France-What-do-you-think) construction.

The idea is to prevent vehicles to arrive on site, to postpone the start as much as possible, so that I can keep the "whac a mole" principle, with moving target this time.

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-with-nextjs-zone-central.jpg" alt="Fin de chantier game - zone centrale" class="w-full">

## Stack

I used Sveltekit for Blackout. Though I enjoyed its light syntax, I struggled with lacking features, especially having dynamic optimized assets. 

I also wanted to refocus on React through Nextjs, to avoid having an overly dispersed knowledge.

I decided to go with the same stack regarding the rest:

- Firebase as backend (auth + user data)
- Tailwind as UI framework
- Vercel as hosting

## Design

### Environment

I kept modeling using Cinema 4D to get the same low poly look & feel, this time designing a hilly countryside crossed by main roads, as well as tunnels. Those lanes will be the interactive part of the map.

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-c4d-env.jpg" alt="Fin de chantier c4d gameboard" class="w-full">

I then adapted predesigned construction vehicles, simplified and uniformized their styles. I rendered them in the 4 perspectives for which they will be used.

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-c4d-vehicles.png" alt="Fin de chantier c4d vehicles" class="w-full">

I defined the animated flags and smokes and rendered them as GIFs through After Effects.

<div class="flex">
<img src="https://res.cloudinary.com/lansolo99/image/upload/v1705480693/lansolo.dev/posts/building-a-mini-casual-game-smoke.gif" alt="Fin de chantier c4d smoke"  style="width:112px; height:112px;">
<img src="https://res.cloudinary.com/lansolo99/image/upload/v1705480693/lansolo.dev/posts/building-a-mini-casual-game-flag.gif" alt="Fin de chantier c4d flag"  style="width:112px; height:112px;">
</div>

### UI

As usual, I started with some Figma screens, based on the previously designed Blackout UI, and replace the environments. Overall, the UI stays the same. Some light improvements have been made here and there.

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-with-nextjs-figma.jpg" alt="Figma screens" class="w-full">

## Coding

### Migration from Svelte

I undertook to migrate the most of my previous Svelte codebase into a NextJs one, using the now established app router. Most of the time, it was just a matter of mirroring structure, replace with the proper framework attributes syntax (`class=` becomes `className=`).

Though a lot of functional programing could stay the same, I had to reorganize how the data flows. Stores become separated contexts, and useState enter the game.

I intended to experiment a lot with RSC and server actions, but, I almost any time gave up using the `"use-client"` directive to be able to use freely all the UI mutation patterns I was used to. I really have to take the mental shift to de-correlate RSCs and CSCs.

I guess it's no big deal as this app is mostly a client side with heavy reactive UI.

### Gameboard

I used a single rendered image for the countryside background, and set the vehicles individually into their own components.

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-c4d-desktop-env.jpg" alt="Desktop c4d environment" class="w-full">

The main game logic consist on generating on the fly vehicles components based on an interval increasing in speed. Each vehicles take some props that define its vehicle's version to pick as well as a lane to run on.

Vehicles animations are handled with Framer-Motion.

I handled the vehicles masking (when entering tunnels) using a single css image-mask.

For the rest, it's a matter of vehicles triggering their situation to a global game context.

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-context.jpg" alt="Fin de chantier React context" class="w-full">

This context is in charge of rendering the whole game status ('ready', 'gameover', 'in progress'...).

<img src="https://res.cloudinary.com/lansolo99/image/upload/c_fit,dpr_auto,q_auto,w_auto/lansolo.dev/posts/building-a-mini-casual-game-gameboard-component.jpg" alt="Fin de chantier Gameboard component" class="w-full">

### Next auth and Firebase

I decided to go with Next Auth and found pretty easy to set it, but I didn't make the Firestore adapter work properly (to get the user data part of the Next Auth context).

Instead, I juggled with both Next Auth and FireStore hooks to retrieve bound data given a user auth, when necessary, that is ugly and I'm well aware of it 🙁.

## Github Copilot

I didn't regret to get the Copilot subscription, that helped me in many ways. Sometimes, it misled me, especially providing obsolete import paths (from the Nextjs page router).

## Deployment

Not that much to say with Vercel that do an excellent job and eases the process, be it the subdomain binding, preview deployments, error logs...

## Wrapping up

To conclude, and as always, working on this kind of side project has been very fun and enriching. Seeing the ideas come to life is very satisfying, while being able to deliver it within a limited time frame.

It also help to underline which part of the process have to be improved, because I consider my codebase as pretty messy at the time, and that gives me a roadmap on what would be interesting to dig in.

## Demo

Here is the [playable game](https://findechantier.pommeclic.com/) of "Fin de chantier" (french version only). The contest run until next February 12th. I will then reopen the game without the contest part.

If interested, you can also play the still playable previous Svelte game called [Blackout](https://blackout.pommeclic.com/).

## Note

This post is also part of my personal blog [lansolo.dev](https://lansolo.dev/) where I share most of my experiments.