Skip to content

Astro, embed an image in markdown without relative path

New Course Coming Soon:

Get Really Good at Git

I hit this problem today: you know, you 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.

Apparently Astro can’t work with this syntax to include a file in the same folder as the markdown file, which is valid markdown and works in most apps and CMS:

![](file.png)

Instead, it requires you to use a ./ relative path

![](./file.png)

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, and 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)

Astro requires you to use a ./ relative path

![](./file.png)

No way to change either of them.

After some googling I found a StackOverflow answer that guided me in the right direction, because I learned I could use a remark plugin to change its behavior, and I could add that to the Astro config in astro.config.mjs like this:

import { defineConfig } from "astro/config"
import SOMEPLUGIN from "SOMEPLUGIN"

export default defineConfig({
  markdown: {
    remarkPlugins: [
      [SOMEPLUGIN, { 
        SOMEOPTIONS
      }]
    ]
  }
})

Now the problem was finding a plugin for my needs.

I don’t know how but found this: 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:

//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.

Are you intimidated by Git? Can’t figure out merge vs rebase? Are you afraid of screwing up something any time you have to do something in Git? Do you rely on ChatGPT or random people’s answer on StackOverflow to fix your problems? Your coworkers are tired of explaining Git to you all the time? Git is something we all need to use, but few of us really master it. I created this course to improve your Git (and GitHub) knowledge at a radical level. A course that helps you feel less frustrated with Git. Launching Summer 2024. Join the waiting list!
→ Read my Astro Tutorial on The Valley of Code

Here is how can I help you: