GitHub

How to Deploy to GitHub Pages in Minutes

How to Deploy to GitHub Pages in Minutes

Free static site hosting, built directly into your existing workflow. That is what GitHub Pages offers, and most developers never fully use it.

Knowing how to deploy to GitHub Pages opens up a straightforward path to publishing portfolios, project documentation, and lightweight sites without touching a server or paying for hosting.

This guide covers everything you need: from the basic branch-based static site deployment to automated publishing with GitHub Actions, custom domain setup, and fixing the errors that trip people up most.

By the end, you will know exactly which deployment method fits your project and how to get your site live.

What Is GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

GitHub Pages is a free static site hosting service built directly into GitHub repositories. It reads HTML, CSS, and JavaScript files from a designated branch or folder and serves them publicly over HTTPS, with no server configuration required.

More than 90% of Fortune 100 companies use GitHub in their development workflows (SQ Magazine, 2025). GitHub Pages is one of the most widely used features for publishing project documentation, portfolios, and lightweight sites without any external hosting cost.

The default site URL follows the pattern username.github.io/repository-name. For user or organization sites tied to a repository named username.github.io, the site publishes directly at the root domain.

What GitHub Pages Does and Does Not Support

SupportedNot Supported
Static HTML, CSS, JavaScriptServer-side code (PHP, Node.js, Python)
Jekyll build pipelineDatabases or dynamic rendering
Custom domains with HTTPS via Let’s EncryptCommercial or high-traffic SaaS apps
GitHub Actions custom workflowsPrivate repositories on free accounts

The published site lives on a CDN. Changes after a git push propagate within 1 to 10 minutes depending on CDN cache state.

What Are the Requirements to Deploy to GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

You need 5 things before any deployment method will work. Missing any one of them causes the deployment to fail silently or produce a 404 after publishing.

  • A GitHub account (free tier works for public repositories)
  • A public repository (or a private one on GitHub Pro, Team, or Enterprise plans)
  • A static site output: plain HTML or a build folder from React, Vue, Jekyll, or similar
  • Git installed locally for CLI-based pushes
  • Node.js and npm if using the gh-pages package or framework build tools

Private repo hosting on GitHub Pages requires a paid plan. The free tier only publishes from public repositories, which means your source code is visible to anyone. For personal portfolios and open-source projects, that’s fine. For proprietary work, it’s worth noting before you start.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →

Account Plan Requirements at a Glance

GitHub Free: Public repositories only. GitHub Pages included.

GitHub Pro / Team: Public and private repositories both supported for Pages publishing.

GitHub Enterprise Cloud / Server: Full Pages support plus additional access control options.

How Does GitHub Pages Deployment Work?

GitHub Pages reads from a source you define: either a branch (typically main or gh-pages) or a /docs folder inside a branch. When you push a commit to that source, GitHub triggers a build and serves the output through its CDN.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

Jekyll runs automatically on any repository containing a config.yml file. If your project is not a Jekyll site, you need a .nojekyll file in the repository root to skip that processing step. Without it, Jekyll may ignore folders prefixed with underscores, like app or dist.

The Build and Serve Pipeline

GitHub’s pipeline runs in 3 stages after every push to the publishing source.

  1. Trigger: Push event detected on the configured branch or folder
  2. Build: Jekyll processing runs (or is skipped via .nojekyll); GitHub Actions workflow executes if configured
  3. Publish: Built files are pushed to GitHub’s CDN and served at the Pages URL

GitHub Pages has a soft limit of 10 builds per hour when deploying from a branch (GitHub Docs, 2024). That limit does not apply when using a custom GitHub Actions workflow, which makes Actions the better choice for teams pushing frequently.

The Fastly-backed CDN caches pages aggressively. If a deployment looks stuck, a hard browser refresh or cache-busting query string usually confirms whether the new build is live.

Source Options Compared

Source TypeBest ForBuild Limit Applies
Branch (main or gh-pages)Simple HTML sites, Jekyll projectsYes (10/hour)
/docs folderProjects with docs alongside source codeYes (10/hour)
GitHub Actions workflowReact, Vite, Vue, custom build pipelinesNo limit

How to Deploy a Static HTML Site to GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

Deploying plain HTML is the fastest path. No build step, no package manager, no workflow file. Just a repository with an index.html at the root.

