If you move a page on a Jekyll site, redirect the old URL before you remove it. A redirect preserves bookmarks and gives search engines a clear signal about the replacement page.
The best method depends on where the redirect is handled:
- Use a server-side redirect when you control the web server, reverse proxy, or hosting platform.
- Use jekyll-redirect-from when the redirect must be generated as part of a Jekyll build.
- Use a generated HTML fallback only when the host cannot provide either of those options.
GitHub Pages can build and publish Jekyll sites, but a repository does not give you access to Apache, Nginx, or another web server's redirect configuration. That distinction matters: a Jekyll plugin can generate a page that redirects in the browser, but it does not turn that page into an HTTP 301 or 302 response at the GitHub Pages edge.
Choose the redirect type first
Server-side redirects are the strongest option
If the old URL has moved permanently, configure an HTTP 301 or 308 redirect at the server, proxy, or hosting provider. A server-side redirect works before the old page is rendered and is the most reliable option for browsers, crawlers, caching, and non-browser clients. Google also recommends permanent server-side redirects when a page has moved permanently in its redirect guidance.
For example, an Apache configuration can use HTTPS for the destination:
Redirect permanent /oldlocation https://www.example.com/newlocation
Use a temporary redirect, such as 302 or 307, when the move is temporary. Do not use a permanent status merely because it is convenient; caches and search engines can retain that decision.
GitHub Pages repositories do not expose .htaccess, Nginx configuration, or a general redirect rules file. If you need a real HTTP redirect while keeping GitHub Pages for the site, put a service that supports redirects in front of it, move the site to a host that supports them, or configure the redirect at the platform handling the domain. See the GitHub Pages documentation and your hosting provider's current routing documentation before changing DNS.
Generated redirects are useful, but they are not HTTP redirects
When you cannot configure the server, a Jekyll plugin can generate an HTML document at the old path. The browser then follows a meta refresh or a link in that document. This is practical for GitHub Pages, but it is a fallback rather than an equivalent to a server-side 301.
Keep the destination stable and specific. Avoid redirect chains, redirecting many unrelated URLs to the home page, or sending a URL to a destination with a different purpose. Update links in your own site as well, so visitors do not have to pass through the old address.
Use jekyll-redirect-from with Jekyll
jekyll-redirect-from is the maintained Jekyll plugin for generating redirect pages. Its README documents both redirect_from for old URLs and redirect_to for a page that should point elsewhere.
Add the plugin to _config.yml:
plugins:
- jekyll-redirect-from
For a page that has moved from one or more old paths, keep the content at its new canonical location and list the old paths in the new page's front matter:
---
layout: default
title: New location
redirect_from:
- /oldlocation/
- /another-old-location/
---
This is usually the easiest pattern for a post or page that already exists at its new URL. The plugin generates redirect documents for the listed paths during the build. Keep the trailing-slash form consistent with the permalink structure used by your site.
To redirect a generated page to another location, use redirect_to:
---
layout: default
title: Page moved
redirect_to: /newlocation/
---
The plugin's generated output uses an instant HTTP-Refresh meta tag. That is why the result should be treated as a client-side fallback, not described as a server-side 301. If your site uses a custom Jekyll build rather than GitHub's supported build, add and test the gem in that build as well as the plugins entry. A successful local build does not by itself prove that the GitHub Pages build has loaded the plugin.
After adding the plugin, build the site locally and inspect the generated output:
bundle exec jekyll build
find _site -path '*oldlocation*' -type f -print
On Windows PowerShell, the equivalent check is:
bundle exec jekyll build
Get-ChildItem -Path _site -Recurse -File | Where-Object { $_.FullName -match 'oldlocation' }
Open the generated file and confirm that its destination, canonical URL, and fallback link are correct before deploying. Also check the published old URL after deployment; a repository build can succeed while a Pages configuration or custom domain points at a different artifact.
Build a manual HTML fallback only when needed
If a plugin cannot be used, create a generated page at the old permalink with a visible link to the destination. A zero-second meta refresh is preferable to a delayed redirect, but visitors must still be able to follow the link when refreshes are blocked.
For example, a redirect.html layout can be written as:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url={{ page.redirect_to | escape }}">
<link rel="canonical" href={{ page.redirect_to | escape }}>
<title>Page moved</title>
</head>
<body>
<p>
This page has moved.
<a href={{ page.redirect_to | escape }}>Continue to the new page</a>.
</p>
</body>
</html>
Then create a page that uses the layout:
---
layout: redirect
permalink: /oldlocation/
redirect_to: /newlocation/
---
The link is important for keyboard users, people who disable automatic refreshes, and clients that do not execute JavaScript. Do not make JavaScript the only way to reach the destination. If you add JavaScript as an enhancement, keep the normal link and pass the destination through a safe, escaped value.
Protect SEO and accessibility during a move
Before publishing the redirect:
- Make sure the destination is the closest equivalent page, not just a generic landing page.
- Update internal links, navigation, feeds, and any documentation that still points to the old URL.
- Use an absolute canonical URL when your deployment needs it, and verify that the canonical target is the same page as the redirect destination.
- Remove the old URL from the sitemap when the new page replaces it. The old URL may remain discoverable through the redirect, but it should not be advertised as a current page.
- Preserve important path variants, including a trailing slash or an old file extension, when those variants received traffic or external links.
- Test the old and new URLs from a clean browser session and with a command-line HTTP client. On a host that provides server-side redirects,
curl -Ishould show the expected 301, 302, 307, or 308 status. A GitHub Pages-generated fallback will normally return the HTML page with a successful response, so inspect the document as well as the browser behavior. - Remove or update the redirect after the old address is no longer needed, but keep permanent redirects long enough for external links and search indexes to catch up.
For a simple move from /oldlocation/ to /newlocation/, the decision is straightforward: configure a server-side permanent redirect if the platform allows it; otherwise generate a Jekyll redirect with redirect_from or redirect_to; and use a manual escaped HTML fallback only when the plugin is unavailable. This keeps the redirect understandable, testable, and usable without overstating what GitHub Pages can do.