nextjs-github-pages is a worked example of shipping a Next.js static export to Pages
🚀 Deploy a Next.js app to GitHub Pages via GitHub Actions
At a glance
- What is it?
- nextjs-github-pages is a small TypeScript project that documents, step by step, how to deploy a Next.js app to GitHub Pages with GitHub Actions: enable static exports, set a basePath, disable server-side image optimization, add a .nojekyll file and wire up a deploy workflow. It is MIT licensed and the deployed example is linked from the README.
- Who is it for?
- nextjs-github-pages suits a developer who wants a reference configuration rather than a reusable plugin, since the whole project is a working Next.js app plus a README that explains each setting, and the deploy.yml workflow is copied rather than abstracted.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What this project is: a template and its documentation
The repository's job is stated in its title and its description: deploy Next.js to GitHub Pages with GitHub Actions, and a view of the deployed app is linked from the README so you can see the result before reading a word.
What is actually in the repository is small. The top level holds an app/ directory, a public/ directory, next.config.ts, package.json, package-lock.json, tsconfig.json, eslint.config.mjs, postcss.config.mjs, a.github/ directory, a LICENSE and the README. That is a complete, minimal Next.js project, and its purpose is to be a template and a walkthrough at the same time.
The distinction from a library or a plugin matters. Nothing here is installed into your project. The configuration is copied into your repository, the workflow file is copied into your repository, and from that point on the configuration is yours. There is no package to upgrade and no version to track, which for a deployment recipe is arguably the right shape, since the things that break in this setup are the things Next.js changes between major versions.
The stack underneath is worth noting because it tells you which generation of Next.js the recipe targets. package.json pins next at ^16.3.8 with react and react-dom at ^19.3.0, and the dev dependencies include Tailwind CSS 4.3.3 through @tailwindcss/postcss, TypeScript 5.9.3, eslint 10.11.0 and eslint-config-next ^16.3.7. The scripts are the standard four: next dev, next build, next start and eslint.
The project is MIT licensed, the default branch is main, and the last push was on 2026-10-21. The releases tell a different story, with v15.1.0 from 2024-12-10, v14.1.0 from 2024-01-22, and a tag named pages_dir for the Pages Router from 2023-06-19, so the project has tracked Next.js major versions over time and the current configuration reflects a recent one.
The warning that comes before anything else
The first thing the README does is tell you where the boundary is, before it gives you any configuration.
GitHub Pages is not a Node.js server, so dynamic logic that cannot be computed during the build process is not supported, with a pointer to the Next.js documentation listing the unsupported features of static exports.
That warning is the whole constraint of this project and it is worth understanding rather than skimming, because a Next.js app that works locally will fail on Pages for reasons that have nothing to do with your deployment.
The distinction is between logic that runs at build time and logic that runs at request time. Anything that can be computed while the site is being built, including rendering a page from data fetched during the build, works. Anything that needs to run when a request arrives, including a server action, a dynamic route resolved per request, a request handler or middleware, does not.
That is why the configuration in this repository includes an option that looks unrelated to hosting and is in fact central to it. Next.js's image optimization runs on the server, and the server is a CDN serving files, so the images have to be served as-is.
The README's framing of what remains is a static site. That is what you get, and if a project needs a request-time capability the answer is a different host, not a different workflow file.
Configuring next.config.ts for a static export
The first configuration step is the Next.js config file, and the README gives the whole file with the comments intact, which is more useful than it sounds because each setting carries the reason it is there.
The file starts from the typed config import and the export of a NextConfig object, and the three settings that matter are output, basePath and images.
The output setting enables static exports:
output: "export",The basePath setting is the slug of your GitHub repository:
basePath: "/nextjs-github-pages",And the images setting disables the server-side optimization, because Next.js does not support dynamic features with static exports:
images: {
unoptimized: true,
},Each of those comments in the README links to the relevant Next.js documentation, which makes the file a set of pointers as much as a set of instructions.
The fourth step is the one people forget. Place a .nojekyll file in the /public directory, and the reason given is to disable GitHub Pages from trying to create a Jekyll website. GitHub Pages runs Jekyll by default on branch-based publishing, and Jekyll ignores files and directories whose names begin with the _ character, which is how it ends up dropping the Next.js output directories. The .nojekyll file tells Pages to publish the files as they are.
The README then shows the resulting layout as a tree, with the app directory, the public directory containing .nojekyll, and next.config.ts, and concludes that this is all you need to configure Next.js to deploy on GitHub Pages.
That is a fair claim for a static site, and the .nojekyll file is the piece that turns a working build into a working deploy.
Images need the base path too
There is a second configuration file to touch, and the reason is a consequence of the basePath setting rather than an independent requirement.
Next, you will need to add the base path to images in the page.tsx file. This is required for the images to appear on GitHub Pages.
The steps are to open app/page.tsx, find the Image components, and add /nextjs-github-pages/, or the slug of your GitHub repository, to the src prop:
<Image
src="/nextjs-github-pages/vercel.svg"
alt="Vercel Logo"
className={styles.vercelLogo}
width={100}
height={24}
priority
/>The reasoning is straightforward once you see it. The site is served from a subpath, gregrickaby.github.io/nextjs-github-pages, so a root-relative src of /vercel.svg resolves to the domain root and not to the site, and the image is a 404. Adding the prefix makes it resolve.
What is less obvious is that this only applies to the src of an Image and not to every path in the app. Next.js's basePath setting handles routing and asset resolution for the framework's own machinery, and the manual step is for the cases where you write the path yourself.
The README points at the official documentation for basePath and images at the end of that section, and the images documentation entry is the one that explains when the unoptimized setting and the manual prefix are needed together.
For a repository with a different name, two edits follow from the same rule: the basePath in next.config.ts and the prefix on every Image src in the app directory. Miss one and you get a page that renders with broken images, which is a less obvious failure than a build error.
The GitHub Actions workflow and enabling Pages
The deployment side has three steps, and the first one is the least convenient part of the whole recipe.
Create a .github/workflows/deploy.yml file, paste the contents of the workflow file from this repository's own .github/workflows/deploy.yml, and save it. The README describes this workflow file as the one that will automatically build and deploy the app when you push to the main branch.
The copying is the point. The README says this is where the magic happens, but the mechanism is a copy-paste from a reference repository, which means the workflow is yours to edit and yours to maintain. If Next.js changes how it emits its export, or GitHub changes its Pages actions, this workflow file is where you deal with it.
Enabling GitHub Pages is a settings change in the GitHub interface: go to your repository's Settings tab, click Pages in the sidebar, and under Build and Deployment select GitHub Actions as the source. The README includes a screenshot of that settings page, which is the kind of detail that saves a reader who has never seen the Pages source options, since GitHub Actions as the source is one of several choices and the others silently produce a different deployment model.
The last step is pushing, and the command is one line:
git add . && git commit -m "initial commit" && git pushThat triggers the workflow, and the README says you should see your site deployed to GitHub Pages in a few minutes.
The repository's own homepage is the deployed example of this exact configuration, so the whole recipe can be checked against a running site rather than only read.
Where nextjs-github-pages fits, and where it stops
The comparison worth making is with a hosting platform designed for Next.js, and with the general static site generators.
Against Vercel, the difference is what you give up and what you get. GitHub Pages is free hosting on a CDN with no Node.js runtime, and you get none of the dynamic Next.js features. Vercel runs the Next.js server, so the full feature set works, and it is the platform Next.js is built for. The argument for Pages is cost and the fact that the site lives in the same repository as the code with a workflow you read.
Against a static site generator such as Astro or a plain static site, the difference is that Next.js gives you the React component model and the App Router conventions, at the cost of the static export constraint. If your site is genuinely static, a generator designed for static output starts from a simpler place than Next.js configured away from its server features.
The limits are already stated. Anything dynamic is out. The basePath prefix has to be applied to image paths by hand, which is a class of bug that shows up as broken images rather than a failed build. The workflow file is copied rather than versioned, so you inherit it and its maintenance. And the pages_dir tag in the release history shows the project went through a Pages Router to App Router transition, which is a hint about how much Next.js's own configuration moves between majors.
What the project is genuinely good for is the reference. Each setting in next.config.ts is explained with a reason and a documentation link, the.nojekyll requirement is called out, the image prefix step is shown with the actual component, and the Pages source setting is screenshotted. For a developer doing this once, that is faster and less error-prone than reading Next.js deployment documentation and inferring the Next.js-specific parts.
The last push was on 2026-10-21 and the repository is not archived, so the configuration follows current Next.js, while the release tags remain on the older major versions.
Editorial conclusion
nextjs-github-pages suits a developer who wants a reference configuration rather than a reusable plugin, since the whole project is a working Next.js app plus a README that explains each setting, and the deploy.yml workflow is copied rather than abstracted. It is the wrong tool for anything dynamic, because GitHub Pages is not a Node.js server and the README is explicit that logic which cannot be computed during the build is unsupported, and it is the wrong tool if you want a maintained action, since the configuration is copied into your own repository and you own it from then on. Before you start, set basePath to your repository slug in next.config.ts, and remember that images need the same prefix in their src prop.
Frequently asked questions
What does nextjs-github-pages do?
It documents and demonstrates how to deploy a Next.js app to GitHub Pages using GitHub Actions. The repository is a minimal working Next.js project plus a README explaining the required configuration: static exports enabled in next.config.ts, a basePath set to the repository slug, server-based image optimization disabled, and a .nojekyll file placed in the public directory.
What do I need to change in next.config.ts to deploy to GitHub Pages?
Set output to "export" to enable static exports, set basePath to the slug of your GitHub repository, and set images.unoptimized to true because the server-side image optimizer cannot run on a static host. The README gives the full next.config.ts file with comments and links to the Next.js documentation for each option.
Why do I need a .nojekyll file?
Placing a .nojekyll file in the /public directory stops GitHub Pages from trying to create a Jekyll website, which matters because Jekyll ignores files and directories whose names begin with the _ prefix and would otherwise drop parts of the Next.js export.
Why do my images not appear on GitHub Pages?
Because the site is served from a subpath. The README says to open app/page.tsx, find the Image components and add /nextjs-github-pages/, or the slug of your GitHub repository, to the src prop, since a root-relative path resolves to the domain root rather than to the site.
How do I set up the GitHub Actions workflow for the deployment?
Create a .github/workflows/deploy.yml file and paste the contents of the workflow file from this repository, then in your repository Settings open Pages in the sidebar and select GitHub Actions as the source under Build and Deployment. Pushing to the main branch then triggers the build and deploy.
What can I not do with a Next.js site on GitHub Pages?
GitHub Pages is not a Node.js server, so dynamic logic that cannot be computed during the build process is not supported. The README points at the Next.js documentation listing the unsupported features of static exports, and the images.unoptimized setting exists for the same reason.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gregrickaby-nextjs-github-pages)Was this useful?