Remaking my Portfolio with Eleventy
Some notes on setting up a blog with Eleventy with Markdown - and solving a few problems along the way.
My old blog/portfolio was oldschool, handcoded HTML and CSS, with a dash of JS. Deployed with FileZilla. Oh yes. The site had a dynamic header and footer, but creating a new post still required copying an old post and replacing the old content with new. Fun to build, but a pain to maintain.
Time for a remake!
While I wanted something a little easier to use for regular "blog-age", I had also had enough of bloated WordPress installations and fiddling with child-themes. WP is great for many things, but with all it can do nowadays, it sometimes feels like overkill.
- Simple, (mostly) static HTML, for a fast and light-weight site.
- A simpler way of creating and editing content, with full control (looking at you, WP Gutenberg)
- Easily customizable in terms of design, layout and functionality
- An excuse to focus on improving my front-end coding skills, not least in the CSS-department.
A friend introduced me to the static site generator Eleventy (11ty for short) and got me curious about both SSG's and Markdown. With the old WP post editor, I usually stayed in HTML-mode, but for my handcoded portfolio, typing HTML quickly became tedious.
Also, writing code and writing prose calls for different mindsets, in my opinion. Having to keep track of closing brackets and indentation isn't conducive to quality writing. On the other hand, I like to be able to format the text once and for all as I write, instead of pasting in something from a word processor and deal with that mess.
Markdown seems to be made for people like me, in that regard: A simple and easy to write syntax, which lets you do basic text formatting. You can write code directly in a Markdown file as well:
This span is HTML written in a .md file.
You can show the code by wrapping it in ``:
<span style="background: rgb(228, 227, 255)">This span is HTML written in a .md file.</span>
11ty can then take Markdown files (*.md) and compile them into HTML.
While 11ty.dev has lots of documentation and links to various examples of implementations, I struggled a bit at first. Some of the tutorials I found seemed to presume knowledge of SSG's, which I didn't have. I eventually found a tutorial made by Jon Keeping, which was fairly easy to follow (thank you, Jon!). However, I still feel the whole concept of SSG's - what they are and how they work - could be better spelled out for complete beginners such as myself.
Thankfully, the internet is full of nice people and help was to be had. I started an issue on GitHub. I asked confused questions over here.
The problems I had:
- Understanding the folder/file structure of 11ty's output
- Getting internal links to work when the site was deployed
- How to link CSS and JS and get them working locally
The folder/file structure:
I found this extremely baffling at first! 11ty takes Markdown (.md) files as input, applies whatever template files you have set up, and outputs html files. But: If you have created a file named about.md, 11ty will output it as index.html, inside a folder named about! Yes, about.md becomes /about/index.html. This seemed weird.
Folder/file structure generated by 11ty, with _site as default output folder:
_site |__index.html (the actual home page) | |__about | index.html |__contact | index.html |__posts |__post1 | index.html |__post2 index.html
Now, my old site had a different structure. Basically, in the root (public) folder of my server, I had an index.html, an about.html, etc. Then there was a subfolder named "posts", which contained posts (obviously). Images, CSS and JS files lived in their own sub-folders. This was how I built websites in the good ol' days, before I discovered WordPress. But as it turns out, there is a good reason for doing things the 11ty-way - and that is longevity:
What to leave out… File name extension. This is a very common one. "cgi", even ".html" is something which will change. You may not be using HTML for that page in 20 years time, but you might want today's links to it to still be valid.
In other words; keeping url's as clean and agnostic of technologies and opaque topics/contexts as possible makes them less liable to be broken, when someone decides to rename part of the path. Makes sense, but this reason is only kind of implicitly stated in the 11ty docs.
Deploying your site:
Most beginner-tutorials for 11ty suggest deploying your site to Netlify or GitHub Pages using various various automated deployment schemes. But...I just want to upload my files to my paid hosting using FTP or some such?
Easy enough, once you get your head around the file structure as mentioned above: Simply upload the contents of 11ty's output folder (the one named _site pr default) to the public root folder of your server. I have used FileZilla (ftp client) for this, but will probably set up something less clumsy I can run from a terminal.
A few notes on url's and file names are in order: When you create a new .md file and build it for the first time, 11ty will create a new folder in the _site folder, named after the file. So creating a file named about.md results in a folder named about. This folder then contains an index.html, which is actually the html version of about.md.
But - careful with those file names!
Any links in your documents must match the file path exactly! This means you cannot (as I did) have lower-case paths (href="/about/") pointing to upper-case folders - the links won't work. This may seem obvious, but had me derailed for a while: I hadn't noticed that some of my output folders were upper-cased, and didn't realize the significance of this fact, or why it had happened.
Pro tip: How you name your input files determines how you write your paths!
Paths should have trailing slashes!
According to the 11ty documentation, link paths should have trailing slashes, so this: href="/about/"; but not this: href="/about".
Leaving out the trailing slash could result in your browser trying to download the file pointed to, rather than load it. I haven't had that problem, but better safe than sorry.
Including CSS and JS:
But: CSS and JS files don't need to be "built", they are just fine as they are. They do need to be present in the right folder, in the 11ty output directory for any styles or scripts to work. Here's how I did that:
In my .eleventy.js file, I added a function call under module.exports:
eleventyConfig.addPassthroughCopy([ "css/style.css", "js/sitescripts.js" ]);
This copies my CSS and my JS files from the input directory to the output directory and preserves the folder structure for those files.
In the 11ty docs, go to Passthrough File Copy to read more.
Possible problems running client-side scripts:
I ran into a problem, when linking scripts in the usual way; putting the script tag before the closing body tag in the html. For a script to run on the home page, I put the script tag in my base-layout.njk file, since this is what is used to generate my home page at build time.
But since the layout for my posts is nested within the base-layout in order to inherit things like the header and footer, the script is now also being called on every post - in fact on every page of the site, since my about, blog and contact pages are also based on base-layout.njk. Inlining the scripts creates the same result, obviously.
This only resulted in console errors in my case, but with other client-side scripts, it could cause real trouble for visitors. Far from ideal, then. I will have to find a better way to run client-side scripts at some point, perhaps by putting discrete elements needing js in their own includes.
Conclusion: 11ty so far:
At this point, I more or less have what I wanted: A much simpler/faster way to create and edit content, which I can style and modify how I want - with static html as the output.
I find I rather like writing in Markdown. It's generally faster than wrapping everything in element tags, and whatever limitations it may have, I don't really mind mending with a splash of html here and there (I prefer styling code blocks as span and pre-tags, rather than using Markdown syntax).
As a bonus, I have also learned a lot - which I hoped I would. All in all, a good start.