Recently I revamped my open source version of 2048 Game and decided to migrate it to Next.js and React 18. The existing game was published to GitHub Pages without any custom domain. I was considering to deploy to Vercel but it would lose organic traffic from Google which was build up over the last 3 years. It means I needed to experiment with deployment to GitHub Pages and today I will share what i learnt.
If you want to see the end result of before reading the whole article, you canĀ
Quick Intro
I will be using two GitHub features ā GitHub Actions and GitHub Pages. If you haven't heard of them, let me quickly explain:
GitHub ActionsĀ are like little workflows that can do tasks on your projects. It's like having a helper that automatically does things you tell it to do. You can use Actions to run tests, for quality checks, or to build your application. In my case, I used this workflows to automate deployment pipeline.
What areĀ GitHub Pages? Think of them like a web hosting option for developers and open source projects. You can use GitHub Pages to share your portfolios, host websites of your open-source projects, or just publish your pet projects like mine.
Now let's get started.
Step 1 ā Activate GitHub Pages for Your Repository
To publish our Next.js application, I needed to activate GitHub Pages for the projectās repository. You can find in the Settings tab (1 in the image below), then selectĀ PagesĀ from the menu on the left-hand side (2), and find the dropdown menu that allows us to specify the deploymentĀ SourceĀ (3).
Now you will need to change the deploymentĀ SourceĀ toĀ GitHub Actions.
From now on, your project has a dedicated page. You only need to publish content there.
Step 2 ā Configure the Next.js Build Process
Before deploying the Next.js app, it's important to change the build output. By default, Next.js uses Node.js to run the application, and this is incompatible with GitHub Pages.
GitHub Pages is designed to host static files, which means we can publish only HTML, CSS, JavaScript (and other static files) there. So we'll need to enable static page generation in Next.js.
To do so, you will change the output mode toĀ export
Ā insideĀ next.config.js
:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "export", // <=== enables static exports
reactStrictMode: true,
};
module.exports = nextConfig;
Now after runningĀ next build
, Next.js will generate anĀ out
Ā folder containing static assets for your app. In the next steps, we will take this directory and upload it to GitHub Pages.
Step 3 ā Fix Missing Images
The Pages are published under a sub-path of a domain and takes the project name as a sub-path. Confusing? Let's take a sneak peak into a URL of my 2048 game as an example:
https://mateuszsokola.github.io/2048-in-react/
Github created a dedicated subdomain for my user calledĀ mateuszsokola (my username). But the project is published under the sub-path, which in my case isĀ /2048-in-react
. Unfortunately, this will lead to issues with missing images and styles.
By default, Next.js maps all static assets the domain. This means that theĀ favicon.ico
Ā file will be resolved toĀ mateuszsokola.github.io/favicon.ico
Ā instead ofĀ mateuszsokola.github.io/2048-in-react/favicon.icon
.
To fix this, we can set up a path prefix by addingĀ basePath
Ā inside theĀ next.config.js
Ā file:
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: "/2048-in-react", // <=== here it is
output: "export",
reactStrictMode: true,
};
module.exports = nextConfig;
In my case, it isĀ /2048-in-react
Ā since my project is calledĀ 2048-in-react
.
Remember to include the (/
) at beginning of the project directory.
Step 4 ā Create Github Actions
Next.js is producing deployment artifacts that can be published to GitHub Pages. Now it's due time to set up Github Actions to publish them. I decided the deployment into two separate actions to promote reusability:
The setup-node
Ā action will set up Node.js and instal all dependencies. Having a standalone action for the Node.js setup will allow me to reuse it for other pipelines. For example, I have pipelines that runĀ
The publish
Ā action will build Next.js artifacts and publish them to GitHub Pages each time we merge code into theĀ main
branch.
Let me begin by explaining theĀ setup-node
Ā action. Here is the code:
# File: .github/workflows/setup-node/action.yml
name: setup-node
description: "Setup Node.js āļø - Cache dependencies ā” - Install dependencies š§"
runs:
using: "composite"
steps:
- name: Setup Node.js āļø
uses: actions/setup-node@v4
with:
node-version: 20
- name: Cache dependencies ā”
id: cache_dependencies
uses: actions/cache@v3
with:
path: node_modules
key: node-modules-${{ hashFiles('package-lock.json') }}
- name: Install dependencies š§
shell: bash
if: steps.cache_dependencies.outputs.cache-hit != 'true'
run: npm ci
Important: Create this file in the Ā .github/workflows/setup-node
Ā directory in your project. Make sure to call it action.yml
.
What does this snippet do?
-
It creates aĀ
composite
Ā action. TheĀcomposite
Ā action allows you to bundle multiple workflow steps into a single action. If it isnāt clear you will understand it once we get into the second action. -
It creates a new build environment using Node.js 20 and installs project dependencies.
These are the most important parts of theĀ setup-node
Ā action. Now, let's move on to theĀ publish
action:
# File: .github/workflows/publish.yml
name: publish-to-github-pages
on:
push:
branches:
- main
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout šļø
uses: actions/checkout@v4
- name: Setup Node.js āļø - Cache dependencies ā” - Install dependencies š§
uses: ./.github/workflows/setup-node
- name: Setup Pages āļø
uses: actions/configure-pages@v4
with:
static_site_generator: next
- name: Build with Next.js šļø
run: npx next build
- name: Upload artifact š”
uses: actions/upload-pages-artifact@v3
with:
path: ./out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Publish to GitHub Pages š
id: deployment
uses: actions/deploy-pages@v4
Create this file in theĀ .github/workflows
Ā directory in your project. You can name the file as you like ā I called mineĀ publish.yml
.
What it does?
-
This action is triggered each time the new code is pushed or merged into theĀ
main
Ā branch. -
It uses theĀ
setup-node
Ā action to set up the environment. Thecomposite
action I created in the previous action. Now you know how to include yourcomposite
actions in other actions. -
The action has two stages: in the first stage, Next.js app is being built. In the second stage, the artifacts from the first stage are uploaded to GitHub Pages.
These are the most important aspects of the deployment pipeline. I skipped the permissions and concurrency setup since they remain unchanged for all GitHub Pages deployments.
Now, action is ready to use.
Commit and Push
After committing and pushing your changes to theĀ main
Ā branch, GitHub will automatically spin up the deployment to GitHub Pages.
To inspect the process, navigate to theĀ ActionsĀ tab (1 in the image below), and select theĀ publish-to-github-pagesĀ action from the menu on the left hand side (2).Ā You will see a all your deployments on the screen (they are calledĀ workflows).
Now select the first one of those workflows, and you will see a two-stage deployment. In theĀ deployĀ stage, you can find a link to your website on GitHub Pages.
Conclusion
Github Pages isn't sufficient for hosting websites with millions of views. But it's an perfect choice to host your portfolio or a website for your open-source project.
There are many free options to host our websites such as Vercel, but I wanted to show you an alternative. GitHub Pages is built for developers and I think every developer should be familiar with it.
If this article helped you, please share it on your social media.
And where do you deploy your application? Is it always Vercel?
Learn React 18 & Next.js
You donāt feel strong with React or Next.js? Join my online course on Udemy! I will help you to get started with React by creating a fully-functional 2048 Game. I believe creating games makes learning more fun, and you'll have something cool to show your friends.
šššš
š§āš Join