Content: Embed images in markdown without relative path

Join the AI Workshop to learn more about AI and how it can be applied to web development. Next cohort February 1st, 2026

The AI-first Web Development BOOTCAMP cohort starts February 24th, 2026. 10 weeks of intensive training and hands-on projects.


You know, 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.

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.

Lessons in this unit:

0: Introduction
1: Markdown in Astro
2: Images
3: Content collections
4: ▶︎ Embed images in markdown without relative path
5: Run client-side JS in Astro MDX