11ty logo

Eleventy seems really popular among web technology blogs so I wanted to give it a proper chance by attempting to move my blog to it.

I have been thinking of redesigning my blog for a while & maybe even moving away from Gatsby.

I wanted to use a good starting point for the blog so am using the official starter eleventy-base-blog.
This starter has a lot of features but also will hopefully allow me to learn & extend 11ty.

11ty/eleventy-base-blog on github

First Steps #

I did a few things to setup the initial workflow.

Prettier Options #

  arrowParens: 'always',
  printWidth: 80,
  singleQuote: true,
  jsxSingleQuote: false,
  semi: false,
  trailingComma: 'es5',
  tabWidth: 2,
  bracketSpacing: true,
  endOfLine: 'lf',

11ty-equk/.prettierrc.js on github (Jun 10, 2023)

First Problem #

The first problem I came across related to using pnpm.
eleventy-base-blog references css from a path in node_modules.

{%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %}

This was easily fixed by copying the css to the project & fixing the references to it.

Modifying Slug #

Before adding any css styles or messing with the templates or layout etc I thought I'd try generating post slugs using date & title from frontmatter in posts.

This was a lot easier than I thought it would be.

📝Generating Slug Using Date & Title In 11ty

Restructuring Folders #

I decided to structure the project a bit different to the default setup.
Having a src folder makes things a lot easier to work with.

└── public
└── src
    ├── _assets
    ├── atom
    ├── _data
    ├── _includes
    ├── _media
    ├── pages
    ├── posts
    ├── _scripts
    ├── sitemap
    └── _styles

Some added features also meant adding folders.
src/_media/images is used for image storage for image optimization.
src/_assets/js is esbuild optimized javascript output.
src/_assets/css is postcss optimized css output.

Adding Tailwindcss #

Most references suggest using npm-run-all to run 11ty & tailwindcss.
This comes with a few problems, especially if you are using inlined css.

Building is ok as you can run it sequentially but in dev mode things really don't work well as 11ty is trying to reference generated css at the same time as tailwind generating it.

    "build": "npm-run-all -s build:*",
    "build:css": "tailwindcss -i src/_styles/_global.css -o dist/css/styles.css --minify --postcss",
    "build:html": "npx @11ty/eleventy",
    "dev": "npm-run-all -p dev:* -r",
    "dev:css": "tailwindcss -i src/_styles/_global.css -o dist/css/styles.css --watch",
    "dev:html": "npx @11ty/eleventy --serve --quiet",

11ty-equk/package.json on github (Jun 21, 2023)

Integrating postcss & tailwindcss on this project has gone over a few iterations but I finally got it working quickly with livereload & everything working.

📝Integrating Tailwindcss With Eleventy
📝Postcss 11ty Integration Update

Optimized Postcss Integration #

📝11ty Postcss Integration Optimized

This is the final iteration I made which is more than 3x faster with only a few posts.

[11ty] Copied 11 files / Wrote 27 files in 0.79 seconds (29.3ms each, v2.0.1)
[11ty] Benchmark    896ms  33%    25× (Configuration) "postcss-trans" Transform
[11ty] Copied 11 files / Wrote 25 files in 2.39 seconds (95.6ms each, v2.0.1)
[11ty] Benchmark    977ms  34%    23× (Configuration) "postcss" Nunjucks Async Filter
[11ty] Copied 11 files / Wrote 26 files in 2.61 seconds (100.4ms each, v2.0.1)

Image Optimization #

Image Shortcode #

eleventy-base-blog comes with image optimization through use of image shortcode.

{ % image "cat.jpg", "photo of my tabby cat" %}

📝Image Optimization In Eleventy

Markdown Image Optimization #

I wanted automatic markdown optimization to make things easier when writing blog posts & also to make it easier to transfer existing content over with minimal changes.

To do this I needed to change the configuration of markdown-it. (markdown.renderer.rules.image)

I used eleventyConfig.amendLibrary (example of this was already in eleventy.config.js).
I based the variables & code on the shortcode implementation already in eleventy.config.images.js.

📝Markdown Image Optimization In Eleventy

Consider where images are stored & generated when using automatic optimization

Adding esbuild #

Esbuild only needs to run once on each build as it's just bundling our page javascript.

Run esbuild before eleventy by using eleventy.before.

Javascript input src/_scripts/js output src/_addets/js.

📝Using Esbuild With Eleventy

Clientside Javascript Elements #

Trying to keep clientside javascript to a minimum.

Darkmode #

Mobile Navigation #

Adding Pagination #

Pagination - Eleventy Docs

Syndication Feed Generation #

I setup my syndication feed to display an excerpt for each post as most tech blogs I subscribe to do this.

With eleventy-base-blog atom feed generation is done using a njk template with permalink set to feed.xml so I decided to create an excerpt njk filter.

📝Generating Summary For Atom Feed In 11ty

Newpost Creation #

I moved my newpost script from Gatsby as an easy way to create posts.

📝Gatsby New Post CLI Script - Jul 6, 2019

The script uses readline and fs which are both core nodejs functions.

const fs = require('fs')
const readline = require('readline')
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
})

Clean Builds #

Ensuring clean builds seemed quite important so I ended up creating a prebuild script to remove output dir before running 11ty build.

The script checks if the output directory exists before cleaning & returns a message if it does not exist.

async function preEleventy() {
  // Start time for cli stats
  const start = +new Date()
  console.log('[pre-11ty] Starting Clean Build')
  // Clean output if exists
  if (fs.existsSync(outputDir)) {
    fs.rmSync(outputDir, { recursive: true })
    console.log(`[pre-11ty] Cleaning Old Build From ${outputDir}`)
    const end = +new Date()
    console.log(
      `[pre-11ty] Build Output: '${outputDir}' Removed (+${end - start}ms)`
    )
  } else {
    console.log(`[pre-11ty] Build Output: '${outputDir}' is clean`)
  }
  console.log('\n')
}
[pre-11ty] Starting Clean Build
[pre-11ty] Cleaning Old Build From dist
[pre-11ty] Build Output: 'dist' Removed (+10ms)

11ty Postcss Integration #

📝11ty Postcss Integration Optimized
📝Postcss 11ty Integration Update
📝Integrating Tailwindcss With Eleventy

11ty Image Optimization #

📝Markdown Image Optimization In Eleventy
📝Image Optimization In Eleventy

11ty Misc Tweaks #

📝Removing Luxon From Eleventy
📝Generating Summary For Atom Feed In 11ty
📝Using Esbuild With Eleventy
📝11ty Fixing Livereload Client For Inline Styles
📝Generating Slug Using Date & Title In 11ty

11ty Additional Features #

📝Favicon Generation In Eleventy
📝Adding Webmentions in Eleventy

Source Code #

The source for my 11ty blog is available on github.

11ty-equk