GitHub Pages: 3 Hacks for Clean Subdirectory URLs 2025
Tired of ugly .html URLs on your GitHub Pages site? Learn 3 simple to advanced hacks for 2025 to get clean, professional subdirectory URLs. Boost your SEO and UX today!
Alex Carter
A front-end developer and tech writer passionate about clean code and simpler workflows.
Let’s be honest. You’ve just built a beautiful, fast, and free website using GitHub Pages. You’re proud of your work, you’ve pushed your final commits, and you’re ready to share it with the world. You send the link to a friend: your-username.github.io/about.html
. They click it, and that ugly .html
extension just hangs there at the end of the URL, mocking your otherwise pristine creation.
We’ve all been there. In a world of clean, semantic web design, file extensions in URLs feel like a relic from a bygone era. They’re not just an aesthetic annoyance; they make URLs harder to remember, less professional to share, and can even have minor impacts on SEO. Fortunately, reclaiming your URL sanity on GitHub Pages is easier than you think. You don’t need to switch hosting providers or pull your hair out with complex server configurations.
This post is your definitive guide for 2025. We’ll walk through three distinct hacks—from dead-simple to powerfully automated—to achieve those clean, beautiful subdirectory URLs (like /about/
) on your GitHub Pages site. Let’s dive in and clean things up.
Why Clean URLs Matter (A Quick Refresher)
Before we get into the “how,” let’s quickly touch on the “why.” Why bother with this at all?
- User Experience (UX): Clean URLs are easier for humans to read, type, and remember.
/services/consulting/
is far more intuitive than/services_consulting_page.html
. - SEO Benefits: While not a massive ranking factor, search engines prefer well-structured, keyword-rich URLs. A clean structure helps search engine crawlers understand your site's hierarchy.
- Future-Proofing: What if you switch from a static HTML site to a WordPress site or another CMS? A URL like
/about/
can be maintained. A URL like/about.html
reveals your underlying technology and can be harder to migrate without redirects. - Professionalism: It’s a small detail, but it signals quality and attention to detail.
Hack 1: The Classic "index.html" Folder Method
This is the original, most straightforward, and universally compatible method. It relies on a fundamental behavior of virtually all web servers: when you request a directory, the server automatically looks for and serves a default file, which is almost always index.html
.
How it Works
Instead of having a file named about.html
in your root directory, you create a folder named about
. Inside that folder, you place your HTML file and rename it to index.html
. That’s it! When a user visits your-site.com/about/
, the server sees the /about/
directory and serves the index.html
file within it.
Step-by-Step Guide
Let's say your project structure looks like this:
your-repo/
├── index.html
├── about.html
└── contact.html
To get clean URLs, you would change it to this:
your-repo/
├── index.html
├── about/
│ └── index.html
└── contact/
└── index.html
Now, the following URLs will work perfectly:
your-username.github.io/
will serve the rootindex.html
.your-username.github.io/about/
will serveabout/index.html
.your-username.github.io/contact/
will servecontact/index.html
.
Pros & Cons
- Pros: Foolproof, requires no configuration, works with any static site (plain HTML, or any generator), and is easy to understand.
- Cons: It’s a manual process. For a site with many pages, creating folders and renaming files can become tedious. It can also make your local project directory feel a bit more cluttered.
Hack 2: The Jekyll Permalink Power-Up
Did you know that GitHub Pages has a secret weapon? By default, it runs your site through Jekyll, a powerful static site generator. Even if you don't think you're using Jekyll, if you have a bunch of Markdown or HTML files, GitHub is using Jekyll behind the scenes. We can leverage this to automate our clean URL creation.
The Magic of _config.yml
Jekyll is controlled by a configuration file in your root directory called _config.yml
. By adding a single line to this file, you can tell Jekyll how to structure your URLs (which it calls “permalinks”).
Step-by-Step Guide
- Create the Config File: If you don’t already have one, create a file named
_config.yml
in the root of your repository. - Add the Permalink Setting: Open the file and add the following line:
permalink: pretty
- Commit and Push: Save the file, commit it, and push it to your GitHub repository.
That's it! Jekyll will now automatically take a file like about.md
or about.html
and build it as /about/index.html
behind the scenes. You don't have to change your file structure at all. Your project directory stays clean and flat, while your live site has beautiful, clean URLs.
You can also get more advanced. For example, if you organize posts in subdirectories, you could use permalink: /:categories/:title/
to include categories in the URL.
Pros & Cons
- Pros: Fully automated, “set it and forget it,” keeps your source directory clean, and offers powerful customization options.
- Cons: This method requires you to use Jekyll's build process. If you're using a different static site generator (like Hugo or Eleventy) or want to disable Jekyll, this won't work.
Hack 3: The Modern Workflow with GitHub Actions
What if you're using a modern JavaScript-based SSG like Next.js, Eleventy, or Astro? Or maybe you just have a build step you need to run. In these cases, you often disable the default Jekyll build. This brings back the ugly .html
problem. The solution? A custom build and deployment process using GitHub Actions.
How It Works
GitHub Actions allows you to define a custom CI/CD (Continuous Integration/Continuous Deployment) pipeline. We can create a workflow that does the following every time we push to our main branch:
- Builds our static site (e.g., runs
npm run build
). - Takes the output (usually in a
dist
orbuild
folder). - Renames the files to create the clean directory structure from Hack #1 automatically.
- Deploys the final, modified files to GitHub Pages.
Step-by-Step Guide
-
Disable Jekyll: Create an empty file named
.nojekyll
in the root of your repository. This tells GitHub Pages not to run Jekyll and to just serve the files as-is. -
Create a Workflow File: Create a directory path
.github/workflows/
in your repository. Inside, create a new file, e.g.,deploy.yml
. -
Define the Workflow: Paste the following configuration into
deploy.yml
. This example assumes your build command isnpm run build
and the output is in a/build
directory.name: Build and Deploy to GitHub Pages on: push: branches: [ "main" ] # Or your default branch jobs: deploy: runs-on: ubuntu-latest permissions: contents: read pages: write id-token: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm install - name: Build static site run: npm run build # Your build command - name: Rename HTML files for clean URLs run: | find build -type f -name "*.html" | while read file; do if [[ "$file" != *"index.html"* && "$file" != *"404.html"* ]]; then mkdir -p "${file%.html}" mv "$file" "${file%.html}/index.html" fi done - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: ./build # Your build output directory - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4
- Configure Pages Settings: In your repository settings under "Pages," set the "Build and deployment" source to "GitHub Actions."
Now, every push to `main` will trigger this action, building your site and automatically restructuring the files before deploying. You get full automation with any tool you want.
Pros & Cons
- Pros: The most flexible and powerful method. Works with any static site generator or build process. Fully automates the entire workflow.
- Cons: The most complex to set up. Requires a basic understanding of YAML and CI/CD concepts. Can feel like overkill for a very simple site.
Comparison: Which Hack Is Right for You?
Still not sure which path to take? This table breaks it down for you.
Feature | Hack 1: Folder Method | Hack 2: Jekyll Permalinks | Hack 3: GitHub Actions |
---|---|---|---|
Ease of Setup | Very Easy | Easy | Moderate |
Automation | None (Manual) | Fully Automatic | Fully Automatic |
Flexibility | High (Works with anything) | Low (Jekyll only) | Very High (Works with anything) |
Best For... | Simple HTML sites, beginners | Blogs, Jekyll-based sites | Modern SSGs, complex projects |
Conclusion: Clean URLs Are Within Reach
There you have it—three battle-tested methods to banish .html
from your GitHub Pages URLs forever. No matter your technical comfort level or project complexity, a solution exists for you.
- For the beginner or a simple project, the manual folder method is a quick and effective fix.
- For the blogger or Jekyll enthusiast, enabling pretty permalinks is a no-brainer.
- For the modern developer using the latest tools, mastering GitHub Actions provides ultimate power and flexibility.
Clean URLs are a small but significant detail that elevates your project from a simple repository page to a professional-looking website. So go ahead, pick the hack that fits your workflow, push your changes, and enjoy the satisfaction of a clean, polished URL. Happy coding!