I'm currently trying to deploy a Next.js app on GitHub Pages using GitHub Actions, but I get a page 404 error even after it successfully deploys. I've looked around a bunch of similarly named questions and am having trouble figuring this out.
I used the Deploy Next.js site to Pages workflow that GitHub provides. Here is the nextjs.yml
file:
# Sample workflow for building and deploying a Next.js site to GitHub Pages
#
# To get started with Next.js see: https://nextjs.org/docs/getting-started
#
name: Deploy Next.js site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["dev"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Build job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect package manager
id: detect-package-manager
run: |
if [ -f "${{ github.workspace }}/yarn.lock" ]; then
echo "manager=yarn" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=yarn" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/package.json" ]; then
echo "manager=npm" >> $GITHUB_OUTPUT
echo "command=ci" >> $GITHUB_OUTPUT
echo "runner=npx --no-install" >> $GITHUB_OUTPUT
exit 0
else
echo "Unable to determine package manager"
exit 1
fi
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: ${{ steps.detect-package-manager.outputs.manager }}
- name: Setup Pages
uses: actions/configure-pages@v4
with:
# Automatically inject basePath in your Next.js configuration file and disable
# server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
#
# You may remove this line if you want to manage the configuration yourself.
static_site_generator: next
- name: Restore cache
uses: actions/cache@v4
with:
path: |
.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build
- name: Static HTML export with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next export
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./out
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
I got this on the build step:
Route (app) Size First Load JS
┌ ○ /_not-found 875 B 81.5 kB
├ ○ /pages/about 2.16 kB 90.2 kB
├ ○ /pages/contact 2.6 kB 92.5 kB
├ ○ /pages/experience 2.25 kB 90.3 kB
├ ○ /pages/home 2.02 kB 92 kB
└ ○ /pages/projects 2.16 kB 90.2 kB
+ First Load JS shared by all 80.6 kB
├ chunks/472-0de5c8744346f427.js 27.6 kB
├ chunks/fd9d1056-138526ba479eb04f.js 51.1 kB
├ chunks/main-app-4a98b3a5cbccbbdb.js 230 B
└ chunks/webpack-ea848c4dc35e9b86.js 1.73 kB
○ (Static) automatically rendered as static HTML (uses no initial props)
Full image: Build with Next.js
I read in Next.js pages end in 404 on production build that perhaps it has something to do with having sub-folders inside the pages
folder, but I'm not sure how to fix that as I wasn't able to get it to work without sub-foldering page.js
files for each page.
EDIT: Here is my next.config.js
file:
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: '/pages',
output: 'export',
}
module.exports = nextConfig
EDIT: Removed github repo & website link as the issue has been resolved and they are no longer relevant to this particular question.
Your app is working and deploying properly, the only thing you are missing is a home route page.js
to be in app/page.js
, that is why you get a 404 on the /
route.
Check this link it is working: https://mctripp10.github.io/pages/home
But your current "home page is nested under /pages
. I suggest fully removing the /pages
route to get the desired behavior, also you need to modify your paths not to lead to /pages/about
, just to use /about
for example.
Your app
directory should look like this
//...root project ^
/app
page.js // <- your page.js from /pages/home should be here
layout.js // <- all of your pages will use this layout
/about // <- when deployed renders https://<<your.url>>/about
page.js
//... root project v
Next will route match pages and render them only if they are located in the app
directory.