Meta Blog: Advanced
Published on March 31, 2021A blog post on how to create your own blog (posts) with 11ty. Part II: Advanced technical details.
Part 1 of this series went through the basic setup and customization of this blog for your own purposes. In this part, I will go through a few technical details, tips and additional notes, that can allow you to extend the site and troubleshoot errors. This part can also serve as a project reference or documentation of some sort.
Overview
Before we go into detail about different aspects of the website, here’s a quick overview of all the different folders and what they contain:
.
├── config Configuration for plugins (e.g. markdown-it, KaTeX)
├── src
│ ├── assets Website assets
│ │ ├── fonts
│ │ ├── icons
│ │ ├── images
│ │ │ ├── favicon Icons and images for Web App
│ │ │ └── posts Images in posts
│ │ ├── other Other assets (e.g. PGP key)
│ │ ├── scripts JavaScript
│ │ │ └── modules
│ │ └── styles
│ │ ├── base Base styles (e.g. markdown, CSS reset)
│ │ ├── components Styling for various components
│ │ └── utils CSS utilities
│ ├── components Nunjucks components (e.g. card, tags)
│ ├── data Website metadata
│ ├── includes Nunjucks includes (e.g. footer, navbar)
│ ├── layouts Nunjucks page layouts (e.g. base, post)
│ ├── pages Concrete pages (e.g. about, post archive)
│ └── posts Markdown posts
└── utils JS utilities (e.g. filters, shortcodes)
Styling
Styling is done using SCSS. All stylesheets are located in src/assets/styles
. The styles are then imported and bundled in main.scss
.
The styles are grouped into three main folders:
base
: The base styling comprises basic stylesheets used globally throughout the page, such as normalization or typography. These styles are very generic, meaning you probably want to modify styles in different places, such as thecomponents/
folder for specific components.components
: These styles consist of more specific styles tailored to certain components, such as the footer, the navigation or the post tags. This is probably the best place to modify or add new styles when customizing the website.utils
: The utilities are mostly SCSS-specific functions, that make use of SCSS’s scripting features. This is also where the global variables for colors, breakpoints, etc. are defined for the entire page.
The compilation process, including minification, and error handling is defined in the styles.11ty.js
file. In practice, you shouldn’t need to modify this file.
Theming
The blog supports adaptive light and dark themes out of the box (based on the prefers-color-scheme
media query). The different color palettes are defined in _variables.scss
under the $themes
key.
Individual properties are themed using the t
SCSS mixin. This is for example how links are themed throughout the blog:
a {
@include t(color, 'link-color');
text-decoration: underline;
}
The mixin takes a CSS property as the first argument, followed by a variable name referencing the desired color. This name refers to a field from the $themes
map, which means you can only refer to colors defined as part of a theme. The mixin takes additional optional arguments, which you can find in the mixin’s source.
Breakpoints
Breakpoints are also quickly defined using SCSS mixins. There are two mixins, mq
and mq-down
, which provide breakpoints starting at, and going up to, a certain width.
The mixins take the name of a breakpoint, as defined in the global variables. An example use of breakpoints is when styling the navbar. The following declaration hides the navigation burger menu for large screens (starting at 940px in width) and up:
@include mq(lg) {
&__toggle {
display: none;
}
// ...
}
Markdown
Markdown files are compiled using markdown-it. The configurations for markdown-it and it’s plugins are located in the config/
folder.
The styles for Markdown documents, such as posts, are located in src/assets/styles/base/_markdown.scss
. Note that Markdown documents must be wrapped in an element with class .markdown
for the styles to take effect. You can thus use the Markdown styles in HTML/Nunjucks files by wrapping sections in such an element.
Plugins
The following markdown-it plugins are used in this blog:
Additionally, two custom plugins, one for the arrow icons after external links, and one for the anchor links when hovering over headings, are implemented in the config folder.
Posts
The blog supports several non-standard additions to Markdown, that add blog-specific functionality to your posts.
Nunjucks expressions
You can write Nunjucks markup directly in your markdown posts, just as you would in the other pages. Just wrap the expression between two curly braces: {{ Nunjucks expression }}
. For example, you can conveniently link to the page’s code repository, directly in Markdown, like this:
You can find the source code [here]({{ meta.code.repo }}).
This gives:
You can find the source code here.
Shortcodes
Shortcodes are another very practical feature of Nunjucks in Markdown. All shortcodes are defined in utils/shortcodes.js
, and you can add more. Shortcodes expand to a longer parameterized expression.
Standard shortcodes only take arguments, such as in this example:
{% 'icon pencil' %}
This produces an SVG element:
The standard shortcodes available out of the box are:
icon
to embed icons fromsrc/assets/icons/
ytvideo
to embed YouTube videos based on their id
There are also paired shortcodes, that wrap a markup section, such as this one:
{% msg 'info' %}
An informative message that **even** supports _Markdown_!
{% endmsg %}
This produces the following:
An informative message that even supports Markdown!
The paired shortcodes available out of the box are:
msg
for message boxesdetails
for an expandable HTML summary/details element
KaTeX
You can also include math expressions in your post. The expressions are compiled using KaTeX, which allows you to write TeX-like expressions. All KaTeX configurations are located in config/markdown-it/katex.js
.
For inline math expressions, wrap your code in single dollar signs: $math$
. For example, you can easily include fractions:
A fraction $\frac{a}{b}$ includes a numerator $a$ and a denominator $b$.
This produces the following text:
A fraction includes a numerator and a denominator .
For blocks of math, wrap your code in double dollar signs: $$ math $$
. For example, you can display Euler’s identity:
Euler's identity:
$$e^{i \pi} = -1$$
This results in:
Euler’s identity:
You can find all supported expressions and formatting options in the KaTeX docs.
Nunjucks
Nunjucksis used as the templating language for the blog.
There are several places where Nunjucks is used:
src/components/
: Nunjucks allows imports of so-called macros, which are used to represent the components. Macros are similar to functions and accept arguments to construct a parameterized output.src/includes/
: Nunjucks’ includesallow you to literally include chunks of markup as reusable units. This is used for non-variant parts of the website, such as the footer, header, etc…src/layouts/
: Layouts are page skeletons that are used as a common base among pages. The base layout is the HTML skeleton for all other pages and layouts. The post layout extends this base layout to include additional stylesheets for code highlighting or the utterances comment widget.src/pages/
: The pages represent concrete pages of the website, such as the About page or the Projects page. These are written with Nunjucks, but already include front matter for 11ty.
11ty
Most of the 11ty-related configuration is placed in the .eleventy.js
file.
Note, that if you are serving this website from a subproject on Github pages, i.e. when you are not using GH_USERNAME.github.io
, but rather GH_USERNAME.github.io/PROJECT/
, you must change the 11ty pathPrefix
field in the configuration file. The setting is commented out in this website’s configuration.
In development mode (npm run dev
), Markdown posts and images in the src/posts/drafts/
folder will also be built and served. They do, however, not appear in production mode and are not tracked by git.
Icons
All icons placed in the src/assets/icons/
folder will be grouped into an SVG sprite to improve loading time. The icons can then be used via the icon
shortcode.
Plugins
The 11ty plugins used in this blog are:
You can find the full list of available plugins in the 11ty docs
Webpack & Babel
All JavaScript code referenced in src/assets/scripts/main.js
is transpiled to backwards compatible JavaScript using babelto support older browsers.
The code files are then bundled using webpack, with the webpack configuration file located at src/assets/scripts/scripts.11ty.js
. The bundling process uses an in-memory file system to bundle the scripts in memory and return the bundled result as a reusable JS string.
Github
The site is automatically built and linted using the provided Github Actions workflows. The workflow files are located in the .github/workflows/
folder.
The lint action uses Prettier to check the code for styling and formatting issues. See the VSCode section for information on the Prettier extension to automatically format your code when you save.
VSCode
For VSCode users, I recommend installing the Prettier extensionto automatically format your code and posts on save. All recommended plugins are listed in the .vscode/
folder. These recommendations should be automatically suggested when first opening the project in the editor.
That was it. Thanks for reading!