Beautify URLs in Jekyll

Jekyll can hide the .html extension by rewriting paths like /dir/file.html to /dir/file/index.html and then letting the webserver’s “default index” feature do the work. If you don’t want to use this (arguably dirty) trick you can produce extension-free URLs of normal HTML files yourself and let your webserver handle the rewrite.

Liquid filters

For removing file extensions from our site’s URLs we create a new Liquid filter in Jekyll’s plugin directory.

module Jekyll
	module URLBeautifier
		##
		# Remove ending "index.html" or ".html" if present.
		def beautify_url(url)
			beautify_resource(beautify_directory(url))
		end

		##
		# Remove ending "index.html" from urls.
		def beautify_directory(url)
			if url =~ /index\.html$/
				url = url[0..-11]
			end
			url
		end

		##
		# Remove ending ".html".
		def beautify_resource(url)
			if url =~ /\.html$/
				url = url[0..-6]
			end
			url
		end
	end
end

Liquid::Template.register_filter(Jekyll::URLBeautifier)

Usage:

<a href="{{ page.url | beautify_url }}">{{ page.title }}</a>

Serve locally

Removing the file extension from URLs breaks the website as the default Jekyll web server cannot handle rewrites. We could install a production-ready one but that would be overkill.

Instead, you can download a webserver Python script for developing here (ugly code inside). You can set DOCROOT and PORT in lines :3 and :4. It is compatible with both Python version 2 and 3.

Use Jekyll to build your files (jekyll build -w) and the script to serve them.

Serving with Nginx

For production use I here show an example server directive for Nginx.

server {
	listen 80;
	listen [::]:80;
	server_name example.com;

	location / {
		root /usr/local/www/example.com/www;

		# Don't try to rewrite files with extension.
		if ($uri ~* ".+\.[a-z0-9]{1,4}") {
			break;
		}
		
		# Try with '.html' extension if otherwise not found.
		try_files $uri $uri/ $uri.html;
	}
}
First published on September 6, 2014