On the limits of MDX
I feel I must preface this with some hedging because I'm about to challenge something that many people seem to love: MDX.
I have nothing but respect for those who contribute to the MDX ecosystem. Also, I'm totally the type of person that would love MDX. I have been writing in Markdown since 2004, and one of my first GitHub projects was a jQuery based markdown-footnotes plugin for Wordpress (jeez louise don't use this!). At university, I had a whole multimarkdown-to-LaTeX setup in Sublime Text with pandoc, BibTeX, and PDF preview with Skim going for me. It was kinda great (at least for the two weeks the setup worked)
I don't think MDX should be “considered harmful”, nor that everyone should stop using it. But I think there are some things worth considering before locking your, or rather, others’ content to it. And I'm writing this knowing there might be things I've missed or not considered. Feel free to respond to me with your own blog post, or on twitter. I don't think this is the hill I want to die on though. So I'll allocate no more than 3 hours to follow up on this discussion. Use them wisely.
With that out of the way. Let's jump into this. 🏊
What is MDX?
If you go to mdxjs.com it self-defines as “an authorable format that lets you seamlessly write JSX in your Markdown documents.” For those not in the know, JSX is “an XML-like syntax extension to ECMAScript without any defined semantics.“ (at least as proposed by the draft specification). In order words, MDX, that is, the MDX precompiler, lets you combine the templating syntax usually found in React.js projects with Markdown. It looks something like this:
# Hello, *world*!Below is an example of JSX embedded in Markdown. <br /> **Try and changethe background color!**<div style={{ padding: '20px', backgroundColor: 'tomato' }}><h3>This is JSX</h3></div>
It may look like HTML, because it does, but it's JSX. The intriguing part with MDX, but also the… uhm… problematic part, is that you can do stuff like this:
import { Button } from './Button'# Hello worldHello, I'm still a mdx file, but now I have a button component!<Button>Click</Button>
(example from the docz.site)
Yep, you can import JSX components and embed them with your run-of-the-mill Markdown prose. If you're documenting your JSX based component library, which is what Docz let you do, this makes all the sense in the world. MDX is also used to author slide decks in mdx-deck, which is very appealing if you're tired of clicking around in Keynote/PowerPoint/Google Sheets. Which many of us are. I'm not denying the appeal or usability of MDX for certain things for certain people.
From a React developer’s standpoint that it's used to writing JSX, MDX seems to be touching on the ethos of Markdown, at least as John Gruber, it's original creator, introduce it on daringfireball.com:
Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).
Markdown has always allowed inline and block-level HTML to express things outside of the syntax. Because HTML was the end product. In that way, MDX isn't much different. Markdown's key feature though is "easy-to-read, easy-to-write". I'm not sure if MDX keeps within, or moves away from this general intent. Gruber made a syntax that was easier to read and write for anyone not familiar with HTML. I'm not convinced that JSX solves the same problem.
What is the problem MDX tries to solve?
Markdown was designed at a time where most of the web authoring was still done in HTML. It was also designed when web content was mostly text and images. This isn't the case anymore. Web content has moved towards a much richer set of components, from embeds to interactive codeblocks, to between-paragraphs call to actions.
MDX seems like an attempt to make these components available to the author in the same syntax used in frontend development (well, as long as your frontend development uses JSX). And that's pretty much it. I think.
But this problem has been solved already. With something they call “rich text editors.”
There's plenty of content platforms with plenty of rich text editors that spew out plenty of different formats, including markdown, HTML, and abstractions as MobileDoc and Portable Text. Medium gained popularity thanks to its smooth authoring experience, Notion now seems to have taken over that hype. Void of HTML and Markdown (well, markdown-like shortcuts works, but is not a requirement), but with rich embeds. Arguably, these interfaces are more friendly and more accessible than learning Markdown, or MDX.
There had to be at least one reason for Slacks introduction of a rich text editor, yes, it wasn't very well executed, and we got Markdown back (I actually got used to the RTE), but I suspect they actually attempted to solve real user experience problems: Not everyone wants to learn Markdown.
Hey, I'm writing here!
I have written React for 20 years (that's recruiter for “since 2015”). I should know how to use my keyboard to paint beautiful JSX components with some lovely props and all that. But for some reason, when I have been made to write MDX. It. just. doesn't. work. I mess the syntax up all the time. Forget that I can't actually be writing Markdown inside of an MDX component (without wrapping it in some MDXprovider something). No syntax highlighting (this may have changed at the time you read this). No helpful error to actually point out where I forgot to close that component. Yeah, I know, but I was really supposed to be writing. Not doing debugging of frontend code.
And yeah… speaking of those components. Most times I had to use MDX, it was to contribute to someone else's documentation. So that means that I had to actually look up a bunch of documentation just to make a code example or a “note”. Sure, I could just TK'ed those parts (and I did), but again, it feels unnecessary for doing something that could be seamlessly solved with a text editor.
This is my totally subjective experience, but for now MDX is introducing a level of friction that I'm not really ok with when I'm writing. This takes me to the next section. Other people!
So, are we expecting people to use this?
I generally have hesitations dividing people into (I can be persuaded if you actually identify as a Luddite). But I have been through enough projects as a consultant and have been through enough user tests to be very careful in forcing even Markdown on people who go to work to do content. Writing with a markup syntax should be opt-in, not forced upon you.
You expect a person who probably already have too much stuff to do, to:
- Learn Markdown
- Then learn MDX/JSX and imports
- Internalize your component system (that never changes, right?)
- Work with plain files
- Use git or whatnot to actually get the stuff where it needs to go
- Ask you how to troubleshoot their texts when it gets borked
Sure, you have managed to persuade your client to do it and that's jolly good. But I know that for most people that don't share our coding interests, this will not fly. Not the bit. Also, you're asking them to put their content into a certain format that arguably marries it to presentation. That's probably OK for a slide deck, but less OK if that content is actually describing something of value inside of your organization.
And it has nothing to do with people being "technical" or not. Most content people I know can spot an apostrophe from a grave accent after two jaegers after a seminar. They know how the syntax works. At least some of the time. It's about what we can reasonably expect people to have to deal with. Should they be learning to write JSX components, when frankly, that's your job?
“But Knut, I have this client and they love it”. Sure, that's great for you and your client! But now you have another challenge. That client may want their content elsewhere. Or well, redesign their site the year we all do everything in WebGL. Or they just want to switch out their design system with new components. Yes, I know you have an AST. But you know what's better than an AST? Not to have to use an AST.
Because it's not only moving between formats and languages, it's also how you actually structure your content by what it means, and not after the whims of a specific presentation.
You can't unmix cake
I work for a company that promotes structured content, so you should see this coming from a mile away:
For most uses of MDX, you will end up mixing specific presentation concerns with your content. This is not great.
Yeah, it kinda worked for HTML. Until something called iOS came along. And then you had an icky problem. Sure, you could parse it. But have you ever tried to parse real-world HTML? You probably rather spend your afternoon on something different.
For people working with content strategy, content is best stored as ingredients from which you can bake the things that you need when you need it. They have been preaching “structured content” for ages and fighting with CMSes that force content into WYSIWYG page builders and make editors copy-paste their texts around in small layout boxes prisons.
Yes, technically you can be really semantic with MDX too. Compose your components to be great meaningful abstractions, not get tempted to use that style
attribute, and keep everything neatly separated in their own documents. But there's little in the design and practice of MDX that promotes this use. It is promoted as a way to build rich visual presentations.
Sometimes you want to make a cake, and that's fine. But you should think really hard if you could feed a lot more people for a lot less effort if you hadn't made the cake in the first place. Ok, this metaphor is pretty tired now. The point is: You should think really hard about how you want to be able to work with your content, the inclinations of whom you want to work with your content, and finally, how sustainable and flexible your structuring of it is.
The obligatory section where I try to sell you our thing
I get it. I get the tangibility of flat files. I get that it feels good to take your coding skills into your prose. But it's not the best way to work with content. Text editors with familiar affordances that produce typed rich text that can be queried and serialized into whatever you need are better. Where developers can define the data structures they need, and editors get easy-to-use tools to get their work done. Like what we're building at Sanity with Portable Text.
But it doesn't even need to be Sanity. After we launched with Portable Text, others have recognized that storing rich text in JSON structures has its advantages. No, you will never want to actually read or author the JSON, but you shouldn't need to. That what's React and JSX are best for. Namely, building the editorial experiences that don't come in the way of writing. That can be reused across frameworks, programming languages, and redesigns.
Closing remarks
(take a minute to appreciate that subtle pun)
With that out of the way, let me reiterate that I don't want to knock the people behind MDX and adjacent technologies. It obviously brings some people joy. You shouldn't feel bad for using it either, but now at least you have some counterpoints to make better decisions from. Maybe someone gets inspired to prove me wrong and make a structured content pattern library for MDX. That would at least be something. Or use some of my aforementioned allocated three hours of discussion time to tell me everything that's wrong with the Portable Text specification (I welcome it actually if it can make it better).
But do make sure you have considered if MDX solves the problem you really should be solving, or if it only tickles your developer fancy.