How to Add a Custom 404 Page to Your Jekyll Site
Create a custom 404 error page for your Jekyll site — with helpful navigation, search, and suggestions to keep visitors on your site instead of bouncing.
A default 404 page is a dead end. A custom 404 page turns a broken link into an opportunity — pointing visitors to your most popular content, your search page, or your homepage. In Jekyll, creating one takes about 5 minutes.
Step 1: Create the 404 File
Create 404.md or 404.html in your site root:
---
layout: page
title: "Page Not Found"
permalink: /404.html
sitemap: false
---
The filename must be 404.html for hosting platforms to serve it automatically. The permalink: /404.html ensures Jekyll outputs the file at the right path regardless of your global permalink setting.
sitemap: false prevents the 404 page from appearing in your sitemap.
Step 2: Write Helpful Content
A useful 404 page has three things: acknowledgment, navigation options, and ideally a search box.
---
layout: page
title: "Page Not Found"
permalink: /404.html
sitemap: false
---
The page you're looking for doesn't exist or may have been moved.
Here are some helpful links:
- [Home](/) — back to the homepage
- [Themes](/themes/) — browse Jekyll themes
- [Blog](/blog/) — read the latest posts
- [Search](/search/) — search the site
Or try searching for what you need:
Then add a search form at the bottom of the content (or in the layout).
Step 3: Build a Better 404 Layout
For a polished result, create a dedicated layout _layouts/404.html:
---
layout: default
---
<div class="error-page">
<div class="error-page__code" aria-hidden="true">404</div>
<h1 class="error-page__title">Page not found</h1>
<p class="error-page__message">
The page you're looking for doesn't exist or has been moved.
</p>
<div class="error-page__search">
<form action="/search/" method="get" role="search">
<label for="error-search" class="sr-only">Search the site</label>
<input type="search" id="error-search" name="q"
placeholder="Search for something..."
class="error-page__search-input"
autofocus>
<button type="submit" class="btn btn--primary">Search</button>
</form>
</div>
<nav class="error-page__nav" aria-label="Suggested pages">
<p>Or try one of these:</p>
<ul>
<li><a href="/">← Back to homepage</a></li>
<li><a href="/themes/">Browse themes</a></li>
<li><a href="/blog/">Read the blog</a></li>
<li><a href="/contact/">Contact us</a></li>
</ul>
</nav>
{% if site.posts.size > 0 %}
<div class="error-page__popular">
<h2>Popular posts</h2>
<ul>
{% for post in site.posts limit: 4 %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{{ content }}
Update your 404.md to use this layout:
---
layout: 404
title: "Page Not Found"
permalink: /404.html
sitemap: false
---
Step 4: Style It
// _sass/layouts/_404.scss
.error-page {
max-width: 540px;
margin: 4rem auto;
text-align: center;
padding: 0 1rem;
}
.error-page__code {
font-size: clamp(5rem, 20vw, 8rem);
font-weight: 900;
line-height: 1;
color: var(--border-color);
letter-spacing: -0.05em;
margin-bottom: 0.5rem;
}
.error-page__title {
font-size: 1.75rem;
margin-bottom: 0.75rem;
}
.error-page__message {
color: var(--text-muted);
margin-bottom: 2rem;
}
.error-page__search {
display: flex;
gap: 0.5rem;
margin-bottom: 2rem;
form {
display: flex;
gap: 0.5rem;
width: 100%;
}
}
.error-page__search-input {
flex: 1;
padding: 0.625rem 0.875rem;
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
font-size: 1rem;
background: var(--bg-color);
color: var(--text-color);
&:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
}
.error-page__nav {
text-align: left;
margin-bottom: 2rem;
ul {
list-style: none;
padding: 0;
margin: 0.5rem 0 0;
}
li {
padding: 0.25rem 0;
}
}
.error-page__popular {
text-align: left;
border-top: 1px solid var(--border-color);
padding-top: 1.5rem;
h2 {
font-size: 1rem;
margin-bottom: 0.75rem;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
padding: 0.2rem 0;
}
}
Step 5: Verify It Works on Your Hosting Platform
Different platforms serve custom 404 pages differently.
GitHub Pages
GitHub Pages automatically serves 404.html for missing pages. No configuration needed.
Netlify
Netlify serves 404.html automatically. Verify by visiting a non-existent URL on your live site.
Cloudflare Pages
Cloudflare Pages serves 404.html automatically.
Vercel
Add to vercel.json:
{
"routes": [
{ "handle": "filesystem" },
{ "src": ".*", "dest": "/404.html", "status": 404 }
]
}
Test it: Visit https://yourdomain.com/this-page-does-not-exist/ — you should see your custom 404 page, and the browser should show HTTP status 404 (not 200).
Auto-Suggest Based on URL
For extra polish, parse the URL to suggest relevant content:
// In your 404 layout
<script>
document.addEventListener('DOMContentLoaded', function() {
const path = window.location.pathname;
const slug = path.replace(/\//g, ' ').trim();
if (slug) {
// Pre-fill the search box with the attempted URL slug
const searchInput = document.getElementById('error-search');
if (searchInput) {
searchInput.value = slug.replace(/-/g, ' ');
}
}
});
</script>
This fills the search box with a cleaned version of the failed URL — so if someone visits /themes/minima-theme/ and gets a 404, the search box is pre-filled with “themes minima theme”.
What Makes a Good 404 Page
Do:
- Keep branding consistent (use your site’s header and footer)
- Offer clear navigation options
- Include a search box
- Show popular or recent content
- Keep the tone friendly, not apologetic
Don’t:
- Make it a dead end with only a “Go back” button
- Use generic error language (“Error 404: Not Found”)
- Remove the navigation bar
- Redirect to the homepage automatically (this confuses users and search engines)
A well-crafted 404 page recovers visitors who would otherwise leave. It’s one of the highest ROI improvements you can make in under an hour.
Browse Jekyll themes on JekyllHub — many include a pre-styled 404 page you can customise.