Adding a sidebar to my pages
Lines shouldn’t be too long for reading comfortably (although…), but monitors are often very wide, so I thought using that space for some navigational elements would make a lot of sense. However, I have a few requirements:
- Build time: modifying the sidebar should be a constant-time operation.
- Page load time: the time until you can read the main content of the page should not be affected by the new sidebar.
- Progressive enhancement: this site should keep working without Javascript.
Requirement (1) rules out a purely static solution, otherwise I’d need to regenerate all my HTML pages1 from Markdown whenever the sidebar changes. Even with a fast static site generator (which my Makefile-Pandoc-Bash hack is not), this would get slower and slower over time.
Instead, I just generate a single sidebar fragment and include it in every page on the client side. Since iframe
s are ugly, this is done with the following Javascript snippet.
async function sidebar() {
const response = await fetch("/sidebar");
const sidebar = await response.text();
document.getElementById("sidebar").outerHTML = sidebar;
}
await sidebar();
This is included in each page as an inline module script. Module scripts are deferred automatically, so it doesn’t matter where we put the snippet above, it will load after the document has been parsed. The only downside is a tiny flicker because the sidebar appears shortly after the main content. To avoid unnecessary requests and save time, I set the HTTP Cache-Control
header to instruct the browser to cache the sidebar for one day2. On Cloudflare Pages, this can be done with a rule in the _headers
file.
/sidebar Cache-Control: public, max-age=86400
If a reader has Javascript disabled, they will simply not see any dynamically loaded sidebar. To allow these readers to navigate the site, each page now has a link to the home page at the top and the home page has a static sidebar with the full navigation3.
255 at the time of writing, not all of them publicly linked.↩︎
In case I change the sidebar, this means that it takes one day until all readers will see the new sidebar, but that’s fine.↩︎
Only the links to my virtual tag pages won’t work without Javascript.↩︎