GitHub Pages became the default choice for static project hosting partly because of this simplicity. The platform is used by millions of developers to publish documentation, landing pages, and portfolios directly from their existing repositories.

Deploying from the Main Branch

Steps:

  • Push your HTML, CSS, and JS files to the main branch with index.html at the root
  • Go to repository Settings, then Pages in the left sidebar
  • Under “Build and deployment,” set Source to “Deploy from a branch”
  • Select main branch and / (root) as the folder, then click Save
  • The live URL appears at the top of the Pages settings page within a few minutes

The site publishes at username.github.io/repository-name. No additional configuration needed.

Deploying from the /docs Folder

This option keeps source code and published files in the same branch without mixing them at the root level. Useful for projects where the site is one output among several.

Setup difference: Under Pages settings, set the folder to /docs instead of / (root). All site files must live inside /docs, including index.html.

One practical note: if your build tool outputs to a different folder (like /dist or /build), you’ll either need to rename it or use a GitHub Actions workflow instead. The branch-based approach only supports / (root) and /docs as source folder options.

How to Deploy a React or Vite App to GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

React and Vite apps need a build step before deployment. The gh-pages npm package handles this by pushing the compiled output directly to a gh-pages branch in your repository.

This is the most common approach for solo developers and small teams. Took me a while to figure out the routing issue the first time, but once you’ve done it once, it’s muscle memory.

Setting Up gh-pages in package.json

Install the package and configure 3 fields in package.json:

