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 . check it here 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: 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. GitHub Actions What are ? 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. GitHub Pages 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 from the menu on the left-hand side (2), and find the dropdown menu that allows us to specify the deployment (3). Pages Source Now you will need to change the deployment to . Source 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 inside : export next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { output: "export", // <=== enables static exports reactStrictMode: true, }; module.exports = nextConfig; Now after running , Next.js will generate an folder containing static assets for your app. In the next steps, we will take this directory and upload it to GitHub Pages. next build out 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 . But the project is published under the sub-path, which in my case is . Unfortunately, this will lead to issues with missing images and styles. mateuszsokola (my username) /2048-in-react By default, Next.js maps all static assets the domain. This means that the file will be resolved to instead of . favicon.ico mateuszsokola.github.io/favicon.ico mateuszsokola.github.io/2048-in-react/favicon.icon To fix this, we can set up a path prefix by adding inside the file: basePath next.config.js /** @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 since my project is called . /2048-in-react 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 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 and . Probably you want to have more than one action as well. setup-node code linter tests The action will build Next.js artifacts and publish them to GitHub Pages each time we merge code into the branch. publish main Let me begin by explaining the action. Here is the code: setup-node # 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 : Create this file in the directory in your project. Make sure to call it . Important .github/workflows/setup-node action.yml What does this snippet do? It creates a action. The 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. composite composite It creates a new build environment using Node.js 20 and installs project dependencies. These are the most important parts of the action. Now, let's move on to the action: setup-node publish # 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 directory in your project. You can name the file as you like – I called mine . .github/workflows publish.yml What it does? This action is triggered each time the new code is pushed or merged into the branch. main It uses the action to set up the environment. The action I created in the previous action. Now you know how to include your actions in other actions. setup-node composite composite 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 branch, GitHub will automatically spin up the deployment to GitHub Pages. main To inspect the process, navigate to the tab (1 in the image below), and select the action from the menu on the left hand side (2) You will see a all your deployments on the screen (they are called ). Actions publish-to-github-pages . workflows Now select the first one of those workflows, and you will see a two-stage deployment. In the stage, you can find a link to your website on GitHub Pages. deploy 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 – 80% OFF only this week. React 18 and Next.js course on Udemy