I’m Still Using Jekyll

Happy New Year 2026! Since migrating from Tumblr to Jekyll (and GitHub Pages) back in 2014, I have remained loyal to the same stack, now with the addition of @divriots/jampack at the end of the build chain.

Truthfully, I have tried many other SSGs: Hugo, Gatsby, Hexo, VuePress (or VitePress, I can’t recall which), Eleventy, Zola, Metalsmith, Lume, bashblog, and probably many others listed on Jamstack. At the end of the day, I always find myself thinking, “Jekyll just feels more comfortable.”

I can’t say Jekyll is perfect. Even now, my desire to have anchor headings remains unfulfilled. This issue has been open for over a year. I’m still conflicted about the implementation: should I use a Jekyll plugin, Node.js-based JavaScript, or just browser-side JavaScript? (To be honest, I hate the latter approach because I disable JavaScript on all my browsers).

When looking at other SSGs, implementing anchor headings seems so easy. Add a plugin, configure it, build, and voilà—anchor headings are done.

Initially, build optimization was also a struggle. There was jekyll-assets, which hashed every CSS, JS, and image file. This was great for ensuring that rapidly changing files wouldn’t clash with browser caches. In other SSGs, this feature is often built-in, especially in JavaScript-based ones like Eleventy, Gatsby, or Hexo.

Then there’s the issue of managing image files served to the end-user. Jekyll lacks a built-in feature for this, unlike other modern SSGs. With the advent of srcset, the <picture> element, WebP, and AVIF, I found myself wondering, “How can I get these features on my blog?”

Furthermore, there is the question of how to load CSS into HTML. The most aggressive way is to inline everything in the <head><style>...</style></head>. But when I tried this while using the Minimal Mistakes theme, the CSS actually outweighed the HTML markup. I also tried loading via JS using this.onload, but the FOUC (Flash of Unstyled Content) was far too obvious. :laughing:

The point is, I am someone who deeply values optimization, security, and privacy. A site should load fast, stay secure using current standards, and respect privacy—these are amazing things to prioritize.

After that long journey, I finally found @divriots/jampack.

Jampack is My Savior

Jampack serves one primary purpose: optimizing the files already built by an SSG. It handles inlining above-the-fold CSS, deferring JS files, generating hashed image names, creating WebP and AVIF versions (though AVIF can slow down build times), adding loading=lazy, and much more. You should check out their documentation.

For some reason, I feel Jampack doesn’t get the spotlight it deserves. Reducing the optimization hurdles inherent in many SSGs is a huge win.

I don’t use every single Jampack feature. My configuration is quite simple, leaving the rest to the defaults:

// jampack.config.mjs

const default_options = {
  html: {
    sort_attributes: true,
  },
  image: {
    external: {
      process: 'download',
    },
  },
  cdn: {
      process: 'on',
  },
};

export default default_options;

With just that config, my Lighthouse scores can hit 90+. I know you shouldn’t measure performance by Lighthouse scores alone, but it gives a good overview of the improvements gained just by adding Jampack.

Integrating Jampack does require additional setup if you aren’t using a Node.js-based SSG. Fortunately, Cloudflare Pages support both Ruby and nodejs, offers non-production build previews and 500 builds per month, which is more than enough for personal use. I can just use Github from a browser, write by myself or ask AI to generate code I want, test it on another branch, Cloudflare Pages build a preview of it, repeat.

Additionally, with the help of AI like Claude, Amazon Q Developer, Copilot, and Gemini, I can develop easily even from my phone (getting Jekyll to work in Termux is still hard to this day). Just remember: always check the code generated by AI. Not all of it is good; they can hallucinate, and their knowledge cut-offs mean they aren’t always up to date. So, always cross-check.

AI is great, provided you use it correctly.


To wrap things up, here is the changelog for the updates I’ve been working on gradually from December through mid-January, generated by Amazon Q. :smile:

January 2026 update changelog

Changelog

🎨 Theme Migration

  • Migrated from apropixyll to minima: Switched to Jekyll’s official minima theme for better maintainability
  • New homepage design: Created a custom profile landing page with clean button-style navigation links
  • Responsive styling: Implemented theme-aware CSS using minima’s native CSS variables for automatic dark/light mode support

🌐 Infrastructure Changes

  • Hosting migration: Moved from GitHub Pages to Cloudflare Pages (<akhyar.id> domain)
  • Enhanced security: Added comprehensive security headers including HSTS and frame protection
  • Optimized caching: Implemented intelligent caching policies for static assets vs dynamic content
  • Service Worker improvements: Enhanced offline functionality with better error handling and cache management

🔧 Configuration Updates

  • Streamlined dependencies: Removed unused plugins (jekyll-paginate, jekyll-github-metadata, jekyll-redirect-from)
  • Updated site metadata: Refreshed author information, social links, and SEO configuration
  • Modernized contact form: Rebuilt contact page with improved styling and AJAX submission via Formspree

📝 Content & Localization

  • Language migration: Translated primary content from Indonesian to English (some stuff still in Indonesian tho)
  • Updated navigation: Restructured site navigation with profile, contact, and privacy policy pages
  • Enhanced 404 page: Created custom styled 404 page matching the new theme
  • Redirect management: Implemented Jekyll-generated redirects for legacy URLs

🗂️ File Structure Changes

  • Removed legacy files: Cleaned up old theme files, JSONP endpoints, and unused configurations
  • Added new components: Custom header, favicon management, and theme customizations
  • Updated assets: New favicon set and web manifest for PWA support

This migration represents a complete modernization of the site architecture while maintaining content accessibility and improving user experience across devices and themes.


Thanks for reading. Bye~