npm install --save-dev gh-pages `

Then add to package.json:

  • homepage: “https://username.github.io/repository-name”
  • predeploy script: “npm run build”
  • deploy script: “gh-pages -d build” (or -d dist for Vite)

Run npm run deploy. The package builds the app and pushes the output folder to the gh-pages branch automatically. In repository settings, set Pages source to the gh-pages branch.

For Vite projects, also set base in vite.config.js to ‘/repository-name/’. Without it, asset paths break in production.

Fixing Routing Issues on GitHub Pages

GitHub Pages does not support single-page application routing natively. Refreshing any route other than the index returns a 404.

There are 2 working fixes:

Option 1 (HashRouter): Replace BrowserRouter with HashRouter in your app. Routes become hash-based (#/about instead of /about). Simple but changes your URL structure.

Option 2 (404 redirect workaround): Add a custom 404.html to the public folder that redirects back to index.html with the original path encoded as a query string. A companion script in index.html reads that query string and restores the route. This keeps clean URLs intact.

For Vite specifically, setting basename={import.meta.env.BASEURL} in your BrowserRouter component resolves most path issues without changing the router type (Satyam Mishra, Medium, 2024).

How to Deploy to GitHub Pages Using GitHub Actions?

maxresdefault How to Deploy to GitHub Pages in Minutes

GitHub Actions handles the full build and publish pipeline automatically. Every push to main triggers the workflow. No manual deploys, no local build step required.

This is the right approach for any project with a build process, a team pushing frequently, or a site that needs to stay current without manual intervention. The continuous deployment setup also removes the 10 builds per hour limit that applies to branch-based deployments.

Writing the Workflow YAML File

Create .github/workflows/deploy.yml in your repository. The minimal working structure looks like this:

 name: Deploy to GitHub Pages

on: push: branches: [main] workflowdispatch:

permissions: contents: read pages: write id-token: write

concurrency: group: “pages” cancel-in-progress: false

jobs: build: runs-on: ubuntu-latest steps:

  • uses: actions/checkout@v4
  • uses: actions/setup-node@v4

with: node-version: ’20’

  • run: npm ci
  • run: npm run build
  • uses: actions/upload-pages-artifact@v4

with: path: ‘./dist’

deploy: needs: build runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.pageurl }} steps:

  • uses: actions/deploy-pages@v4

id: deployment 

The pages: write and id-token: write permissions are required for actions/deploy-pages to function (GitHub Docs, 2024). Missing either one causes the deploy job to fail with a permissions error.

Configuring Repository Permissions for Actions

After creating the workflow file, one setting change in the repository is required.

Go to: Settings > Pages > Build and deployment > Source

Set Source to “GitHub Actions” instead of “Deploy from a branch.” Without this change, GitHub ignores the workflow for Pages publishing.

The build pipeline runs on GitHub’s servers using ubuntu-latest by default. Build logs are visible under the Actions tab, which makes debugging failed deployments straightforward. Each run shows step-by-step output including install, build, artifact upload, and deploy stages.

Using the build-artifact and deploy-pages Actions

actions/upload-pages-artifact@v4 packages the build output into a compressed archive. The path parameter must point to the exact output folder your build tool generates. Common values:

  • Create React App: ./build
  • Vite: ./dist
  • Next.js static export: ./out
  • Jekyll: ./site

actions/deploy-pages@v4 handles the actual publish step. It reads the artifact uploaded by the previous job and deploys it. The two jobs must be linked with needs: build so the deploy job waits for the artifact to exist before running.

The source control integration means every deployment is tied to a specific commit. You can trace exactly which code version is live at any time directly from the Actions history.

How to Deploy a Jekyll Site to GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

Jekyll is the only static site generator with native GitHub Pages support. Push a repository containing config.yml to the source branch, and GitHub builds and publishes it automatically. No workflow file needed for basic sites.

The GitHub Pages gem bundles a specific set of dependencies. As of 2024, GitHub Pages runs Jekyll with the –safe flag, which disables all plugins except those on the official whitelist (Jekyll Docs, 2024). This is the most common surprise for developers coming from a local Jekyll setup with custom plugins.

Basic Jekyll Deployment Without Actions

What you need in the repository:

  • config.yml at the root (even a minimal one triggers Jekyll processing)
  • Markdown or HTML content files
  • A Gemfile referencing the github-pages gem to match the server environment locally

Set Pages source to the branch containing these files. GitHub handles the rest. The build output appears at your Pages URL within a few minutes of each push.

Supported plugins on GitHub Pages include: jekyll-sitemap, jekyll-feed, jekyll-seo-tag, jekyll-redirect-from, jekyll-paginate, jemoji, and jekyll-mentions (GitHub Pages dependency versions, 2024). Any plugin outside this list will silently fail or be ignored.

Using Custom Plugins via GitHub Actions

If your site needs unsupported plugins (jekyll-scholar, jekyll-picture-tag, custom Ruby gems), you need a GitHub Actions workflow to build the site yourself and push the output.

This approach bypasses the –safe restriction entirely. The workflow installs Ruby and Bundler, runs bundle exec jekyll build using your own Gemfile, and deploys the site folder as an artifact. Since March 2024, this is the standard pattern for Jekyll sites with pagination or any non-whitelisted functionality (josh.fail, 2024).

The workflow structure follows the same build + deploy job pattern from Section 6, with ruby/setup-ruby@v1 added before the build step. Set RUBYVERSION to match whatever is in your .ruby-version file.

Key tradeoff: Branch-based Jekyll deployment is zero-config but plugin-restricted. Actions-based deployment gives you full control but requires maintaining a workflow file and Ruby environment setup.

How to Connect a Custom Domain to GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

Connecting a custom domain takes two parallel steps: adding the domain inside repository settings and updating DNS records with your registrar. Both must be correct before HTTPS provisions.

DNS propagation takes anywhere from 5 minutes to 48 hours, with most providers updating within 2 hours (DNSPerf analytics, 2024). Starting the GitHub side first is the right order. Adding the custom domain in Settings before touching DNS prevents subdomain takeover attacks.

Setting Up an Apex Domain

Required DNS records (create all 4 A records at your registrar):

  • 185.199.108.153
  • 185.199.109.153
  • 185.199.110.153
  • 185.199.111.153

These point the apex domain (example.com) to GitHub’s CDN servers. After adding all 4, enter the domain in Settings > Pages > Custom domain and click Save.

GitHub creates a CNAME file in the repository root automatically. If you use a static site generator with a build step, that file gets overwritten on the next deploy unless you copy it into the build output folder before deploying.

Setting Up a Subdomain

Subdomain setup uses a CNAME record, not A records. Point www.example.com (or blog.example.com) to username.github.io at your DNS provider.

Apex domain: A records pointing to GitHub’s 4 IPs. Subdomain (www or custom): CNAME pointing to username.github.io.

Avoid wildcards like *.example.com. GitHub’s own documentation warns these create domain takeover risks even after domain verification.

Enabling HTTPS After Domain Setup

GitHub queues a Let’s Encrypt certificate request automatically after a successful DNS check. The “Enforce HTTPS” checkbox becomes available once the certificate is provisioned, which takes up to 1 hour in most cases (GitHub Docs, 2024).

If the checkbox stays greyed out past an hour, the 2 most common causes are:

  • Extra ALIAS or ANAME records conflicting with the A records
  • A CAA DNS record that doesn’t include letsencrypt.org as an allowed issuer

Removing and re-adding the custom domain in Settings re-triggers the provisioning job. That resolves most stuck certificates without needing GitHub support (GitHub Community, 2026).

Sites created after June 15, 2016 using github.io domains get HTTPS automatically, no configuration needed.

What Are the Limits and Constraints of GitHub Pages?

maxresdefault How to Deploy to GitHub Pages in Minutes

GitHub Pages has hard limits you need to know before committing to it as a hosting platform. Most personal and documentation sites stay well within them. Larger projects sometimes do not.

LimitValueNotes
Repository size1 GB recommendedSoft limit; larger repos may cause build issues
Published site size1 GB maximumHard limit on the deployed output
Bandwidth100 GB/month softGitHub may disable sites that consistently exceed this
Builds per hour10 (branch-based)No limit when using GitHub Actions workflows

What GitHub Pages Explicitly Prohibits

The Terms of Service are direct on this: GitHub Pages is not allowed for e-commerce sites, SaaS products, or any site primarily facilitating commercial transactions (GitHub Docs, 2024).

Prohibited uses specifically include:

  • Online stores handling payments or credit card data
  • Platforms that collect sensitive user credentials
  • High-traffic commercial applications expecting sustained heavy load

Portfolios, project documentation, open-source sites, and personal blogs all fit within the intended use case without issue.

Technical Constraints Worth Knowing

No server-side code execution. Full stop.

PHP, Node.js, Python, and databases are all off the table. GitHub Pages serves static files only. If your project needs an API backend or server-rendered pages, you need a different host or a backend service/) running elsewhere.

1 user or organization site per account. Project sites are unlimited, but the root username.github.io domain can only serve one repository per account.

Private repository Pages support requires GitHub Pro, Team, or Enterprise. Free accounts can only publish from public repositories. The published site is always public even when the source repository is private on a paid plan.

How to Troubleshoot Common GitHub Pages Deployment Errors?

maxresdefault How to Deploy to GitHub Pages in Minutes

Most GitHub Pages failures come down to 4 issues: wrong source settings, broken asset paths, Actions permission misconfigurations, and CDN cache delays. Each has a direct fix.

Understanding what GitHub does during the publish pipeline makes most errors obvious once you know where to look.

Fixing 404 Errors

A 404 after deployment almost always means one of these 3 things:

No index.html at root: GitHub Pages requires index.html at the root of the source folder. Files nested in subdirectories won’t serve automatically.

Wrong source branch or folder: Check Settings > Pages and confirm the source branch and folder match where your built files actually live.

Jekyll eating underscore-prefixed folders: Folders like app or _dist get ignored by Jekyll’s default processing. Add a .nojekyll file to the repository root to skip Jekyll entirely (GitHub Community Docs, 2024).

Fixing Asset Loading Issues

CSS and JavaScript files that load locally but 404 on GitHub Pages share one root cause: absolute paths that assume the site lives at / rather than /repository-name/.

GitHub Pages serves project sites under a subdirectory path. A stylesheet referenced as /styles.css resolves correctly at localhost:3000/styles.css but becomes a broken path at username.github.io/repository-name/styles.css.

3 ways to fix it:

  • Use relative paths in HTML (./styles.css instead of /styles.css)
  • Set the homepage field in package.json for React projects
  • Set base in vite.config.js to ‘/repository-name/’ for Vite projects

Fixing GitHub Actions Build Failures

The most common Actions failure for Pages deployments is a missing permissions block. When a workflow adds any permissions key, GitHub removes all default permissions except those explicitly listed.

A deployment job that includes pages: write and id-token: write but omits contents: read will fail at the actions/checkout step because the token can no longer read the repository (GitHub Community, 2023).

The full permissions block for a Pages workflow:

 permissions: contents: read pages: write id-token: write 

Also confirm that Settings > Pages has Source set to “GitHub Actions” and not “Deploy from a branch.” Running an Actions workflow without switching the source setting causes the deploy job to succeed but the site to never update.

Fixing Sites That Are Not Updating After a Push

CDN cache is the most common reason a live site shows old content after a successful deploy.

Quick check: Open the Actions tab and verify the workflow completed without errors. If it did, the new build is live. What you’re seeing in the browser is cached.

A hard refresh (Ctrl+Shift+R on Windows, Cmd+Shift+R on Mac) bypasses the browser cache. If the content still looks stale after that, the CDN layer may not have cleared yet. Wait 10 minutes and check again.

For branch-based deployments specifically, pushing to GitHub only triggers a new build if the push targets the exact source branch configured in Pages settings. Pushing to a feature branch while the source is set to main does nothing.

One last thing worth checking: if you recently renamed the repository, the Pages URL changes with it. Old bookmarks pointing to the previous URL return 404s until they’re updated.

FAQ on How To Deploy to GitHub Pages

Is GitHub Pages free to use?

Yes. GitHub Pages is free for all public repositories. Private repository publishing requires a paid plan: GitHub Pro, Team, or Enterprise. The free tier includes custom domain support, HTTPS via Let’s Encrypt, and 100 GB/month bandwidth.

How long does it take for GitHub Pages to go live?

Usually 1 to 10 minutes after a push to the source branch. CDN cache can make it appear slower. GitHub Actions deployments follow the same timeline once the workflow completes successfully.

Can I deploy a React app to GitHub Pages?

Yes. Install the gh-pages npm package, add a homepage field to package.json, and run npm run deploy. For Vite projects, also set the base option in vite.config.js to match your repository name.

What is the difference between deploying from a branch vs. GitHub Actions?

Branch-based deployment is simpler but limited to 10 builds per hour and only supports /root or /docs as source folders. GitHub Actions has no build limit and supports any build tool or output directory.

Why is my GitHub Pages site showing a 404 error?

Most 404 errors come from a missing index.html at the root, the wrong source branch set in Pages settings, or Jekyll silently ignoring underscore-prefixed folders. Adding a .nojekyll file to the repository root fixes the folder issue.

Can I use a custom domain with GitHub Pages?

Yes. Add 4 A records pointing to GitHub’s IP addresses for apex domains, or a CNAME record pointing to username.github.io for subdomains. Enter the domain in Settings > Pages. HTTPS provisions automatically via Let’s Encrypt within about an hour.

Does GitHub Pages support server-side code?

No. GitHub Pages serves static files only. PHP, Node.js, Python, and databases are not supported. If your project needs a backend, you need a separate hosting service or a cloud-based backend running elsewhere alongside the static site.

Why are my CSS and JavaScript files not loading after deployment?

The cause is almost always absolute asset paths. GitHub Pages serves project sites under /repository-name/, not /. Switch to relative paths or set the correct base URL in your build config. For React, update the homepage field in package.json.

How do I deploy to GitHub Pages using GitHub Actions?

Create .github/workflows/deploy.yml with pages: write and id-token: write permissions. Use actions/upload-pages-artifact to package the build output, then actions/deploy-pages to publish. Set Pages source to “GitHub Actions” in repository settings.

Can I use GitHub Pages for a commercial website?

No. GitHub’s Terms of Service explicitly prohibit using Pages for e-commerce, SaaS products, or sites that primarily facilitate commercial transactions. It is intended for personal sites, portfolios, open-source project pages, and documentation.

Conclusion

This conclusion is for an article presenting the full process of deploying to GitHub Pages, from a basic static site publish to automated GitHub Actions workflows and custom domain configuration.

The right deployment method depends on your project. Plain HTML sites work fine with branch-based publishing. React, Vite, and Jekyll projects with unsupported plugins need the Actions-based build pipeline.

Get your DNS records right before touching HTTPS. Most certificate provisioning failures come down to conflicting records, not GitHub itself.

Pages has real limits: no server-side execution, 100 GB/month bandwidth, and no commercial use. Work within them and it is a reliable, free static hosting option that integrates directly with your existing repository and source control workflow.

50218a090dd169a5399b03ee399b27df17d94bb940d98ae3f8daff6c978743c5?s=250&d=mm&r=g How to Deploy to GitHub Pages in Minutes

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.