Bryant tackles the challenge of building a documentation site that lets content editors manage help articles through a CMS instead of markdown files. Watch as he sets up a backend with Directus—creating categories, articles, and tags relationships—before diving into a frontend template to bring it all together in his race against the clock.
Speaker 0: What's up peeps? Welcome back to another episode of 100 apps, one hundred hours. I'm your host, Brian Gillespie for Directus. Today, we've got a pretty cool episode, I think. Yeah.
I've seen this come up time and time again in our community and some of the questions. You know, most documentation sites or help centers, at least in the developer community, they're all static markdown files, which is great. As a developer, I love markdown plain text formatting in a nice easy to read way, easy for me to author. Content editors, they don't necessarily love markdown. So today, we're going to be building a help center.
If you're new to 100 apps, one hundred hours, there are two rules. We have sixty minutes to plan and build an application, an idea, a clone, whatever, no more, no less. And number two, use whatever we have at our disposal. So with that, let's fire sixty minutes on the clock and go. So I usually start every episode just trying to figure out what type of functionality we're looking for here.
So I want a documentation site, a help center slash documentation site where let's do this on a new line, where content editors can edit within a CMS and not necessarily text files or markdown or whatever. Right? Those are the main requirements here. If we were to put down, like, a stretch goal on this, I would say, like, IT and IN support could be a we'll call it a stretch goal. Sounds good?
Sounds great. Alright. So as far as what we want out of our data model here. Right? When I think of a help center, I think of categories.
So I think of what section do these belong in, and I think of articles. So category has what? It has a name. It has articles within it. So there's a relationship there.
The articles belong to a category. Could there be multiple categories or multiple could an article live in multiple categories? I would say not. I would say that's probably the realm for our friend tags. Right?
Or topics or something like that. Right? I can have a mini to mini relationship. So we'll do some nice looking arrows. Great.
Great looking arrows. So we have multiple tags on an article, but an article belongs to a single category. Right? So we have a title for the article. We have a slug and then we have content.
Now this could be markdown if you prefer that. It could be HTML from a WYSIWYG editor. However we wanna do that, we'll tackle that as we dive in. Alright. So before we even do the front end, let's start on this inside Directus.
Now I've got a nice kind of front end template picked out for this, but, let's start back end first with our data. Right? The first thing we're gonna create, let's let's tackle categories. Right? So we'll do categories.
We could call these collections. We call a table inside direct us a collection, so that could be confusing. Let's just call it a category. Great. We'll give it a UUID and we'll hit save.
Do I want any of these other things? We probably want sorts for these. You know, I could decide not to publish an entire category or not. I guess that's okay. Let's give this a name.
Category name, makes sense. Article title, I am we could go with title across the board. I guess that makes more sense. Alright. So let's go ahead and start cleaning up the form a bit.
I like title, status. Do we have a slug for the category? Probably. Forgot to put that in there. We can even add nice little icons in Directus.
Makes it super simple. We'll just add a little link. I'm gonna open up the interface for this and just Slugify this. Make my Slugify option using my little mouse Pose tool here. We'll trim the start and end in case there are white spaces, and let's make this mono space font.
Yeah. This is gonna look amazing. Right? We'll use mono space font for the display. That just controls how it looks in the different directus layouts.
We have a title, a slug. We have a category. What else do we want? We wanna have an icon. Right?
Cool. Icon for this category. Can't get rid of the designer OCD stuff that I still hang on to. Cool. That looks great for categories.
Now let's set up our articles. It doesn't look great. Forgot an icon for the actual category itself and a display template. Great. Okay.
So now we have categories. I could go in and create a new category. Let's call this API reference. Right? API.
And do we have an API? Yeah. Your standard API icon. We'll just go ahead and set this to published. Great.
We have a category. I could query this on the front end. Items slash categories. Boom. I've got a REST API.
Magic happens. Sparkles fall from the sky, etcetera. Alright. So we've got categories. Let's add articles now.
So again, I'm going to caution against using something like slug here as the primary key field because if you ever need to change that slug, you cannot change the primary key value for a record because of all the relationships that are attached to it. Could get very messy. Right? So, what we'll do here, let's add created on, created by. These system fields here or these optional system fields are helpful.
Created by you can also rename them as you see me doing here. Updated at, created at, updated at, updated by that'll be the user. Cool. You can use them as is. You can leave these out.
You can add them back later. It's just a shortcut for you. Alright. So let's pick the article icon. Is there an article icon?
What do you got for me? Directus. That looks pretty good for an article. We'll command s to save and stay. And let's start fiddling around with this, right?
Again, we'll use a title for the article. Cool. Gravy. One of the other shortcuts that you can use in Directus, if you have a field that you want from another collection per se inside your data model, I can just go to duplicate. So I've already got the slug set up how I want it.
We'll just dupe that across to the articles collection. Alright. And categories will probably be above that. So here I can see my slug field. We'll just set that to half width.
What else did we have here? We had content. Right? So how are we gonna set up content? Do we want WYSIWYG?
Do we want Markdown? It could go either way. Let's lean Markdown first just to see what this looks like. Hit save. And basically behind the scenes, this is just creating a text column inside the database.
So, you know, if I wanted to go back later and adjust like the actual interface, what the user interacts with, I can change that from markdown to WYSIWYG very easily. Or if you're like me, you might use even plug something like Tiptap in here through our directus marketplace. Great. K. Now we've got tags.
Let's go in and create our tags. Great. Generate a UUID. What is the tag? Do we have a sort for the tags?
We don't really have any of this tags. We'll use a hashtag. What's the tag? Name of the tag, title of the tag? We'll just use title.
Again, naming things is always the hardest thing. I think there's like a receipt option that kinda looks like a tag. Does that bookmark maybe? Kinda looks like a tag. Kinda also looks a lot like a bookmark.
This does not look like a tag. Oh, that's a Pentagon. Pin tag on. Yeah. Cool.
Let's use that. Sounds great. Alright. So now we have a tag. I don't know that we need a a slug on this.
You know, you might have, like, grouping for tags later. But that's kind of the basic of this data model. Right? Now let's let's add an article to this, and we can quickly see what we're working with. Accessing items.
Items. Accessing items. So there's our slug. We can publish this guy. We can go in and add some markdown.
Hey, yo. This is a markdown editor. It edits markdown. Wild, I know, right? And then I could preview that.
We could save this. Again, we can just, like, look at this URL. We can replace items with the admin. So here we can see this data. This is because we're actually logged in.
When we send this request, it is sending our token in the cookie. If I were to do this in, like, a incognito window, you'll see that I I get no access. No access to that. We could solve that by going in and updating our access policies and and or our roles. So, by default, Directus loads two roles.
There's a public and an administrator role. We've got our access policies here which are, more granular. Right? I can have I can attach 35 different access policies to a single role if I want to. But if we look here, the data that is available without authentication is absolutely zero.
Absolutely nothing because we want you to be secure. So we'll just go in, we'll add tags. We're probably gonna want files if we choose to upload them. So we'll add read access to files, add read access to tags, add read access to categories and articles. The one restriction I'm gonna put on articles is that we only wanna show published articles.
Pretty straightforward. I guess we could do this to categories as well because we do we have a status? Yes. We only wanna show published categories. Now if I were to test that out, we just create a this is unpublished article.
This is a work in progress. That's what we'll call it. This is WIP. Great. I got two articles now.
If I open up that incognito window, paste that same URL except we drop the ID, you could see I'm only getting a single article that is published. If I were to change the WIP article to published, boom, boom, fetch. Yeah. There we go. I can now see that WIP article.
Great. Permissions works. We have a REST API. We have what we need to proceed. So, the thing we are missing here is our relationships.
Right? We don't have a relationship between articles and tags and categories and vice versa. So let's solve for that. Right? First thing, we need to define kinda the way those relationships work.
There is a one to many relationship between categories and articles and a many to many relationship between our tags. So I could do this. I could go into our categories. We'll look for that one to many relationship. We'll call this articles.
The related collection is also gonna be called articles. So the key is the name of the field inside the categories collection, the related collection here, and then we have a foreign key, which will be the category, probably a a nice naming convention here, singular, plural, fun stuff. So the category is only going to be a pointer back to the categories collection. And for the displayed template, we could show the title. Great.
Maybe we wanted to do show if this is actually published or not. I think that's a good way to handle it. And we'll show a link to this item. And if I wanted to drill into this, I can go open the advanced field and we could see here's the related collection. You know, maybe I wanna add that sort field.
We'll use that to, control the order of the articles. You know, we're not in documentation or like a help center or something. You don't necessarily wanna do like chronological order based on date. You wanna do, an order that you specifically set. So I do that.
That should have also created the corresponding field inside articles, so now we have that set up. And then what I'm gonna do now that we're here in articles, we'll create that many to many relationship. I Was trying to look for another name there, wasn't I? Let's call this tags. The related collection will be tags, and we don't wanna allow duplicate tags.
We'll show a link to this. There's a lot of other settings that we control here. You know, how many different items show in a page when you're looking at a lot of them. You shouldn't have probably more than 15 tags per page, but if you do, kudos. Alright.
For our relationship tab here, I always open up advanced so I can see what's going on. You could see now that Directus is gonna create this junction collection for you. I could scroll down, it'll tell you exactly what fields are gonna be created, but I'm gonna adjust that. I'm a little OCD about how I name things. So this is gonna be article tags.
The key for the article, I'm just gonna call that article and then I'm gonna call this tag instead of tags underscore ID. You can let Directus autofill that. You don't have to add it this way. Totally up to you. Whatever you prefer.
And then I'm gonna add this corresponding field. If I do ever want to filter articles by tags, I could go straight to the tag and get a list of articles that way as well if I add this field. And we'll add a sort just just for fun. Great. There's our interface.
There's our display. We'll display the related values. Looking good. And And we can see that Directus has created that article tags collection for us. It's hidden by default.
We don't necessarily need to see it. And what does this look like now? Right? So hey yo. This is the markdown editor.
We have tags. We don't see a category. So I do wanna be able to edit that category. We'll just unhead that guy and boom. There we go.
So now we can see a title. Here's the status. And maybe we move that category up here to the top besides status. That makes sense to me. Again, the beautiful thing here is we are updating the form that our team members are actually gonna interact with, which I think is freaking awesome.
I don't wanna hide that. I just wanna make it half width. Got a little carried away there. Move some of these other ones out of my way. Alright.
So now we've got category. Got a status, category, title, slug, content, and then tags if we wanna apply those. What does this actually look like? Looks pretty good. There's our API.
Cool. That's the category it's in. Here's the title. Here's the slug. There's the tags.
We can create a new tag. Let's call this, reference or feature. We can call this items. That makes sense. Great.
We'll hit save and stay. This is not looking nice. I don't like this. This is the UUID for the tag. So let's just go into here and I can fix this two ways.
I can go into my tag and add a default display template. I think that should take care of it. We'll maybe do the same here for our articles. Just anytime we're using this, it should default. Okay.
So now I can see the tags. We have items there. Looks much better. Much, much better. I still see, like, category here.
We probably need to fix that as well just because it's gonna drive me crazy. So that is our display template here. We just wanna make sure we're displaying related values. If I don't populate that field, it should show, like, the default. Why is it not doing that?
Okay. I'll just fix it. Just let me fix it. Alright. We want the title here.
Let's add the title there. Make a liar out of me. Okay. So now I can see the category. I can rearrange the fields up here.
This looks good. There's the category this belongs to. Maybe that's second, third, etcetera. Yeah. I could filter those by sending value, whatever I wanted.
Cool. If I open up the category, I could see all the articles within it and this may be the best way to manage my different articles. Right? So eighteen minutes in, we've got the skeleton of our help center back end. Right?
This looks nice. We've got the ability for someone to edit this content, in a nice editor and riggy jig, away we go. Right? So the other component to this, we need a front end. Right?
And I found this beautiful docs template, from mister Tony Tony Zhang. Tony, have you ever watched this? This is a pretty cool ShadCn view docs template that you've created. It looks great. So you've got, you know, kind of the standard docs vibe going on.
You get a lot of components already built into this thing. So let's just go to GitHub. And take a big risk here on hundred apps, hundred hours. I have not messed with this. It looks like you've got, like, a starter here, but we're gonna, like, change some of the nuts and bolts of this.
So, we're gonna abandon my usual Nuxt starter application that I have. And let's just open this up. We're gonna go to the terminal, git clone, shad c n docs nuxt. I think I'm in the right spot. Maybe not.
Maybe I wanna do git clone, CD and then git clone. Let's back up one directory. Looks like it was already in the help center directory. Did that what did we get here? Trash.
Oh, that's in the trash. Let's open a new terminal instance and solve for that problem. Git clone. Okay. So now we have shad c n docs nuxt.
We'll open this up in the terminal. P n p m I. Let's get this thing fired up. And let's just kind of inspect what's going on here. I see an app dot vue file.
That's kind of standard for a Nuxt app. We have an app folder that controls router options. Looks like that is, like, controlling for, like, a sticky header or something like that. This is cool. And then when you see, like, we have oh, that's my own app.
Come on, guy. That's your standard Nuxt app that you have. Right? Why are you doing that? So then we have something like pages.
Cool. So this is using Nuxt Content. Nuxt Content is a really cool, headless kind of content. So basically, hey. We can use markdown, and allows us to use Git as a CMS, basically.
File based CMS. That's what I was struggling with. They've got this MDC format though, which is kind of interesting where I can, like, use a component like this, like hero, and it will generate this. It'll actually generate stuff like cards for you using kind of a markdown familiar syntax, which, again, pretty cool for developers. You know, nice for content editors that they can create like a complex like looking card or something in here.
Could get confusing, maybe not. Let's run with it and see. But we've got this thing installed. Let's just fire up the dev server and see what we can get done with this thing. Alright.
So we'll go to local host. And we're developing. We're developing. Looking good. Zoom out and direct us a little bit.
Oh, that's not what we want. Come on, baby. Come on. That first time's a little bit slow. Don't be shy.
Okay. So this looks pretty good. We've got an index here. This is a content renderer. I don't know where this is picking up the content from.
I'm assuming it's coming from this index.md thing here, and you can kinda see what's going on. This is the home page. We've got effortless and beautiful. We'll just change this. Bryant's hundred apps, hundred hours, starter, help center.
Using cursor here. It's got nice auto complete. I I that's probably the main reason that I love it. It's a little more intelligent than, like, the Copilot for stuff that I'm already gonna be typing. This is a help center, but with a hundred apps, hundred hours starter.
Great. We don't need this iframe. Cool. We're gonna get started. There it is.
Great. We could leave the buttons. Cool. This is gonna be what? To where do we wanna navigate to?
Let's go to slash, what was our doc that we had? Right? We've got accessing items that is that's what we'll do. Right? Accessing items.
If we remove this link to GitHub, we save it. Something broken. I broke something. Why is this not working right? Actions.
Okay. There we go. That's gonna take us to accessing items. That's a four zero four. Bummer.
No big deal. Alright. So this got this content directory that we're pulling from. Okay. Great.
We can see it's using that that Nuxt content here. Nice feature. Great. I'm just gonna like slap, I'm gonna copy the index file, honestly, from my other starter that I have here and I'm just gonna stick this in index because I'm lazy. Alright.
So now you can see this is my standard starter index file that we'll see. I'll just remove that. Hundred apps, hundred hours. NUC starter. Boom.
There it is. Great. Cool. But I should probably have a button actually to go to one of the individual pages, though. Right?
Let's keep that. Accessing items. Get started. And I'm doing this because I don't want the actual Nuxt content pieces of this. It's okay.
Nuxt u button. What? Nuxt link? Or should it be UI button? UI button.
Where is our where is our UI button? There's our UI button. What other props do we have as a button? As a as Nuxt link? Can we do that with this thing?
Will that actually work? Is it gonna like that? Atrial? Why is it not it's not liking that at all. I don't know.
I don't know why. What if we just do a regular a? Okay. There's our tag. Obviously, that's gonna hit us with like a full page reload, but no worries.
Alright. So what we're gonna do, I'm gonna create a Directus plug in for this, Directus.ts. And to save myself time, invoking rule number two, use whatever you have at your disposal. I've already got a sample Directus plug in in my starter. So we'll just pull this across to plug ins.
Alright. Now if I can go full screen on this. I should put it in the wrong window, Alright. So first off, we need to install the Directus SDK. I'm not gonna use cookies here.
So do we really need authentication? No. We don't need that from the SDK. Let's not even use real time or read me. We're just gonna use the REST API.
Gravy. I'm gonna get rid of this bit about authentication and this bit about that. And all we're gonna do here, pretty easy, pretty simple, we are fetching a direct as public URL from the Nuxt runtime config. We are creating a directus client and then we're providing that back to the Nuxt application so we can access that in multiple places. So now we're gonna install directus SDK.
Solid. And I'm gonna find the Nuxt config for this file. And then we're gonna add, probably need an env variable. Is there a dot env file already? There's not.
We'll call this Directus URL. That's gonna be HTTP local host 8055. That's just what I'm running on here. Great. And then I'm gonna find what's looking for our runtime config.
Public, direct us URL. You can see this is already picking this stuff up for me. Another nice benefit of cursor. And then so we've stripped out. We didn't really strip it out, but let's strip this out.
We don't need that. For our slug, what do we wanna do? What do we wanna do? We've got, why is script set up not at the top? This is again, just my OCD kicking in.
There's some lint rules set up here. E s lint config. Delete. View block order. Oh, let's change that guy.
Alright. Is that gonna fix this now? Script setup. Script. Okay.
Alright. Changing some rules there. We're we're cooking with gas now. Alright. So we could see what's going on here.
Like, this is like pulling this content in from markdown files itself. That's I don't wanna do that. I'm not gonna do it. But now we got this nice directus plugin that we can use and that'll be directus URL. It should be a string.
Let's just fire this up. There's one other thing that I'm going to add to this and it is the I I know because I've worked with this thing before. It's the Nuxt MDC package, which is basically doing some of the heavy lifting under the hood as far as, like, the taking the MDC format and, you know, generating that AST that we can then use to render with. So, we'll p m p m I at Nuxt MDC. And you can see here there is like this parsed markdown or parse markdown function that we could call.
Then we can render that markdown like the body and the data format. Alright. So we've got those two things. Let's fire up this dev server one more time and we'll see what we could do as far as a slug. Right?
So now we're gonna do something like this where I'm gonna import read items from the direct Us SDK and I'm also gonna pull in that Directus client from Nuxt app. So the SDK is very modular, so I don't have to import all the methods that I'm not actually using. Right? And Nuxt will do some fancy, tree shaking magic for us based on the the individual routes. So should be all great.
What we're gonna do here, we'll do something like this. We'll do constant data and then we're gonna do await, use async data. Okay. So we've got this async data composable from Nuxt. We're gonna give this, we want let's also pull in the route for this as well.
So route equals use route. We're gonna pass this a key to use. Alright. So this will be page this will be article let's use a back tick here. Article dash route dot params.slug.join.
Maybe. If that's an actual hooray. Okay. Here we go. This is not right at all.
This is one of those times that you may not want to totally trust. We're gonna return read item no. We're not gonna return that. We're gonna return directives dot request. Read items.
We're gonna get the articles. And then we can define a query. Right? So our query is gonna look like this. We got the filter, and then the slug is what we wanna filter on.
And we want that to be equal to route dot params dot slug dot join. I'm I'm not even sure we actually need that. I can't remember the format that Nuxt is gonna give this to us in. We could call this actual data page. And then somewhere in here, this is where this is read items, we want to do a transform on that async data call.
Transform. Data, data zero. So we're gonna get the first item in that array. This looks good. Directus, directus dot request.
Data page. Script setup tag. What am I missing? Did I goo something? Directus request would read items.
Oh, I didn't miss something. There we go. I think that gets us where we wanna be. Alright. So now let's just open this up, test this out.
Okay. Unexpected token, define page components. Let's just ignore all of this baloney right now. Got page, invalid URL. Well, that's not great.
E n v, direct as URL. K. Nux config, direct as URL. I don't need all of that. Direct as URL.
Oh, that's in the wrong config file. Let's just copy that. Nuxt config, shad c n docs. Cool. Why is that not showing as directories URL as string?
I Wonder why that's not showing an error here. TypeScript error. Nux config. Wrong Nux config. Unexpected use of the global variable.
Why is that unexpected use? Fix with AI. What does it come back with? Import dot Neta dot e m v. That's not gonna be right.
PNP m dev. Maybe that's where we didn't have that the first time we started the dev server. Not a %. Articles, filters, slug, param. And we can even do let's just console log the route dot params dot slug.
Slug. Okay. So now we could start to see what the problem is here. Slug needs to be does need to be joined. Slug.join.
Dodger, hon. Slug accessing items. Why can't we fetch that page? What's going on? There's our slug.
We could see the slug. Great. Why can't we fetch this actual page, right? If we navigate, we go back. We should see, like, a fetch request here from Directus.
Twenty minutes. How are we doing? How are we doing? We're not doing great, Brian. Not great.
Alright. We're we should see a call to direct us somewhere. Local host. 8055. Not seeing it.
Alright. Accessing items. Oh, it's because we're not using a link on that index page. Server side rendering. Fun stuff.
So is there a link in this? Links button link button link button link to okay. So we should use button link, content button link. What component does that get us? Does that get us where we wanna go?
Kind of? Kind of not? So we see a lot of stuff coming from, like, the Nuxt content API. We don't really want any of that business. Don't want that smoke.
How can we strip all this out? Right? Can I just is this gonna can all this? This is gonna break a bunch of stuff, isn't it? Umami client, I don't want that either.
Slug. Okay. If I just trash all of content, what happens if I disable Nuxt content entirely? Nuxt image, you use Nuxt. Chat c n Nuxt.
This could go way wrong. It's always fun, though. Right? Let's just remove content. You where are we using use content helpers at?
Right? I guess I should be looking at these individual things going on here. Use content helpers. Where's that at? Aside.
So we gotta decide. We don't even care about that. What does our where are our layouts? Do we have a layout? Components, where where are you?
App dot view. Layout header, layout aside. Let's just remove the aside. What what's in the header? Layout header, Use config.
Okay. Main setup. Use content headers. Search dialogue. Come on.
Why did you do that, Brian? That doesn't make sense. Use config. It's gonna break. Header, main, new key from value path.
Page dot value dot main. Now if we just strip that out, what what is left? So many fun things here. This is a good reason not to use your own template, or this is a good reason to use your own template. Where else are you use content helpers?
Don't want you. Where is search dialogue being used at? Search button layout, search dialogue. Search button. We'll just remove that.
Can I actually get something loaded? Stressful. Stressful. Stressful. What are we working with?
Nineteen, twenty minutes. So we're back to this slug catch all route. Can we even console log the page? Let's see what we're getting back from the actual page here. Looks like we're struggling to not render any of this, so I'll just fall back on one of my popular patterns that you'll see in a bunch of other episodes of 100 apps, one hundred hours.
We'll just do this. Div. Okay. Cool. So now we can actually see that we are getting some content.
It's just that we're not rendering the content properly. Bada bing bada boom. That's a problem. Right? Alright.
So now let's hop into this Nux MDC business where, hey, we're getting some markdown here from something. Can we just use this n d c component to render this markdown? Alright. So I'll go here. This will be page dot it's not body.
It's page content. What will that actually render, if anything? View, hydration, mix, match, can't find smart icon, can't resolve, KBD. Do we see a MDC component? No.
I don't. And why? Because we did not add this to that. So we want at nuxt js slash mdc. I think that's correct.
Nuxt mdc module. We're gonna add that to our modules. P m p m dev. We'll restart this guy. Oh my gosh.
Did I put this? Okay. Don't do what I did. Do not put this in the same directory as your normal stuff. Ugh, I feel like an idiot.
Okay. There we go. Fire this up. PnPM dev, we'll run it again. We'll wait for Nuxt to run this out.
And is this actually going to work the way we want it to once it spins all of this up? We are cruising on seventeen minutes. Can we actually show these files? Bada bing, badda boom. Cannot find compose.
Where is this coming from? Cannot find module composer. Shadcian YAML. Shadcian docs YAML. Package YAML.
Types index, run model v runner. What are we doing? Theme, CSS, directory. Nuxt instance is unavailable. P m p m I.
When all else fails, just blow away all of your Nuxt stuff. What have happens if we do the node modules? PMPMI. Let's try this one more time. Or it could just be that I've totally broken this thing by stripping away the Nuxt content piece.
Probably would have been better off just starting with our Nuxt boilerplate that I already had. Not saying this is not a good piece of kit, this Shadc and Nuxt template. Just saying if you're gonna do this, don't try to learn that and do this at the same time. Trying to think of what this would even be. That's the Nux icon TS config base URL.
Hopefully, this thing will spin up now. Hundred apps, hundred hours, starter. There's that. It's not finding a smart icon. I don't know what the smart icon is.
Not really super concerned about it. Alright. So here's the page. We could see this is the value that we're getting from the page. Failed to load the resource.
So it's not actually rendering anything. Right? So that part of it sucks. Don't like that. Let's actually try this import parse markdown.
So if we get the content, we'll do page dot value dot content. Should we even use, like, a computed prop for that? You shouldn't put side effects in in that. Right? Page value, content, slugs.
Let's try console dot log content. What if we do console dot log page dot value? Just see what we're getting here. We want to await that. Wait that.
What is this? Man. TS config. Build transpile. I'm not gonna I'm not even gonna use Shiki, but it's probably gonna throw a fit because we've got some components inside this thing that are using it.
The fun of using someone else's template. Why? Where is this even coming from? If we search all inside here, YAML, Nux config, app config. So there's a lot of this in the app config.
It require Nuxt YAML. Where is YAML? Is that it? Composer dot JS. Module helpers, vite node, types node, use config, editor config.
Yeah. This is this is wack, man. Alright. Pivot on the fly. Bad Chad c n Docs Nuxt.
Just delete you, sir. Now, again, this looks like a a great template. I just don't have enough time. I've got eleven minutes here. So we are getting pretty desperate at this point.
We are gonna do I guess I shoulda took what I had before we just ripped it all out. Right? You live, you learn. V base script. I want script setup lang t s.
Alright. Now alright. So we go to this slug. That's gonna be inside the pages directory. We don't really need auth, but let's go back to what we had.
Pnpmi at nuxt js slash mdc. That should get us what we need here. I've already mistakenly put that into the Nuxt config. And here we're gonna use routes. Use routes.
Import. Read items. Read items from direct us Nuxt. Then we'll use constant data of the page. We will await use async data.
Give this a page, page routes dot params.slug dot join slash. Great. Okay. Then we've got the actual function we're gonna return. Return, read items, pages, filters, slug, not even close.
Directus dot request, read items, pages. Still not even close. Boys, come on. Cursor is not not savvy on this. Filter.
It's slug. You're just getting in the way at this point, aren't you, friend? And then we will pull in direct us from Nuxt app. We hit page. This gives us what we need.
P m p m dev. Parse markdown. Pull that in. Alright. So now we want to parse the markdown content.
Console log page. Console log content. We'll just do pre content. What is that actually gonna render, if anything? Oh my gosh.
Failed to resolve import blah blah blah. Does this actually work? Gosh. Fix your template, homie. Fix your template.
Alright. I'm sure you guys are having fun following along with this disaster show here. PMPMI. Delete. PNPM dev.
This is probably like a type error, I'm assuming. Fingers crossed. Or we might just have to hang it up on this one. I hate to be defeated. I really just wanna show some of this content, and I wanted to try the, like, the actual components where you can do MDC in here.
Oh my god. Failed to load. BMPM lock. Delete. Here's what we'll do.
If this doesn't work, I'm done. Nuxt. Node modules. Delete. Nuxt.
Do we have the MDC in here? Nuxt MDC. Where are you? There it is. Nuxt MDC.
Alright. Let me fire this up one last time. We got this. You got this next. Come on, baby.
We've already got our plug in here that should be working for us. We can strip all of this out, just comment it out, basically. We don't need that. Don't need any of that. Okay.
Everything's installed. PMPM dev. I think we need, like, a blooper reel, but maybe that would be every episode that resulted in just nonstop bloopers. Okay. So far so good.
I don't see any major errors coming through. Cannot resolve Tailwind CSS. Are you freaking kidding me? PMPMI, Tailwind CSS at next. Sometimes it just doesn't work out in your favor.
I think that is like 90% of modern JavaScript development is wrestling with dependencies and bundlers and config. Honestly, I spend way more time doing that than I do actually developing stuff. Non pojos. Does this have to have Nuxt Content installed? PMI Nuxt content.
What is the name of this package? Content dot Nuxt. At Nuxt content, I'm assuming, releases. You can start with a fresh I wanna start add to a project, add Nuxt content. I swear if this is it, I'm gonna be so mad that you just have to install this thing.
I thought I was being clever showing you guys this Nux MDC stuff. I've messed with this before. I've got it working previously. Obviously, a little little rusty. Alright.
So let's say we do wanna do, like, this alert thing. What is this thing doing, man? What? Where is Nuxt YAML? Where the hell is this coming from?
Can I find Compose? Compose.js. Where where is this even at, man? Composer requires to CJS loader YAML, feet runner. I'm not loading any YAML.
YAML. Do I have something in the content directory? No. Freaking no, man. If I remove this parse markdown, does that fix it?
Page dot contents. Okay. Yeah. So it renders something here. Console log.
Page is undefined. That could be why. Not even getting a page. That's why you don't trust, don't trust AI, friends. Page dot it's not even page.
It shouldn't be page. But page return request direct us articles filter slug equals route dot params .slug.join. Okay. So now we can see the page. We need to go back and add our transform option.
Transform. Get our data. Hey, yo. There's our content. What do we got?
We got a minute and forty seven seconds left. Amazing. Just freaking amazing, honestly. H one page dot title. Class text three x l, font bold.
Let's add a container to this. Right? That'll give us our page. Amazing. Is that really what it was?
Now is this actually gonna work? Content. What if we show, like, MDC render value equals content. No. It's it's still not gonna shove that down, is it?
Well, well, well, well, mister Bryant, it does not like you. Anyway, we got remotely close. Nah. We really didn't. We've got the help center, like, part of it set up.
Didn't even get into any of the, like, fun MDC component stuff. Roll credits, guys. Yeah. Recapping this, it was a bit ambitious to dive into a template that I had never used before and was totally set up for local markdown files. And I think I could wrestle that in an hour and actually show you how to render Vue components from content, delivered via the CMS.
But, hey, sometimes you win, sometimes you lose. Just gotta keep rolling the dice. Alright. That's it for this episode of hundred apps, hundred hours. We'll catch you on the next one.
Thanks for joining.