Astro, embed an image in markdown without relative path
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.
→ I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter
→ JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025