Astro, embed an image in markdown without relative path

By

Astro loads Markdown images written as file.png, with no ./ prefix, since version 4.6.4. How it works, plus the remark plugin I used on older versions.

~~~

In Markdown we can embed images like this:

![](/path/to/file.png)

or using relative paths:

![](../file.png)

Imagine you have a folder with a markdown file.md and in the same folder file.png, and you want to include that image.

This is valid Markdown, and it works in most apps and CMS:

![](file.png)

Astro supports it too, with no extra setup. The fix landed in April 2024, during the Astro 4 cycle (PR #10801), so any Astro 5, 6 or 7 project handles it out of the box.

Astro finds file.png next to your Markdown file, optimizes it and outputs a regular <img> tag. A path into a subfolder works the same way, so ![](images/file.png) is fine too.

You can still write ./file.png if you prefer. It points to the same file.

Why I needed this

Usually it’s not a problem for me, as all images are in a separate folder under /public, served statically.

But for a project I’m working on, which has a TON of markdown files, I grew tired of using VS Code to edit markdown. I was looking for a good markdown editor that could open a folder full of markdown files, and also visually display images inside the content.

I settled on Obsidian, which I once tried for note taking but didn’t stick to it.

I found it an excellent markdown editor, with lots of options to customize it as I want it to behave.

Problem: Obsidian stores images like this in Markdown:

![](file.png)

When I wrote this post, Astro required a ./ relative path:

![](./file.png)

There was no way to change either of them.

The fix for older Astro versions

If you’re stuck on Astro 3, or on an Astro 4 release older than 4.6.4, the images without ./ won’t load.

After some googling I found a StackOverflow answer that guided me in the right direction. I learned I could use a remark plugin to change this behavior, and add it to the Astro config in astro.config.mjs. A remark plugin works on the Markdown before Astro looks for the image files, so it can rewrite each image path.

Now the problem was finding a plugin for my needs.

I don’t know how, but I found https://github.com/Pondorasti/remark-img-links, which lets you add an absolute URL to each markdown image, to use a CDN or something. Pretty similar to my needs.

So I wrote something similar, directly in my Astro config file. It adds ./ to every image path that isn’t a URL or an absolute path:

//npm install unist-util-visit

import { visit } from 'unist-util-visit'

function fixRelativeLinksFromObsidianToAstro(options) {
  function visitor(node) {
    if (node.url.startsWith('http') || node.url.startsWith('/images/')) {
      return
    }

    if (!node.url.startsWith('/')) {
      node.url = './' + node.url
    }
  }

  function transform(tree) {
    visit(tree, 'image', visitor)
  }

  return transform
}

and I used this in my Astro config:

// https://astro.build/config
export default defineConfig({
  //...
  markdown: {
    remarkPlugins: [[fixRelativeLinksFromObsidianToAstro, {}]],
  },
})

Now even ![](file.png) images work in Astro.

On a current Astro version you don’t need this plugin, so if it’s still in your config after upgrading, you can remove it.

Tagged: Astro · All topics

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about astro: