How to Deploy a Website for Free Using GitHub Pages
GitHub Pages is one of the few free hosting services that has stayed free, fast, and dependable for years, which is why it hosts countless portfolios, documentation sites, and open-source project pages. GitHub Pages is a static site hosting service that takes HTML, CSS, and JavaScript files directly from a GitHub repository, optionally runs a build, and publishes the result to the web. Getting a basic page live takes minutes; getting it live correctly, with the right publishing source, working links, a custom domain, and HTTPS, is what this guide covers.
Quick Answer: To deploy a website with GitHub Pages, push your site files to a public GitHub repository, open Settings, then Pages, and choose a publishing source: a branch and folder, or a GitHub Actions workflow. GitHub builds and publishes the site at username.github.io. Add a custom domain and enable Enforce HTTPS in the same settings page.
What GitHub Pages Can and Cannot Host
GitHub Pages can host any website made entirely of static files, but it cannot run server-side code such as PHP, Node.js servers, or databases. Understanding that boundary up front prevents the most frustrating deployment surprises.
Static means the server simply sends files as they are. Your HTML, stylesheets, images, and JavaScript bundles qualify, and so does the built output of tools like Vite, Astro, Hugo, Eleventy, or Jekyll. A React or Vue single-page app works too, as long as it fetches any dynamic data from an external API. If your project needs a real back end, compare other free hosts worth comparing that can run server code.
There are two kinds of Pages sites. A user or organization site lives in a repository named exactly username.github.io and publishes at the root of that address. A project site lives in any other repository and publishes at username.github.io/repository-name. That subpath matters: it is the reason many framework builds show a blank page with broken asset links, which we fix later in this guide.
GitHub's documentation also sets usage expectations. Published sites may be no larger than 1 GB, sites have a soft bandwidth limit of 100 GB per month, and GitHub Pages is not intended to run online businesses, e-commerce stores, or SaaS products. On GitHub Free, Pages is available for public repositories; publishing from private repositories requires a paid plan.
Step-by-Step: Publishing Your First Site
Publishing a plain HTML site takes a handful of steps and no build tools. Follow them in order the first time, even if you plan to use a framework later.
- Create a repository. For a personal site, name it
username.github.iousing your exact GitHub username. For a project, any name works. Make it public. - Add an index.html file. GitHub Pages serves
index.htmlas the home page. Name it exactly that, in lowercase, at the root of your publishing folder. - Commit and push. Use the web uploader for a first test, or
git add,git commit, andgit pushfrom your machine. - Open Settings, then Pages. Under Build and deployment, set the Source to Deploy from a branch, choose
main, and select either the root folder or/docs. - Wait for the deployment. Open the Actions tab to watch the pages-build-deployment workflow. When it finishes, the Pages settings show your live URL.
- Visit and verify. Load the site in a private window to avoid cached results, and click every link to confirm paths work.
- Add a custom 404 page. Create a
404.htmlfile at the root so broken links show a helpful page instead of GitHub's default.
If your site does not use Jekyll, add an empty file named .nojekyll at the root. Without it, branch-based publishing runs your files through Jekyll, which ignores folders starting with an underscore, a common cause of missing assets from some build tools.
Branch Publishing vs GitHub Actions
GitHub Pages offers two publishing sources, and choosing the right one depends on whether your site needs a build step. Both are free and both produce the same kind of site.
| Factor | Deploy From a Branch | GitHub Actions Workflow |
|---|---|---|
| Best for | Plain HTML sites and Jekyll sites | Vite, React, Vue, Astro, Hugo, and other built sites |
| Build step | None, or Jekyll only | Any build command you define |
| Committed files | The finished site lives in the repo | Only source code; build output is generated |
| Setup effort | A settings change | A workflow YAML file, often from a starter template |
| Control over versions | Limited to GitHub's Jekyll setup | Full control of Node, Ruby, or Go versions |
For anything built with a modern framework, use GitHub Actions. Committing build output to a branch works, but it clutters history, invites merge conflicts, and makes it easy to deploy a stale build. GitHub provides starter workflows for common static site generators in the Pages settings, and they use the official upload and deploy Pages actions.
Custom Domains and HTTPS: What Actually Happens
Adding a custom domain to GitHub Pages is a DNS change on your side and a settings change on GitHub's side, after which GitHub issues a free certificate. This section explains the moving parts so you can debug them, based on GitHub's documented setup.
For a subdomain such as www.example.com, create a CNAME record at your DNS provider pointing to username.github.io. For an apex domain such as example.com, create A records pointing to GitHub's published IP addresses: 185.199.108.153, 185.199.109.153, 185.199.110.153, and 185.199.111.153. GitHub also documents AAAA records for IPv6. Then enter the domain in Settings, Pages, Custom domain. With branch publishing, GitHub commits a CNAME file to your repository; with Actions, the setting alone is used.
Once DNS resolves correctly, GitHub requests a certificate automatically, and the Enforce HTTPS checkbox becomes available. The checkbox redirects every HTTP request to HTTPS, which you always want. If the box stays disabled, DNS is usually still propagating or a record is wrong. To understand what the certificate is doing behind the scenes, read up on how HTTPS certificates work and why they renew automatically.
One security step many tutorials skip: verify your domain in your GitHub account settings. GitHub recommends this because it prevents someone else from claiming your domain on their own Pages site if your configuration is ever removed while DNS still points at GitHub.
Common GitHub Pages Mistakes and Fixes
Most failed GitHub Pages deployments come from a short list of configuration mistakes rather than outages. Work through these before assuming something is broken on GitHub's end.
- Blank page with a framework build. The site is a project site served from a subpath, but assets load from the root. In Vite, set
base: '/repository-name/'in the config; other frameworks have equivalent base path settings. - Page refresh returns 404 in a single-page app. GitHub Pages has no server-side rewrites. Use hash-based routing, or copy
index.htmlto404.htmlduring the build so unknown paths still load the app. - Wrong file name casing. Links to
About.htmlfail if the file isabout.html. Pages runs on case-sensitive servers even if your laptop does not. - Underscore folders missing. Jekyll skipped them. Add
.nojekyllor use the Actions source. - Custom domain resets after each deploy. With branch publishing, the
CNAMEfile was deleted by your build. Place it in the folder that gets published, such aspublicin Vite. - Mixed content warnings. Images or scripts load over
http://. Change them tohttps://or relative paths. - Secrets in client code. Anything deployed to Pages is public. Never place API keys in front-end files.
- Old version still showing. Browser and CDN caching can delay updates briefly. Check the Actions tab for the latest successful run, then hard refresh.
Walkthrough: Deploying a Vite Project With GitHub Actions
Deploying a Vite-based project is the most common real-world GitHub Pages task. This walkthrough assumes a working Vite app on your machine and a repository named portfolio.
Step 1: Set the base path. In vite.config.js, add base: '/portfolio/'. If you will use a custom domain or a username.github.io repository, keep the base as '/' instead.
Step 2: Confirm the build locally. Run npm run build and then npm run preview. If the preview works with the base path, the deployed site almost always will.
Step 3: Choose GitHub Actions as the source. In Settings, Pages, set Source to GitHub Actions. GitHub suggests workflows; the static HTML starter can be adapted, or you can write your own.
Step 4: Add the workflow. Create .github/workflows/deploy.yml that runs on pushes to main, checks out the code, sets up Node.js, runs npm ci and npm run build, uploads the dist folder with the upload-pages-artifact action, and deploys it with the deploy-pages action. The workflow needs pages: write and id-token: write permissions.
Step 5: Push and watch. Commit the workflow and push. The Actions tab shows build and deploy jobs; the deploy job prints the live URL.
Step 6: Handle client-side routing. If you use React Router or Vue Router with history mode, add a build step that copies dist/index.html to dist/404.html.
Step 7: Add the custom domain. Create the DNS records, enter the domain in Pages settings, wait for the certificate, then enable Enforce HTTPS and switch the Vite base back to '/'.
Step 8: Protect the main branch. Since every push to main deploys, require pull requests for changes. This keeps a broken commit from taking your site down.
Key Takeaways
- GitHub Pages hosts static files only, so any project that needs server code or a database must pair it with another service.
- Branch publishing suits plain HTML and Jekyll, while GitHub Actions is the right source for any framework with a build step.
- Project sites live under a repository subpath, which is why framework builds need a matching base path setting.
- Custom domains need correct DNS records first; the free certificate and Enforce HTTPS option follow automatically.
- Verifying your domain in GitHub account settings protects it from being claimed by someone else's Pages site.
Frequently Asked Questions
Is GitHub Pages really free?
Yes, GitHub Pages is free for public repositories on a GitHub Free account, including custom domains and HTTPS certificates. Publishing from a private repository requires a paid GitHub plan. Usage is subject to documented limits on site size and monthly bandwidth, which most personal sites never approach.
Can I use GitHub Pages for a business website?
You can host a simple informational site, but GitHub states that Pages is not intended for running online businesses, e-commerce stores, or SaaS products. A brochure site for a small business is generally fine. Anything selling products or handling transactions should use a host designed for commercial use.
How long does GitHub Pages take to update?
Most updates go live within a minute or two after the deployment workflow completes. Check the Actions tab to see whether the latest run succeeded. If the change still does not appear, browser or CDN caching is usually responsible, so try a private window or a hard refresh.
Why does my GitHub Pages site show a 404 error?
A 404 usually means there is no index.html in the publishing folder, the wrong branch or folder is selected, or file names differ in letter case. For single-page apps, refreshing a deep link causes 404s because Pages lacks rewrites; copying index.html to 404.html during the build fixes it.
Can GitHub Pages run PHP or a database?
No, GitHub Pages only serves static files, so PHP, Node.js servers, and databases will not run there. You can still add dynamic features by calling external APIs from JavaScript, using a hosted form service, or connecting a separate back end hosted on a platform that supports server code.
Do I need to know Git to use GitHub Pages?
No, you can upload files through GitHub's web interface and publish without touching the command line. Learning basic Git commands is still worthwhile, because pushing changes from your computer is faster, keeps a clear history, and makes GitHub Actions deployments far easier to manage.
Conclusion
The key decision with GitHub Pages is matching the publishing source to your project: branch publishing for plain files, GitHub Actions for anything with a build step, and a correct base path either way. Get that right and you have free, fast hosting that deploys on every push. With the site live at a github.io address, your next step is pointing a custom domain at your site so it has a permanent, professional address.




