Working with images in markdown files and static sites

Anh-Thi Dinh
👉 Note: 11ty & Nunjucks.

What we want?

  • Capture the screen to the clipboard and then paste it into the editor. The captured image is automatically copied to a folder and can be viewed in the editor as well as on GitHub and on the 11ty website (after rendering).
  • The same function for online images (copy and paste the URL).


You will need to install the following tools. Depending on your working style, you can choose one or both of them.
  • Typora (what you see is what you get).

Setting up your project structure

Below is an example of the folder structure on my website. Read this section to understand why this structure is important for all parts work together.
2|- _built/ # The output folder (11ty renders markdown files to this)
3|- .eleventy.js
4|- notes/
5  |- blog/ # contains all markdown files
6     |-
7  |- img_post/ # contains all images
8     |- 2022-06-25-name-of-post/ # the same name as markdown file
9        |- figure-1.png
10        |- figure-2.png
Some remarks,
  • I put all the Markdown files and images in a folder called "notes", you do not have to do that. In other words, you can put the "blog" and "img_post" folders in the root folder.
  • The folder "2022-06-25-name-of-post" inside "img_post" is automatically created by Typora or VScode (that's why I use them). But you can also create it manually if you want.

Setting up .eleventy

You need to make 11ty recognize "blog" and "img_post".
1module.exports = function (eleventyConfig) {
2  // For images
3  eleventyConfig.addPassthroughCopy({ "notes/img_post": "img_post" });
5  return {
6		// other settings
7    dir: {
8      input: ".",
9      output: "_built",
10    },
11  };

Setting up VSCode

Make sure you have the Markdown All in One and Markdown Image extensions already installed.
Go to Makdown Image settings:
  • In Markdown-image > Local: Path: /img_post/.
  • In Markdown-mage > Base: File Name Format: ${mdname}/${rand,100}. Whenever you paste an image (from clipboard or from an URL) to a file, a new image file will be created at img_post/2022-06-25-name-of-post/<random-number>.png
A weakness of Markdown Image and Typora is that if you make changes in VSCode or Typora, an image that is automatically created in the folder you want cannot be changed. For example, if you change your mind and delete the line ![](...), the image in the folder "img_post" is still there, you have to delete it manually!

Setting up Typora

Go to Typora Preferences and make the same settings as below,

Why does it work?

Based on how an SSG works, you can use the same idea in this post to get the same workflow for other SSGs other than 11ty (Jekyll, Hugo, Gatsby, ...).
As you know, all rendered HTML files and images must be stored in an output folder, say _built/ in my example. What you see on the website (in the html file) is
1<img alt="alt-of-image" src="../img_post/2022-06-25-name-of-post/name-of-image.png">
and what you see in the Markdown editor is,
They look the same, but in fact they are not. Let's check the folder _built/
2|- _built/
3  |- name-of-post/
4  |  |- index.html
5  |- img_post/
6  |- 2022-06-25-name-of-post-name-of-post/
7     |- name-of-image.png
Because in the .eleventy.js, we have set addPassthroughCopy from notes/img_post/ to img_post/, we have _built/img_post/ after rendering.
It works in markdown editors (VSCode, Typora, Github,...) because the relative path of the image to the markdown file is ../img_post/.
Check again our project structure,
2|- _built/
3|- .eleventy.js
4|- notes/
5   |- blog/
6      |-
7   |- img_post/
8      |- 2022-06-25-name-of-post/
9         |- name-of-image.png
It works in the HTML file because the relative path of the image to the index.html file is ../img_post/ too.
In short, you have to make sure that the relative path of the image to the markdown file is the same as the relative path of the image to the (rendered) index.html file.
Loading comments...