Bryant builds a Guru-inspired knowledge base with bite-sized information cards accessible through a Chrome extension. Watch as he creates a Directus backend with verification flows, then builds a browser extension interface that makes company knowledge searchable and editable on the fly—despite a tricky bug that nearly derails the entire project.
Speaker 0: And we are back with another episode of 100 apps, one hundred hours. I'm your host, Brian Gillespie. Welcome back. I'm here for Directus, by Directus something something. I I don't know.
I'm trying to be fancy here. Not my forte, obviously. Dad of three little girls, gave up being cool a long time ago. But today, we have got a cool episode for you. We are going to be tackling an internal knowledge base.
I'll explain what that is in a moment, but if you're new to 100 apps, one hundred hours, there are two basic rules. Number one, we have sixty minutes to plan and build your app, your clone, your idea, whatever this is. You get no more, no less. And rule number two, the anti rule. The no holds barred WrestleMania action, use whatever you have at your disposal.
This is a no holds barred cage match, basically. So let's talk about internal knowledge base for a moment. When I used to run a customer success team, at a previous company, there was this product called Guru that was basically an internal knowledge base. You know, we used it for a lot of our chat support team. Also our CSMs, you know, if they had a question, we could easily document this.
And the cool thing that they did have was this Chrome extension that would basically give you access to all the knowledge base. And, you know, the structure was very bite sized pieces of information, and that was the whole idea behind it. So we're gonna try and replicate something similar. You know, anytime you have something like an internal knowledge base, if it's not in everyone's face, the knowledge goes stale. If it's a pain in the butt to edit, it goes stale.
So let's tackle that challenge. We're gonna put sixty minutes on the clock. Let's let's ride. Let's wrassle. Alright.
So, functionality for this specific app. Right? And this is me probably biting off a lot more than I can actually chew in sixty minutes. But what we're gonna do, we're gonna build a back end for the internal knowledge base, And then we're going to build a Chrome extension to search search articles, edit articles, and that's probably the extent of maybe what we'll get done in an hour. I don't even know if we'll get this done.
Right? But, we need to kinda flush this out further. Let's go in and map some data model. Map this out. Right?
So at a high level, we're we're gonna have users of this application, so we'll have some authentication, etcetera. You know, they'll be able to log in. As far as the actual knowledge itself, I like the term cards for this. Instead of articles, that's what we're gonna do. And the reason why is these are bite sized pieces of internal knowledge.
I think that's a helpful paradigm. As far as the fields that we want, we're gonna have a title for the card. Maybe I won't even get into, like, AI generated summary of this. We may use some AI stuff to, like, dive into this. Let's have an owner of this card.
Like, who owns this knowledge internally? We've got the actual content of the card for sure. You know, maybe we got some tags for the cards as well. And then, of course, we have tags. Let's say there's a title for the tag and then a topic or an area.
Right? I think that's a good structure for tags. Like, in in the case of Directus, that may be, like, features or frameworks or something like that. And then we'll have users. So and a user owns a card.
Tags are connected to cards in some form or fashion shape, form, or fashion to quote the West Virginia governor here. This is a many to many relationship between cards and tags. Right? A card could have multiple tags. A tag could have multiple cards or a single tag could be applied to multiple cards.
So that is the data model setup we are going to roll with. You know, if you've watched this before, I've got, like, a standard Nuxt starter that I use for this. But, on the front end, we're gonna try this Chrome extension Vite starter from, mister Fayezara. Fayez Fayez Ahmed. I think that's his name.
Yep. Fayez. Hopefully, I'm pronouncing that right. If I'm not, I apologize. But, let's focus on that back end first.
Right? We are going to zoom way in and let's create our first collection. Right? Let's call this cards, and I'm gonna give these a generated UUID. We'll say when the card was created, who created it, when it was updated.
What's the status of the card? You know, this could be helpful if we have, like, cards that are draft or not approved or not verified, I would say. That should be like the one of the first states that we have for this. And then we'll add a a sort order, I guess. Why not?
Let's see if we could find a card. So this is a looks like a memory card, a SIM card. It's a good icon for this. Great. I'm just gonna hit command s to save this and stay.
And let's start with the title. So straight input field string. We do wanna require a value for this. Right? Great.
You know, we could potentially index this field if we want to inside the database. That's what that's for. Do we need to trim? We don't need this to be URL safe, so we're gonna roll with that. And then what else do we have?
We had an some content for this. Let's go with the WYSIWYG editor. We'll have some content, you know, and for, like, AI heavy stuff, we might even, like, set this to be markdown. Basically, behind the scenes, these use the same type for the column inside the database. And what Directus is doing behind the scenes whenever I add this field is basically just creating a new column inside the cards table inside our Postgres database.
So for now, let's, let's go to the markdown interface just to appease our developer friends. And let's say we'll auto format the display for this. Cool. Great. Gravy.
Amazing. What else do we need? Right? We wanna assign ownership of this card. And, you know, maybe we even want to have, like, a date verified.
So let's take care of the ownership first. Right? I'm gonna add a many to one relationship here. So I'm gonna just call this the owner of this card, the related collection. Whenever you spin up a Directus instance, it gives us, some system collections that it prefixes with Directus so that all of your your SQL stays pure, which is nice.
And then we're just going to add the Directus users collection here. So this is what the instance uses for authentication, you know, into the studio and via the API. So we'll just piggyback on that. Right? We'll assign a user to this.
And for the display, cool, great, everything looks nice. We'll display should be an option to display the user. We could show the user in a circle. That will look great. And let's move that owner beside this.
We want to show the status. Date updated. So there's the status title owner. And maybe we want to switch that around. Basically, what I'm doing here is just controlling the form for anybody using the back end of this.
So let's make the title full width just to give that proper weight, proper gravitas. Here's the status. Maybe we wanna update that from draft to you know, it's not necessarily like we're concerned about whether this is published or not. We just want it to be verified. So, like, internally, you wanna make sure that that content is totally verified.
So that's what we'll do. We'll call it verified. This is archived. Cool. We could copy these choices and just paste those into our labels.
And I don't wanna show as a dot. I just wanna show each actual label. Alright. So next, maybe we add a time field, date time. Let's do this as time stamps.
We'll just follow the same convention, date verified. Cool. Awesome. Alright. And we'll come back to that in a moment.
This is our cards collection. Right? Let's call this direct us features. I'm gonna assign this to me, the admin user, and we will here's all the amazing features of Directus. Great.
REST APIs, GraphQL APIs, APIS APIs. There we go. Insights, permissions, whatever. Right? Great.
There's our preview for the markdown. You know, if we decide to do some AI, you should later this is gonna be a a friendlier format for that. Great. We've got a card. Cool.
We can move this around. You know, let's add just a a hook to this using some flows to automatically populate the date verified. Right? So, anytime I verify a card, let's say a card is updated, updated or created, card is updated, created. You know, we could be add verification stamp.
Alright. And basically, anytime a card is created or, you know, let's just say updated in this point because the default should be like draft, the state for all of the cards. Anytime a card is updated, let's go in and let's make sure check the status. Check status. Alright.
We're just gonna create a condition here and this uses the standard, filter rules inside Directus. What I'm gonna do is just copy our template here. We're gonna adjust this a little bit. Payload dot status. We'll drill in one more layer And if the status is equal to verified, we're gonna run some action after this, right.
So inside Flows is a great way to add simple automations to your back end And there is flow control already built into flows. Shocker. Right? But if this condition passes, we're going to take action on it. If it doesn't pass, meaning the status is not updated or it's not there, it will, you know, follow the rejection path.
So in this case, you know, I I could log something to the console. In this case, I'm just going to, run a little script. Get current time. Right. We're gonna return, what's new date?
Is that gonna be two ISO? Is it two ISO string like that? New date to ISO string. Is that what we're looking for? New date to string to ISO string.
That should be what I think that's what we're looking for. So we're just gonna return the current time. Great. And then I'm going to update the data. Update card.
Cool. So we'll do cards. We can use the permissions from the trigger. And I'm gonna say this should be dollar sign trigger dot keys, the first item in that array. Not a % sure, but, date verified.
And then we'll do something like this. We'll just use this mustache syntax, git underscore current time. Great. Cool. Let's see if this actually works.
Alright. So this is good. These are all amazing features of Directus. I'm gonna verify this. I hit save.
And voila. Now we could see the exact date and time that I verified this thing, December 3 '10 '14 AM. Amazing. Sweet. Right?
Alright. Let's go back and continue our March onto our data model here. So let's set up some tags. I'm not really concerned about when these were updated, etcetera, blah blah blah. You know, maybe we wanna sort the tags, but, let's find a tag.
We could use the hashtag. That's what tags are for. This is a title. Cool. Title of the tag.
That's required. And we'll keep keep updating. We don't wanna change just yet, my friend. And then the topic. Right?
What are we gonna call this? Area topic? I think I like topic for this. I still wanna keep the string. I don't think there's a need for extra topics, but what we'll do, we'll just pick the options from a drop down.
Right? So in the case of Directus, you know, this could be features features of Directus. Makes sense. Frameworks, like next Nuxt, etcetera. Frameworks.
Can we get another f one? What else is this gonna be? API, API, pricing, you know, the pricing of direct you know, these could be infinite, and maybe that's, you know, not not a great one because that could be just like a a side effect. Cool. So now we have tags.
We want to create this relationship between the two, and it doesn't really matter where I start here. All roads lead to the many to many relationship. If I'm on the cards collection, I'm gonna create a new field. We're gonna call it keys or I'm sorry. Call the key is gonna be tags.
I need more coffee today. The related collection is gonna be tags. We don't wanna allow duplicate tags. We wanna show a link to this item. But what I wanna do here, I'm gonna open up the advanced field creation mode, and you could see what's going on behind the scenes.
Directus is creating a junction collection for us. I'm gonna change the names of these just for my own anxiety, I guess. So we're gonna call this card tags. So these are tags on a card. The junction field or the the foreign key is card for the card, tag for the tag, and then we're gonna add this corresponding field to tags as well.
We're gonna call those cards, and then the sort is gonna be sort. I'll just set these to delete the junction table item in case we deselect a tag from any of these. There's no reason to keep, the extra info in this junction collection. Great. We'll display some related values and away we go.
Right? Now I'm gonna set like a default display template here just in case we're using that in some of the views. We'll do the same for the tags. We'll give that a title. Maybe we wanna show the actual topic.
Cool. Topic. Great. Boom. Boom.
Boom. Boom. Boom. We've got all the relationships. We've got everything configured.
This is a feature tag. We don't have a tag for features. Well, we have a topic for features. What is this gonna be? This is, REST APIs.
Cool. Directus REST API. It's awesome. Cool. Alright.
So there we go. Now we have some tags. We have title. We have some content. We have the tags here.
I can see all the cards within that. This is looking freaking sweet as far as the back end. Like, if I want to fetch all my cards, I could just open up the direct assistance. I'll swap the admin side of this. I'll go to items cards.
Here I can see all of that. And one of my favorite features of the REST API is the ability to do stuff like this where I can say, hey, I want all the root level fields. That's what this wild card is for. And then I also want all the fields for the tags. So you could see here, this is I'm actually going through the junction collection.
So I probably wanna go one step further and do this. So I can actually see, okay. Here's my tags. Here's the tag. What's the title of the tag?
What's the topic? Etcetera. And I, you know, that's not really recommended for production use. Right? I would probably wanna be more specific so that you don't end up with, like, six levels of recursion because you could see the cards start to show here.
Tags dot topic. Cool. There we go. There's the tag. There's the title.
Topic. You know, I could go in and keep going with this. You get the idea. You get the picture. Alright.
Let's bring that back. So I've still got access to my direct as admin. And then we are going to fire this thing up. Is this gonna go well? I do not know.
So we're gonna pull this up, and I'm probably better off, like, starting a new directory for this. CD sites. Cool. We're gonna, like, what? Git clone?
Can I page? Git clone. The extension. Okay. CD, the extension, and code dot.
Is that the, that's not gonna open it in cursor. We're gonna cheat. Is it really cheating? I don't think so. We're gonna use cursor today.
Alright. So looks like what do we have? We got PMPMI, kinda your standard. So we'll wait for this terminal to pop up. PMPMI.
Okay. Come on. Come on. Core pack. Do I have to enable core pack?
Core pack enable? Core pack enabler. That's what I am. User local core pack target in this. What is going on here?
CD my extension, cloned to local. PMPMI. What is going on here? Unexpected identifier core pack. Is this just like a bad terminal instance?
PPMI. Yeah. Wild. Okay. I guess the shell wasn't loaded yet before I fired this thing up.
Alright. So now we'll do p m p m dev. Never used this thing before, so it should be fun watching me sweat. What are we gonna do here? Then load the extension in the browser within the extension folder.
Okay. So, I am using Arc. I'm gonna switch over to Chrome for this. I'm gonna drag this out of the way. You know what?
I I do like Arc. There are some frustrations with Arc, but, you know, it is what it is. Let's go to where is it? Slash extensions? Extensions?
We'll just manage our extensions here. Let's load and unpack extension. You can see I've got, like, Vue already installed on this one. Extension select. Failed to load extension.
What are my docs saying? Extension extension dev, I guess. Let's try the dev folder. Okay. We got v extension.
Cool. What is this gonna do? Can we pin to the toolbar? Tim the toolbar, Taylor. Okay.
Cool. So now we have this cool little extension. Alright. Dark mode, airplane mode, VPN. I don't know what any of these settings are doing, but, this looks cool.
This is our little pop up widget. Right? I'm assuming somewhere in the source folder here we can find what we need for this. Alright. So this is kinda structured.
I I've worked on Chrome extensions a little bit in the past. Let's see. We've got the pages. We got an app. So we're showing a router view, which is nice.
So we can navigate between these specific things. We've got pages, index.HTML. We have the module. That's the specific pop up. You know, we've got, like, content scripts and things like that.
I'm assuming if I open up this, this will say hello from content script. Let's actually for now, let's just focus on the pop up side of things. Right? I don't so much care about the settings here or the about. Where's the about page?
That's the profile page, I'm assuming. Profile page. Put your own content here. Cool. Alright.
How are we gonna get started with this thing? Let's see if we can actually just fetch a list of our articles, and we're gonna take over the home page here. The first thing I'm gonna do is move this script setup to the top. We'll do lang t s typescripts. Great.
This has already got Tailwind installed, so I'm cruising there. Let's call this the we'll give this a little header actions. Is it articles, cards? Directus knowledge cards. That sounds great.
Knowledge cards. Okay. Div. Great. Yeah.
We'll do flex call. Okay. I'm I'm gonna roll with you there. Now as far as the components, let's not over engineer first. Okay.
So now we get into, like, our first kinda inflection point here. We want to PMPM install the Directus SDK. Awesome. We'll put the SDK in here. We'll import where am I gonna stick the SDK clients?
Util services, you know, we could call it that. Services. We will create a directus.ts file. We're gonna import the rest. We're gonna create Directus from the Directus SDK.
Read items, read item, update item. I'm just gonna import the whole house here. Right? Create an item, delete an item. And one of the nice things about the Directus SDK is how modular it is.
Right? So I can only I only have to import the items that I actually need. And I'm just gonna hard code the app URL here. That's our Directus URL, 8055. Create Directus.
Okay. And then we can export Directus. Do we want that to be you know, let's call it export cons. So I could still, you know, access Directus. But also let's, let's carry this further and just get like a a function.
Export async function. Get cards. Get cards. Cool. Yeah.
Maybe we wanna potentially pass like a like params for that. We're gonna commit typescript no nos here. We'll just slap any on there. And what we're gonna do here, we'll say cards. We're going to what?
Await. Directus. That's not that's not a good auto completion cursor. Alright. So we're gonna say read items, knowledge cards, params.
We're gonna return the cards. Get card. Yeah. There we go. Okay.
Now it's starting to get the picture. Right? This is one of the reasons why I have adopted cursor is because once it zeros in on, like, the logic for how you do some of this stuff, it is pretty good about actually taking care of it for you. Right? It's not gonna be knowledge cards though.
And that could be solved by actually giving it, you know, like a TypeScript definition of what our types are, which you could potentially grab from the Directus open API spec. Alright. So let's go back to the pop up. Now we've got the service. We're going to import get cards from at services.
I hope that is the actual alias for this. We'll we're about to find out, honestly. Do we wanna do cards? Why would we do cards as a reference? Cards equals await get cards.
And are we gonna pass any params? Let's just get all the fields for the cards. It failed. Services from Directus. Yeah.
I kinda figured that was gonna be the case. Okay. Now we've got that. Let's just go in. Oh, we've got this.
We could format this a little bit. One of the first things I like to do just to make sure I'm getting the data that I want is just output this thing. So we'll save. Refresh. Can I actually see the network requests that are occurring through this thing?
Inspect? What does that do? Does that give me okay. So now we're here inside the oh, as soon as you throw the pop up away, it disappears. Inspect.
Is there a way to save this? The pop up is gonna disappear on me. So if I go to here so wait. Get cards. Are we actually finding that?
Pages pop up. Dot.services.directus.js. Is that where how we should import this thing? I don't see nothing. What's happening?
Maybe we should actually wrap this in, try catch so we could see some errors. Right? Try return cars. We'll just log the errors out. And now if we pop open the console, right, should we see some errors happening?
Console failed to load. This is forbidden forbidden. We can't access this. Why is that happening? I kinda thought this would be the case.
Right? So by default, whenever I create new collections, Directus does not provide any access to those collections. Right? So if I look at the Public Access Policy, I got nothing coming from that. We got thirty minutes on the clock, so for now let's, let's just grant full access to this.
We are working locally. You know, if I was going to basically go to production with this, obviously, I would implement authentication. Maybe we can circle back to that. But, you know, the core functionality here is being able to update, edit, and rearrange these cards. Alright.
So now with those permissions populated, we save this again. Can we actually see what's going on here? Console component, setup component. I don't see, get cards. Is there a way to actually sticky the inspection window?
How do I do that? Focus page. I thought there was a way to to keep this up regardless, but maybe not for the pop up window. Settings, type error, node. Let's just try to restart.
Let's see what we got. Do we have to reload this extension every single time? Refresh? I sure hope not, but we will if we have to. Now I don't see any.
So we should be able to, like, console log the cards. Here's the cards. Right? Should be able to see some kind of output from that. Inspect.
Console. Scheduler flush view internals. It's not liking that for whatever reason. Right? Maybe we want to do on on mounted.
Cause cards. Response. Cards dot value equals response. Cards dot value.
Speaker 1: Hey. Okay. Yeah.
Speaker 0: It doesn't like fetching when the component is created for whatever reason. Not sure why that is, but there we go. We've got our cards. We could see the cards here. Cool.
I can also do what we talked about where I can say, okay. I wanna get the tag. And where I'm using the SDK, I can also do something like this where we have tags, and then I can provide, like, an object like structure. So within that, we have, tag, and then we have the title. Let's fetch the ID of the tag and then the maybe even the topic.
Tags. Tag. Okay. So now we could see all the info we want. That's working correctly.
Let's, let's actually render out these cards. Right? So we'll do, like, a div. V four in cars key card dot ID. What are you gonna come up with cursor?
Title.subscription. No. There's not gonna be a description for end. Maybe we show the tags within that. So span b four tag in card dot tags tags.
Cool. Rest knowledge card, v API. Class. Let's give them some padding. We'll add a light border, round, large, rounded, l g.
See what that looks like. Okay. And this is actually gonna be is this gonna be router link? Router link is gonna be missing two, a car dot ID. Okay.
And then we're gonna need pages. So what does our actual router look like? Right? Okay. Looks like cursor is doing its thing for me here.
So the path dot card dot ID pages card. So we're gonna create a new card page. Cool. Card dot view. I probably need to import that as well.
Card view. Oh, it is dynamically importing those. Okay. That's fine. We can stick with that.
Vbase TS setup. Move my script up to the top. And then we can, like, nab this card thing as well. But for now, this should solve the challenge. Okay.
So now we can see the card. There's a direct us REST API. Card is looking nice. Let's go back to this. Maybe we give the title a little styling.
Text large, font bold. Okay. We add a little margin to the top of this, give it a border, give a little padding to the top. Okay. So now we got our cards.
We're probably gonna want a, like, a search input as well. Search input. If I do something like this, what is cursor gonna do for me? Input, placeholder, search. We could search our cards.
Cool. And then, you know, we might even wanna do something like this where we have a query, and then we're gonna add, like, a watch to this. Watch search new val. What are we gonna do as far as the fetching? It's actually await get cards unmounted.
And what we could do on the new value, we are going to if new value, cars have we don't wanna search cars that way. We could just use the directus API for this. So let's set up the watch, just to make sure that watcher is actually working here. And I could at least do this on the Directus documentation so we got something nice to kinda look at. Right?
If I change the search here, it should be updating watch search. It's not console logging that new value for the search. Why is that? Because I don't have a v model on the search input. Let's try this again.
Console. Why is the search are we outputting the sir okay. So now we can start seeing that. Great. Does this thing have something like view use already plugged in for, like, a debounce?
I don't see that. But alright. We're we're not gonna worry too much about the debounce right now, and we're just gonna ignore this. Like, let's get to the actual card view for now. And, god, I really wanna change that router, that footer.
We'll just drop the footer off of this. Cool. Alright. So now we can see the cards. Here's the settings.
Cool. Great. How much time are we cruising out? We got twenty two minutes left. Let's see if we can get to actually editing these cards.
So, if we take some of our logic here from the actual home page, we can probably just reuse a lot of this. We could get card, card. We don't need a search. Get card. And, again, I'm not totally sure why this thing is not wanting to card dot value equals response.
Why it's not wanting to fetch properly? You know, if we're using script setup, it should do that for us, but, I digress. It's at a h one. Text two XL border b. P b four.
Cool. And does it sound like tailwind typography in it? I don't know. We're just gonna do div class. Text large.
Oh, we can add a prose class in there just to see. And one of the main reasons I love Tailwind is just the ability to, like, quickly do stuff like this. Alright. Git card. We're gonna git card.
That is in the services.directus.js. Git card. Right? Search is not defined. Why do I need search?
Oh, because we're watching that value. We don't need to watch that business. Alright. Go to home. So refresh this.
We go to the direct API. Why is the ID is not defined. Oh, okay. Yep. We need to pass the ID.
So that's gonna be what? Const route equals use route params dot ID. Are we passing that? Yep. We do have that.
Cool. So now we should be getting that ID.
Speaker 1: What is the oh, we
Speaker 0: had to import that. Forgot I'm not working in Nuxt. Nuxt does all the fancy auto imports for us. So we refresh. There it is.
Directus REST API. We can go home. We can go back to that card. Cool. Alright.
Let's do const is editing. Ref equals false. Does this have auto imports? I'm assuming it does because it is. Let's see.
Auto import, components auto importing, feed plugin components. We'll just import ref to be safe. Right? Obviously, that's already working, but let's give this some padding as well, make this look a little nicer, and we'll add a little margin to the top of this bad boy. Okay.
Alright. So now we have our content. We could view this. Let's add a button to edit this thing. Right?
Flex items center gap for I'll just say justify between, and then we're gonna add a button. Okay. We can edit this card. That's cool. The border b will move here.
Cool. Alright. And if we edit this, what are we gonna use for the editor? View markdown editor. View markdown editor.
What do we have here? What do we have? This is, again, risky business. Markdown editor in v three. Oh, no.
Alright. This is it's not markdown. Base editor. Where are the demos? Import?
Base editor? Oh, I guess we're this just doesn't have, like, some nice syntax. Right? Code mirror editor? Yeah.
This looks way is this too cumbersome for what we're looking for? I probably should have snuffed this out earlier. Right? View editor, MD editor for view. This one's got 1,300 stars.
I don't necessarily want to, like, show the information. We just need, like, a nice editor. Right? And this might be, like, something where we throw throw it back on, like, not markdown, but HTML. Right?
View three markdown editor. View three markdown editor. Should probably just drop something like tip tap into this. Yeah. Let's just go for it.
Okay. So PMPMI, MD editor MD editor v three. Here's what the usage looks like. Let's try to import all of this. This will be the content, And we're gonna what?
Clone that content. Okay. Is editing. So this will be v m d editor. Is that what it is?
V model content. And then we're gonna have a save function. Async function. Save. Await update card, which is a new one that we do not have.
Update card. ID and content. Is editing value. Cool. I don't think there is a save function.
Alright. So we're let's wrap this. Div. V f is editing, and we'll do a button to save. Now is this actually going to go off?
I don't know. Vite server did not start. Something bad is oh, you gotta actually fire up the dev server after you install the thing, Brian. That would actually make sense. Fifteen minutes left.
Can how far can we get on this internal knowledge base tool? Alright. So here we go. Search cards. We can we're not getting the card.
We're throwing an issue. Use ID. Can I use list is outdated? Where do we get in here? A day card ID equals rent route top params.ID.
Error when updating dependencies. What is the view version of this? Okay. So let's do PMPM. I think it's v view 3.5 view at latest.
Hopefully, that gets us the use ID composable that we're talking about. PMPM dev. Okay. Syntax error does not provide an export. Alright.
So that is obviously a problem. We will export update card. There's the data. Update the card, return the card. Bada bing badda boom.
We are going to update the card with the value as well. Constant response, card dot value equals response. Or we can just console log this. And you could see Cursor is doing a lot of the heavy lifting for me here. What else are we getting?
Service does not provide. It does provide an update card. Export async function. Services pages card. It should provide if we can get the card, why can't we update the card?
Alright. So we hit edit. There we go. We can hit save. Card dot value equals response.
V equals true. Shallow false. Update card. Why is the card Card. Well, that doesn't look right.
On mounted card, await card response card dot value equals response. Why is this a why was this an array to begin with? Right? Extensions reload. Okay.
Something is going wrong here. What are we doing wrong? The card dot contents, get card returns the card, read item cards dot ID. What is the actual response that we're getting? Inspects cards.
There's the response. Card dot proxy. So why is it not showing the actual card content anymore? Car dot value. Oh, what is going on here, man?
Do I have something else going on? But I define card way too many times. Response get card. So we get the card. I could see the response.
The response looks good to me. Right? Go here. Go home. You see the the response.
There's the response. Content. Tags. There's the card value. Maybe we set this to content dot value equals card dot value dot content.
Card. Card dot title. What in the world is going on? Dep. Why are we loading?
I'm not comprehending something here. VF card. VF card. We are seeing the car. Cannot read.
VF card. How is the card dot title this is what I'm struggling to understand. Cards. There's the cards. There's the card.
Card dot value. We can see the title right there, card dot value. Unref. Guard. We are running out of time.
What is going on here, man? Where did we go wrong? Is it when we brought in the MD editor business? Alright. So this works.
Yeah? Or it should. Some new, like, quirks with Vue. What is going on? I pulled in the latest version of Vue, and now we are, like, dying here.
Dying on the vine. Car dot value equals response. Is there, like, a weird thing that I'm not picking up what I'm putting down here? Why does this work? And that doesn't.
Cards ref. This is the exact same logic from the home. On mounted async, we get the card, Cards dot value dot response. Is this storing is like a lots of fun all the time. But cards.
Click the card. See the card. There's the card. It is an object as it should be. Card dot value equals response.
I don't understand. V f card has a value. Do we have to specifically say the value dot title? No. You shouldn't have to.
Not in the template. Why do I keep getting this error? This would be a good question for AI, I assume. Why do I keep getting this as my content. You shouldn't have to do that inside the the template, though.
Yeah. That's what I thought. You shouldn't have to unref in the template. Right? This is the case where AI, yeah, Check that response on your unmounted callback.
Yeah. Huge help here. Some kinda, like, proxy issue with view, I'm assuming. I don't know. I don't know what the deal is.
Read item cards. Card equals response. Blah blah blah blah blah blah blah blah. Okay. Some funky business going down.
Ref car. Value. Yeah. There should be no need to actually I swear this is like a hot module reloading thing. B is ref true.
What is the actual card, Joe? So if that's the card, why do we have? This is baffling me, man. So there's my card data. If that's the value of the card, should I not be able to access the card dot title?
Card dot content. Oh. Oh my gosh. So that is the freaking problem when I updated and saved this card. This is like the king of deep oh, look.
Sometimes. So I accidentally saved the value as that. We had everything going for us. I blew it all away just to goof this thing up big time. Hey.
That's how we roll here on 100 apps. There was an issue with the save function that called caused the problem here. So let's say we got content equals ref. That'll be nothing for now. The content dot value should equal the response dot content.
So that's the content we're gonna submit. Is editing. God. What an idiot. Boom.
Explosion. There we go. This is one that I man, I really just have to, like, finish this one for my own sake. Failed this mission totally because I got hung up and not actually paying attention. That is the fun of this thing.
Right? So here we go. We got an async function for save. Let's call it save. We're gonna update the card with the content.
We'll set is editing to false. Const response response equals. We'll set the card dot value to the response. Cool. And then let's do this where we say v if is editing, v else model.
We're gonna do wrap that in a div. V if is editing, and then we're gonna add a save button. Class p two blue, etcetera. Click save equals content dot value. Do we have a button?
We forgot to add our edit button. And let's remove this at the top. Give this some padding. V is editing equals false. Vhtmlcard.content.
Here's our content for this card. This is amazing content. Open this back up. There's our REST API. We hit edit.
This shows this freaking thing. There's our editor. Test. Me. I failed the submission.
Great. If we hit save, what does that do? Console update card is not defined. Obviously, we didn't import that. Update card.
We'll try this again. Test, test, test. Save. Of course, there it is. There's the test, test, test content.
Too little, too late, friends. And that's the way it rolls on 100 apps, one hundred hours. That's it for the internal knowledge base episode. Careful of how you say values, man. I never, for the life of me, thought, okay.
Why am I getting this? Surely there would have been an error, boneheaded mistake. That's the way it goes. We'll see you on the next one.