When rendering our markdown we might want to enrich the experience with some dynamic content. Many static site generators allow to include dynamic content placeholders for like embedding a Youtube video, generating table of contents, code blocks with interactive functionality and more. One way to achieve this in the React ecosystem is by using MDX. MDX is similar to JSX but for Markdown content, and allows us to directly embed React components within it. This gives an enourmous flexibility to what we can display within a page.
In this lesson we’re going to generate a new Nx library to host our “mdx elements” and learn how to leverage the MDXRemote
component to embed these React components into our markdown rendering flow.
Instructor: [0:00] Our portfolio site is now able to render Markdown on our page, which allows us to publish our articles. We definitely don't want just visual aesthetic content, but also more dynamic content, that makes the whole experience of reading these articles much richer.
[0:14] Many other static site generators have the possibility to include so-called snippets or templates within the actual content. For instance, if we would want to embed here a YouTube video, based on the syntax you're using, you might be able to say something like, YouTube, and give it a URL, and then, this would embed automatically some YouTube video, based on a URL within that content.
[0:36] We want to achieve something very similar. One approach to go here is to use MDX. MDX adds the possibility to embed within your actual Markdown document, also code. As you can see here, for instance, there is some code logic being embedded. It's similar to JSX, but for Markdown.
[0:55] This allows for a very rich experience and gives us great flexibility, as we can import here our React components within our Markdown content and mix and match them together.
[1:05] Let's implement that for our own portfolio site. First of all, I'm going to rename, here, these to MDX. We also need to make sure that in our Markdown rendering logic we use your MDX as our file extension. With that, we are set up.
[1:21] The next thing is we need to import a set of components which we want to be able to render within a Markdown document. The MDXRemote component here already accepts a components property, where we can pass in components that should be detected within a Markdown document.
[1:38] Since in an Nx workspace we would want to host these components in a library down here, I'm using the generator again to generate a new library. This time we're using the console, and we're using nx g for generate now our React, because we want to generate a React library.
[1:54] We call it MDX elements. I want to place it into the directory=shared, because this might be shared across multiple applications. Then I can use the dry run to see what would be generated. I am using CSS for this library. We can see it would create in the libs shared an MDX library with some couple of content or a pre-configured.
[2:17] Let's remove the dry run. Let's, again, confirm the CSS choice here. Now we get a new library created with already some MDX elements in here. These are just empty components that have been pre-configured for us. We probably won't need those. We can actually go and remove these.
[2:34] Rather let's generate a new component in our new library that is called YouTube for embedding YouTube components. Let me pull up here the activity bar again, and use Nx console to generate that component. I'm searching here for component. I'm creating a React component because it just doesn't necessarily have to do with Next.js. Let's call this here, YouTube.
[2:56] The project I want to generate this in, is my shared-mdx-elements. I'm using CSS for the style, so we can leave all our other changes untouched. We click Run, and it generates now a new component within that MDX Library.
[3:08] We can now go in and customize this. Our YouTube component would probably get a title, which you might want to render alongside with the component, and a UUID, which is the ID of the YouTube video which you want to embed.
[3:21] In terms of the implementation, we would have here an iframe, which is what you get from a YouTube video, which has a source. We can construct that source, and use here a props.uuid as identifier of the actual endpoint. Let's add here a width and a height. Obviously, you can configure that as you prefer, in your own setup . Maybe, also let's include here a title, which comes from props.title.
[3:48] With that, we have our YouTube component set up. We also want to export this from our library here. We go to that verify, that index.ts file here, and export everything from libyoutube. With that, we can now go back to our actual page component again. At the very top, we want to import the YouTube component.
[4:06] Now we have a new library which we just created, which is that shared-mdx-elements, which exports that YouTube component. Once we have that in here, we can go ahead and pass that to the MDXRemote component.
[4:18] Now, we might want to group these MDX elements a bit further, to make it easier to pass them to the MDXRemote component. Let's create here an MDX elements object. We pass all these MDX elements to the components properly, of our MDXRemote. With that, we should be able to embed a YouTube video just in our content here.
[4:40] Let me add here some YouTube video from my own channel. Let's restart our server again. If we go to our localhost and refresh, we see our YouTube component being embedded within our page.
Member comments are a way for members to communicate, interact, and ask questions about a lesson.
The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io
Be on-Topic
Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.
Avoid meta-discussion
Code Problems?
Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context
Details and Context
Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!