← Back to list

How I’m writing MDX with Obsidian

Introduction about my cool blog features. A development story about remark-obsidian-mdx

MJ Studio in MJ Studio · 2026-01-17 05:29 · 6 claps · 7.1 min read
#markdown #mdx #remarks #obsidian #editor
Open on Medium ↗
Wiki topics: ⏱️ · Productivity

How I’m writing MDX with Obsidian

A development story about remark-obsidian-mdx

This is a story about how I set up my MDX-based blog posting environment with several frameworks and plugins including one I made myself.

Obsidian Markdown Editor

Do you like Obsidian? It’s a high-end markdown editor which includes numerous features and plugins. Obsidian is also free and incredibly easy to use for developers.

The Obsidian team supports multiple platforms such as desktop, iOS, Android, and so on. One of the reasons I use this editor is the automatic syncing feature over iCloud or their cloud called Obsidian Sync(which is a paid service).

Today, I’m going to drop a post about how I set up a smooth blog posting environment using several frameworks and a Markdown remark plugin I developed.

What were my problems?

As you may know, or may not have heard, I’m in the army now. In this limited setting, I can’t write blog posts freely. When it comes to content like MDX that I need to see preview as I write, it’s quite tough.

The difficult things were as follows.

  1. How can I write posts on a small device like an iPhone due to lack of laptop or tablet even if I got a bluetooth keyboard?
  2. How can I upload posts I wrote to the blog published on a website (cloud)?

It comes down to having to come up with extraordinary solutions. It makes me passionate actually?

Obsidian rescues me. Its amazing WYSIWYG(What You See Is What You Get) editor helped me write beautiful markdown based posts easily.

The first problem was gone! Can I eliminate the second one easily too?

Spoiler: This article is all about how I could solve the second one.

One-way synchronization from iCloud Drive

The idea is simple. There should be a server which publishes the blog website using content pulled from a cloud storage storing our raw writings.

I matched this with Github Action. Wow, Github Action was perfect for running periodic tasks like publishing the blog website.

Then, what is cloud storage? What should we utilize?

Is it all right if we use iCloud as the cloud storage in light of the fact that Obsidian provides iCloud as an option?

Well, my answer is “I don’t want to do it but there isn’t an option”.

If I could use another cloud storage service as an alternative, I would use it. Unfortunately, It’s the only option. There is no way to manage an Obsidian vault(in Obsidian, workspace is called a vault) on iOS without iCloud and Obsidian sync(paid).

Because I’ve been paying Spotify subscriptions not only for myself but also my parents recently, I couldn’t extend subscription list anymore (just kidding).

I didn’t expect there was a third-party service that makes using iCloud via the CLI easy. But there was. It’s rclone. It might seem that the name rclone is inspired by rsync utility.

Anyway, I managed to set up rclone for iCloud and built a pipeline which pulls iCloud Obsidian vault content automatically and pushes it to publish my blog website.

I’m not going to write all about how I set it up. I just want to share my problem solving experiences. But, you would want to check my real blog website repository to explore how it was organized. Specifically, you would check .github/workflow/sync.yml Github action workflow.

[embed]GitHub - mym0404/english-blog Contribute to mym0404/english-blog development by creating an account on GitHub.github.com

Native convenience syntax in Obsidian

There are a couple of special syntax on Obsidian. It’s such as[[other-note]] note referring in the same vault, ==highlight== highlight mark syntax, ![[image.png]], ![[draw.excalidraw]]content embedding preview, and so on.

It makes Obsidian not only a Markdown editor but a robust popular editor in the world. It also gives several benefits to users who don’t want to type <img src="..."/> or ![alt](...) syntax by hand.

Speaking of image management, I’d say storing images in the same vault without any other cloud storages is much more natural in Obsidian.

Previously, in the other blogs, I used to upload images to my CDN, and embed them with the markdown syntax. It was powered by Image Auto Upload Plugin which is built on top of Piclist(a.k.a Picgo in the past).

Given a mobile environment where I can’t use Piclist, it’s impossible to use that way. In my circumstances and from my perspective, Past Image Rename Plugin is a way better option. Regardless of platforms which I’m writing on, I could paste the image from the clipboard. Then it copies the image data into the designated asset directory which I set in the plugin options and inserts Obsidian native embedding syntax like ![[name.png]] .

The following is a preview.

I can use ![[sample-1.png]] in blog/-sample.mdx without the path prefix although the location of the image is assets/images/sample-1.png. Just so you know, it’s a beauty of Obsidian.

What will happen if I publish this MDX file to a website?

There is no magic. It’ll be just <p>![[sample-1.png]]</p> .

Also, there are other cool syntaxes in Obsidian like [[note]] or native callouts like > [!NOTE] {title} .. .

The idea that I should create my own remark plugin is germinated from these problems. I couldn’t live with the status quo!

Seamless look & feel between Obsidian editing processes and published results.

