GitHub Pages is a great free resource for hosting unlimited static sites. You can build your Next.js app into a static site using Next’s export feature. There are a few features of Next.js you won’t be able to use with this, but in this article, I’ll talk you through deploying your app, and what you can and can’t do.

GitHub Actions

I’m going to start off with my basic Next.js template, but this should work with any Next.js app. GitHub actions provide a very simple method for generating a static site from your Next.js project and deploying it to GitHub Pages.

The first step is going to be setting your repo to use GitHub actions.

Simply go into the settings for your repo, into Pages, and select GitHub actions for the source. The url should be at: “https://github.com/<account>/<repo>/settings/pages”

The workflow for Next.js should be recommended, but just in case it isn’t you can select “Browse all workflows” to search for it.

Once you’ve selected the Next.js workflow, you should be greeted by a screen like this:

If you’re comfortable, feel free to change any values in the config, such as which branches trigger updates to your site.

Then go ahead and click start commit, and your workflow should be set up! Your site will start deploying whenever you next push your code.

Once your site is finished deploying, it should be accessible at “https://<username>.github.io/<reponame>/”, for example, you can find the one for this article at: https://upmostly.github.io/nextjs-github-pages/

Dynamic Content with GitHub Pages

Since we’re exporting our site as a static site with no server, there are a few things that are unavailable. Here’s the full list from Next.js

  • Image Optimization
  • Internationalized Routing
  • API Routes
  • Rewrites
  • Redirects
  • Headers
  • Middleware
  • Incremental Static Regeneration
  • fallback: true
  • getServerSideProps

The big ones you may need to worry about are API routes and getServerSideProps(). GitHub pages are serverless, so there’s no backend to serve API routes, or to provide server-side rendering. If you do need these, Vercel is another good option for hosting which supports these features.

We can however use Static Site Generation, which lets us generate the pages for our routes at build time. You can read more about that here, but I’ll showcase a quick example.

You can take a look at the full code for our page on GitHub, but all you need to know for this is that I’ve created a dynamic route, which takes a blog id as a parameter to load a blog post from a text file. To create a route for each blog post when we build our app, we first need to tell Next.js what routes to create, and what props to pass to each route.

export const getStaticPaths = async () => {
    //I have a folder containing blog posts in text files
    const paths = fs
        .readdirSync(path.join(process.cwd(), 'blog-posts'))
        .map((fileName) => fileName.split('.')[0]); //Just a quick map to remove the .txt from the filenames
    return {
        paths: paths.map((fileName) => {
            return { params: { blogPost: fileName } };
        }),
        fallback: false, //Means anything else will 404
    };
};

In my case this is simple. I’m storing all of my blog posts in a folder, so I just need to tell Next.js to build a page for every blog post in that folder.

Then in getStaticProps() we tell Next.js how to create the props for our page from the path:

export const getStaticProps: GetStaticProps = async ({ params }) => {
    //We get the filename as a parameter from the context object

    //fs is server side only, but this code only runs on the server
    if (!params) return { props: {} };
    const blogPost = fs.readFileSync(
        path.join(process.cwd(), 'blog-posts', params.blogPost + '.txt'),
        'utf8'
    );

    return {
        props: { blogPost }, // will be passed to the page component as props
    };
};

In my case, we just use the prop we’ve received to find load the blog post from a text file.

The actual blog post page component is simple, we just output the text file:

const BlogPost = ({ blogPost }: { blogPost: string }) => {
    return <div className="w-full p-5">{blogPost}</div>;
};

And here’s our finished product:

Check out the live version here. It’s a little basic, but we’ve got a static app with dynamic routes, all hosted for free!

Thanks for reading this article on deploying Next.js apps to GitHub pages. It’s a great free hosting solution for static sites, which perfectly suits a lot of use cases. You can also deploy React apps through this service, or any static website. If you liked this article, or if I helped you out, feel free to leave a comment below!

Avatar photo
👋 Hey, I'm Omari Thompson-Edwards
Hey, I'm Omari! I'm a full-stack developer from the UK. I'm currently looking for graduate and freelance software engineering roles, so if you liked this article, reach out on Twitter at @marile0n

💬 Leave a comment

Your email address will not be published. Required fields are marked *

We will never share your email with anyone else.