DEV Community

Cover image for Modern Web App - Start of the Journey
François
François

Posted on

Modern Web App - Start of the Journey

Recently, I wanted to test a few technologies and use this excuse to start a new project around StarFinder as a support for my discovery journey 😄

This post and the next ones, are the documentation of this journey and, as such, are not a "tutorial" on starting a new project with nextjs, vitest or typescript but the sum of my findings and choices. See them as my "travel log"!

The Project

StarFinder

My goal is to implement a wizard to help in the character creation process for the tabletop role playing game StarFinder. A few solutions already exists but I found them lacking on the UI/UX part and I wanted to have a solution that guide the user while having a more modern look.

My github repo: https://github.com/superfaz/starfinder

  • First goal: Creation - A user should be able to create a level 1 character based on the official rule book extended with the character option book. As a result, he should have a proper character sheet (at least printed; potentially online) that he can use to play his character.

  • Second goal: Level-up - A user should be able to apply its level-ups and be guided in doing so (automatic updates and help provided to know what is authorized to him or not).

  • Third goal: Sharing - A user should be able to share its character sheets with other people and in particular Game Masters.

My (initial) Stack

My Stack

I wanted to do this project with the following key technologies:

  • typescript with swc for coding
  • nextjs to test its Server-Side Rendering capabilities
  • copilot in support as the project will be open-source
  • azure static web app for deployment

As the project moved forward this stack has evolved and I will give more details about those changes on later posts.

The First Step

My initial objective was to simply set-up the project, create the associated github space and prepare the release via github actions and azure static web app. And start to code my proof-of-concept.

During this process, I did a few interesting discoveries regarding node support on github and azure stacks:

  1. Github Actions Runners is using Node 18 per default (and not the 20 which is the latest LTS at the moment).

    Source: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md

    The following step can be added to a github action workflow to install the desired version:

      - name: Setup Node.js environment
        uses: actions/setup-node@v4
        with:
          node-version: "20.x"
    
  2. SWA deployment, based on Oryx, is using node 16 per default. That's indeed a strange choice. Oryx will read the package.json file of the project to determine the version of node to use based on the engine/node property:

    "engines": {
      "node": ">18.0.0"
    }
    
  3. SWA runner doesn't support node 20, even if the deployment allows it. You have to add a restriction on the same engines/node property:

    "engines": {
      "node": ">18.0.0 <20.0.0"
    }
    

    Sources: https://github.com/Azure/static-web-apps/issues/1349 and https://github.com/Azure/static-web-apps-cli/issues/756

Optimizing the workflow with Cache

In order to keep the Github Actions workflow running smoothly, adding some cache for yarn and nextjs was a mandatory step.

For nextjs, the configuration is straightforward and based on the official documentation:

Source: https://nextjs.org/docs/pages/building-your-application/deploying/ci-build-caching

      - name: Cache for Next
        uses: actions/cache@v3
        with:
          path: ${{ github.workspace }}/.next/cache
          key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
Enter fullscreen mode Exit fullscreen mode

For yarn, the official documentation extracts the path of the global cache before using actions/cache. I preferred to move the cache to a known location to simplify the configuration. Here is my set-up:

      - name: Setup Yarn
        run: |
          corepack enable
          yarn config set enableGlobalCache false
          yarn config set cacheFolder .yarn/cache

      - name: Cache for Yarn
        uses: actions/cache@v3
        with:
          path: ${{ github.workspace }}/.yarn/cache
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
Enter fullscreen mode Exit fullscreen mode

The Proof of Concept

While developing the first elements of the app with nextjs, it appears quite quickly that I will not exploit the Server-Side Rendering a lot at the beginning. As using Client rendering is required for a lot of user interactions.

A small configuration was required for the nextjs build to successfully being deployed as a SWA. In the next.config.mjs, I added the following:

  if (process.env.GITHUB_WORKFLOW) {
    // Configuration for Azure Static Web Apps
    console.log("Azure Static Web Apps configuration");
    return { ...standardConfig, output: "standalone" };
  } else {
    // Default configuration
    return standardConfig;
  }
Enter fullscreen mode Exit fullscreen mode

The POC was able to help the user to select a Race, a Theme and a Class while providing meaningful data about those choices (and sub-forms when needed).

This implementation was based on json files for the data. And it was quite clear for me that one of the next steps will be to extract those into a NoSQL data source.

Screenshot of the project
current status

Next step: Adding tests

The next post will be about the deployment of vitest for the project and why it was finally required to do a switch to jest.

Top comments (0)