Using custom components with Nuxt-mdc to build a theming system
I'm building a blogging platform ( Writizzy ), an alternative to Ghost or Substack. Under the hood I use Nuxt, but I don't use nuxt-content to have more flexibility, so I use the Nuxt-Mdc module directly. This module allows you to extend markdown to include custom components, such as image galleries, embedded YouTube players, and more. However, Writizzy offers themes, and we want to easily customize components for each theme. In this article, I'll show you how to use Nuxt-Mdc for this fairly common use case. The nuxt-mdc module is used by nuxt content, but it can also be used directly to parse markdown content and render it as HTML. It's a core building block of Nuxt-Content, but fortunately it works as a standalone module. Among Nuxt-mdc's features, you can use MDC components . An MDC component is essentially a markdown syntax that calls a Vue component for rendering. For example, with this markup: We're telling Nuxt-mdc to use the Card component to render the block above. This is also what Nuxt-mdc uses to render all Prose components , which are custom components for headings, links, blockquotes, etc., created after markdown parsing. Internally, each standard Markdown element is transformed into MDC components. For example: is transformed into (This is a simplification . In reality, it's more of a substitution at the renderer level. The renderer reads the AST tree containing an h2 node and decides to use the h2 component to render it. But this is a good way to think about it.) This feature allows Nuxt-Mdc users to customize the rendering of each MDC component, including Prose components. To override a Prose component or create a custom component, you just need to place them in the directory of your Nuxt application. But what if you want these components to change based on the selected theme? That's exactly the question I faced with Writizzy. In Writizzy, I'm developing a theming system. You can choose your blog's appearance from the themes listed here . I partially reused what I had already built for Bloggrify (an open source project for creating static blogs). But with Writizzy, I was quite unsatisfied with this solution, especially for custom components. Obviously, the appearance of custom components should change based on the theme. It turns out there's an undocumented feature in Nuxt-Mdc that does exactly this. By default, the documentation recommends using the MDC component to display markdown, for example: However, MDC uses **MDCRenderer **behind the scenes. And looking at MDCRenderer's source code , we notice an interesting prop: This prop allows you to pass the list of components to use. By default, MDCRenderer will look in this list first, then fall back to , so you can override only the components you want to modify: And that's it! Now you can customize each component based on the theme. This approach works well for Writizzy, and I plan to apply it to Bloggrify as well. If you're using Nuxt-MDC with a theming system, I think this is the cleanest solution—even though it deserves to be officially documented. I've opened an issue to clarify its status. In the meantime, it's working in production on Writizzy without any issues.