Long story short, I’ve published a remark plugin named remark-obsidian-mdx .

[embed]GitHub - mym0404/remark-obsidian-mdx: Do you burn for writing your MDX based blog with Obsidian? Go… Do you burn for writing your MDX based blog with Obsidian? Go for it 🚀 - mym0404/remark-obsidian-mdxgithub.com

And this is the result. The left side is the Obsidian preview, and the right side is published post preview.

You can see another note that is embedded with ![[sample.mdx]] even though it’s the same note(it works in a recursivemanner with depth limits.). Furthermore, highlighting syntax, Callout syntax, image embedding syntax, all work seamlessly. That’s not the end. It can handle cases where it can’t find a resource path by rendering a NotFound component. It looks cool, doesn’t it?

How is Markdown converted to HTML?

First of all, I don’t even know the details exactly. Until now, I have had only basic concepts of Markdown transformation. There are steps called Remark and Rehype.

I won’t go into detail deeply due to a lack of expertise, but I’m going to explain what I used to build this package. The following are basic processes of them.

In the beginning, Markdown is converted to MDAST(Markdown Abstract Syntax Tree). Micromark is one of the famous Markdown parsers. It is in charg of parsing raw Markdown files.

https://andrewlb.com/blog/building-for-an-ecosystem

https://andrewlb.com/blog/building-for-an-ecosystem

MDAST is a kind of AST that expresses markdown content as a tree. I know that this isn’t a good explanation. I’ll show you an example.

# Hello
This is **bold** text.
{
  "type": "root",
  "children": [
    {
      "type": "heading",
      "depth": 1,
      "children": [
        {
          "type": "text",
          "value": "Hello"
        }
      ]
    },
    {
      "type": "paragraph",
      "children": [
        {
          "type": "text",
          "value": "This is "
        },
        {
          "type": "strong",
          "children": [
            {
              "type": "text",
              "value": "bold"
            }
          ]
        },
        {
          "type": "text",
          "value": " text."
        }
      ]
    }
  ]
}

Can you grasp the structure of MDAST? It’s simple enough to understand what it is.

The most important property is type . I’ll explain it later in this article.

Put simply, remark is a comprehensive process that includes parsing markdown(with Micromark today), inspecting the structure of the tree, applying node transformation plugins and converting MDAST to HAST(HTML Abstract Syntax Tree) at the end of the process.

Developers develop their remark plugins. A Remark plugin is a sort of simple modification algorithm which transforms nodes in the middle of the process. We used to utilize [unist-util-visit](https://github.com/syntax-tree/unist-util-visit) to visit intermediate nodes while remark was constructing the tree.

This is an example that shows how we can modify a node in the remark plugin.

visit<VisitTree, string>(tree, "blockquote", (node, index, parent) => {
   if (!parent || !hasChildren(parent) || typeof index !== "number") {
    return;
   }
   const callout = createCalloutNode({
    blockquote: node,
    options: options?.callout,
   });
   if (!callout) {
    return;
   }
   parent.children.splice(index, 1, callout);
   return;
  });

Can we convert Obsidian syntax as a unique type in MDAST?

Obsidian syntax to MDAST nodes

Yes, I could convert Obsidian components to MDAST nodes which have a custom type field in their properties.

For example, when we write [[note]] in our Markdown file, it is supposed to be aparagraph node. But I wanted a node having wikiLink type would be generated.

First, I integrated a WikiLink Micromark extension, but as I expanded its features to support Obsidian embedding syntax such as ![[]] , I had to fork the entire Micromark plugin and rebuild it from scratch.

As a result, it allowed me to look up whether a node was a wikiLink type.

For embedding syntax, I tried to parse paragraph nodes and find the pattern of the character ! appended to the wikiLink node, and it worked.

With all these processes, I could publish my own remark Obsidian syntax package on Github.

[embed]GitHub - mym0404/remark-obsidian-mdx: Do you burn for writing your MDX based blog with Obsidian? Go… Do you burn for writing your MDX based blog with Obsidian? Go for it 🚀 - mym0404/remark-obsidian-mdxgithub.com

Furthermore, it means I no longer need to pick out what I have to use to build my own blog which is made of Markdown content anymore. I have a cool blog that offers not only automatic synching but great Obsidian compatibility.

I didn’t know much about how Markdown and MDX are transformed into the real HTML tree. This experience helped me to get such understanding clear enough to utilize them from now on.

I appreciate you reading this. I hope you have a beautiful rest of the day.


메타데이터
post_id
71fa430e65ee
slug
how-im-writing-mdx-with-obsidian-71fa430e65ee
url
https://medium.com/mj-studio/how-im-writing-mdx-with-obsidian-71fa430e65ee
canonical_url
https://medium.com/mj-studio/how-im-writing-mdx-with-obsidian-71fa430e65ee
author_url
https://medium.com/@mym0404
status
ok
fetched_at
2026-06-12 07:40:50