My Favorite Way to Use Markdown in NextJS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
if you say Doc dot you can see just those types right here description published title how amazing is that oh Josh the way we're gonna work with markdon in this video is going to be fully typesafe yes sir it is and it's also blazingly fast because everything is done at build time nothing is weighing down your client even though when working with markdown you usually use very heavy dependencies I want to share an absolute gem with you today say you wanted to create a new blog article follow along with a video and you'll know how to only create one marked on file containing your blog article content and everything else is gonna be handled for you that blog article is going to be accessible on the web to your users it's fully typesafe it's honestly very enjoyable to work with let's Dive Right In Here we are brand new project let's build an amazing markdown X block together okay we're gonna need one dependency for this yarn at or npm install and that is going to be content layer that's what we're gonna use amazing tool I'm gonna show you why and then we're going to install four plugins these are not necessary you can leave them out however for me it's important to show you the best possible code and this is an amazing approach to make your markdown even better you're going to be able to add some beautiful code you're going to be able to skip to some headlines that's what these plugins are for and first one is going to be re-hype Dash Auto Link Dash headings that's what's going to allow us to jump to certain anchor points then re-hype Dash pretty Dash code also a rehype dash select to generate a slug for each of these headings and lastly remark Dash gfm again last four completely optional I'm gonna install them because I want to show you the best possible code and let's let them install and then get started with our markdown X block okay it looks like we're done and these dependencies took a while to install I sat here for a solid two minutes because they are huge working with markdown is not a very lightweight thing to do but don't worry everything is going to be generated at build time none of this is going to weigh down your client footprint now first thing we're gonna do to get started is in our root file create a new file and that is going to be called contentlayer.config.js and this is where we're gonna configure everything that's related to how we want our project to act in this config first thing we're going to do is import everything that we need and those are the plugins that we have just installed then we're gonna Define our computed fields and what these do is each field allows us access to a resolve function and inside of it the dock where we can extract a certain value that is going to be returned for this slug as a computed field and similarly we want the slug as params then we're gonna export a dock and this is the important thing this is what we're going to import later in our page in our blog I'm going to name it DOC then this is the important thing the file path pattern this is where your markdown content will actually live I called mine Complete next.js because I'm going to be writing a nextjs Blog important that you name it where in your file system your actual markdown content will reside the content type is going to be MDX and then we can insert certain Fields into this stock and now comes a huge benefit of content layer these fields like the title with required true are typesafe these are generated at build time and we can import the type in our page you're going to see that later these fields will correspond to the front matter of or markdown files if I show you what that means I've got a demo project my course project open here this I mean without the Vimeo ID but this title and description properties you see here defined in these three hyphens are going to be the front matter and this is what we're making typesafe right here in the content layer config with title and description then we also want a published property for each blog article and want to also pass in or computed Fields like the slug and the slug is params that we have to find up there then we're going to export a function that is called make source as a default with the content path and because I want all the marked on files with the subsequent folder of complete next stress to reside in the source content folder that's what I'm gonna pass here the document types if you had multiple like Doc and article and so on maybe the legal pages of your app that those would also go into the document types and then some MDX plugins first one for the remark plugins we're going to install remark gfm a plugin to support gfm with Auto Link literals footnotes and so on then for the re-high plugins that give us prettier code and make or headings actually clickable so we can jump to a certain part of the markdown X we want re-hype slug rehype pretty code and pass that some options for example a theme and when we visit each line we also want empty codes or empty lines to be pastable that's why we're putting an empty spacebar inside of the empty children then on each visited line we're going to push a class name that's going to allow us to fine tune the style and same goes for a highlighted word and then we're going to implement rehype Auto Link headings which is also going to allow us to skip to the headings along with a slug and passes some properties like the class name the area label and that is our content layer logic fully done how beautiful is that we can run a build on this and it's going to go to our source content folder then search for complete next JS and then for any markdown file inside of that directory which doesn't exist yet but we can still run yarn content layer build and see what happens we're going to run that oh and it seems like I forgot one dependency a peer dependency that is missing I'm going to say yarn add and then she key which is responsible for the code syntax highlighting at build time by the way none of this is actually weighing down your client-side footprint which is awesome and then if we try to build again you can see generated zero documents in dot content layer which makes sense because we don't have any marked on files to generate from yet but you can see the dot content layer is right here with a cache and inside of the generated we can see the dock the type we we have defined right here how beautiful is that and then an index.mjs where all or marked on files would go as parse JavaScript or more like parse Json I should say and then we also get access to the types right here this is fully typesafe super well done okay we know where content layer is searching for or content and that's in the source directory then inside of the content folder and then inside of something called complete Dash next JS because that's where I want my blog articles to live and if we create articles in here as marked on X or markdown they're going to be generated by content layer at build time for example we could say middleware.mdx I want to write an article about middleware and what we do inside of this file is first Define the front matter because in content layer we have defined we want each file to have a title and a description we need to Define that right here for example the title is going to be middleware is awesome and then the description we could also use this as The Meta description on the actual page would be an article about nexjs middleware and then close the front matter off with three hyphens now below the front matter is where the actual content goes I'm just gonna paste a lot of lorem ipsum right here um to mock a Blog article out save that and then let's try building this again as you can see it says generated one document in dot content layer and if we check what it generated let's go into the generated and then the dock and then to the index.json we can see our article is right here with the raw content that we can then use to actually render all the marked on and with the code which is just nothing else than JavaScript we can see the title is right here the description is right here and also the published value we have put into our content layer config with a default value of true and you know what I'm gonna change the complete next.js file path in my content layer to blog I just forgot to change it when I copied it out for my course and so I'm going to change it to block which also means we need to change this right here into block the name is going to match this right here the content layer config then run the build again that's going to build out the entire file with the middleware.mdx generated one documents in dot content layer great and what that allows us to do is create a same route in our app folder so for example let's add a route called blog and inside of the blog we're going to create a dynamic file that's going to catch any path following the blog URL structure called slug in these angled brackets to make it dynamic great and that needs to be a folder actually create that as a folder and then inside of the in angle brackets lock folder create a page.tsx this page.tsx is going to determine what is shown for this Dynamic path okay and the logic on this page is going to be pretty straightforward first off we're going to receive the params and these are going to be passed to this page because it is dynamic so SD params we're going to receive whatever is right here as the slug in the URL and we know the type of that if you're in typescript we can Define the type like this with the params these are going to be an object and contain the slug as a string because this is what we put in the angled brackets if you want more information on how this whole thing works I did a whole tutorial on the next JS app router and I definitely recommend you watch that great and then for the fetching right on this page what we want to do is get the corresponding generated markdown file for the certain slog we're on for example if we were on slash blog slash middleware we wanted this file right here the content of this MDX file to be fetched and the way we can do that is by saying async function get doc from params and then this is going to receive a slug as a string and inside of the body of this function we're going to say cons dog or coins cons article if that's what you wanted to call it it's going to be all docs and this all dogs comes from import all docs from content layer slash generated this is giving us an error because it currently does not recognize the file path but we know this is a correct file path under content layer generated so what we can do to tell typescript this is an allowed file path let's go way down here inside our tsconfig to the paths and then add a new one saying content layer slash generated is going to be equal to dot slash dot content layer the folder we have up here slash generated save that restart the typescript server and then the arrow is going to be gone and you want to see something amazing when I hover over the all docs it says all docs is dock array this is fully typesafe do you understand how cool that is we can say all docs and what we want to do is find a certain one for each dock we're gonna make a check that is going to be if the doc dog dot doc dot slug as prems is going to be equal to the slug we are passing in that we receive as props to this certain page and if we do we know this is either a doc or undefined because it might not find this certain slug if there is no doc then we're gonna say no nothing is going to happen and else we're going to say return doc what you could also do is throw a not found error right here and that's going to throw a 404 if you're trying to navigate to this for example you would do that by saying not found importing that oops and that is what we need to import as well from oops from next slash navigation like that and then we can invoke that that's going to throw a 404 error if there is no Doc and then we can know we are definitely returning a doc from this function to get access to the stock in the page we can say corn stock is going to be equal to call this function with the params.lock that we're getting into this page and then we know we are being promised a document so we're going to await this operation and also to do this the await in the top level we're gonna need to mark this server component as asynchronous we know we can do that because it is a server component that is receiving the page props and then we have access to the dock and can do with it whatever we want for example let's say Json Dot stringify and we're going to put the doc in here now this is not actually how you would want to render out your dock but I'm just gonna do this to show you that it actually works let's navigate to localhost 3000 then slash blog and slash middleware that's going to invoke the slug called the dynamic page with a middleware slug and then hopefully give us back or component or the statically generated markdown file and it does again as I said this is not how we how you would want to render this out this looks really really bad but because there are so many ways on how you could render this out I'm not going to provide you with any certain way because there is no best way but if you want more information on how to properly display this because this looks very horrible I recommend looking into a package that is called Next Dash content layer let me show you what that looks like let's say yarn at next con to content layer hit enter and that's going to install a wrapper 4 content layer in nexjs and then I just copy and pasted some code over again if you want access to this code and there's going to be a repo in the description where I learned this from that is going to make it easier to render all the markdown essentially you can see for each markdown thing that there could be we are declaring a custom component like each heading or an anchor tag the P tags the lists and so on and then down here we're using a hook that is being provided to us if you take a look at where this comes from way at the top from next Dash content layer a super convenient wrapper and then we are returning a component with the components that we have just specified so instead of doing this let's say MDX import that as a component it's going to be self-closing and receives something called code and if you can't tell from this code right here what we want to pass into that it's going to be in curly braces dynamically dock dot body dot code that's that's what we're going to pass into this and now if we reload the page and the dev server is not running and you can see it looks way better there's a very subtle background and we're displaying the right information to the user styling is totally up to you but that's how you properly render your component very very amazing stuff oh and by the way one last thing if you take a look at the type safety you can see the properties that we have custom defined in our content layer config right here the title right here the description and the published if you say Doc Dot and then press Ctrl spacebar to see what types we have access to you can see just those types right here description published title the slug the slug is perhaps the dynamically computed Fields how amazing is that that is really really cool stuff it's fully type safe we can render it out like this and display the title for example in an H1 if we wanted to say Doc dot title and that is going to be pulled right here from the front matter in our middleware this title right here great that's how you properly handle markdown X in react or nexjs I really hope you enjoyed this one I wish you a lot of fun building something very very cool with this I'm going to link the report in the description and then I'm gonna see in the next one have a good one and bye bye
Info
Channel: Josh tried coding
Views: 10,847
Rating: undefined out of 5
Keywords: react, mdx, markdown, nextjs, nextjs markdown, react markdown, react mdx, nextjs mdx, mdx nextjs, mdx tutorial, react mdx tutorial, nextjs mdx tutorial, nextjs markdown tutorial, josh tried coding, joshtriedcoding
Id: YC6LqIYVHxI
Channel Id: undefined
Length: 15min 51sec (951 seconds)
Published: Tue May 16 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.