
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
00:00:00Â To start displaying the list of all the existing documents, let's head over to our homepage, which is under App and then Root.
00:00:09Â Currently, we have only the state where the documents.length is equal to zero, which is what we're always showing.
00:00:16Â But now, we can fetch real documents and then list them right here.
00:00:21Â So let's do just that.
00:00:24Â I will head over to room.actions.ts and we already have a create, get and update, but now instead of saying get document,
00:00:34Â we want to fetch all the documents.
00:00:37Â So we can start by copying this entire server action of get document, pasting it below and saying get documents, plural.
00:00:46Â And the only parameter will be an email for the user for whom we're trying to fetch the documents for.
00:00:53Â So we can say email of a type string.
00:00:56Â Doesn't even have to be inside of an object.
00:01:00Â Great.
00:01:01Â Once we get that, we want to fetch all the rooms.
00:01:04Â So we can say const rooms is equal to liveblocks.getrooms plural.
00:01:10Â And we want to get all the rooms where the user ID is equal to the email that we have.
00:01:17Â And believe it or not, that is it.
00:01:19Â We can just say return parse stringify rooms.
00:01:23Â And here we can say error happened while getting rooms.
00:01:29Â Now, if we go back to the page, instead of these fake documents, we can fetch real ones.
00:01:35Â So that's going to look something like this.
00:01:38Â const room documents is equal to await get documents coming from lib room actions to which we need to pass the clerk dot email addresses.
00:01:53Â zero dot email address, and this is supposed to be clerk user.
00:01:58Â Once we have the room documents, we can just map over them right below by saying room documents dot data dot length is greater than zero.
00:02:08Â Then we want to show something that something will be a div with a class name equal to document list container.
00:02:19Â With an inside div of a class name equal to document list title with an H3 within it.
00:02:29Â And that H3 will have a class name equal to text-28-semi-bold.
00:02:37Â And it's going to simply say all documents.
00:02:42Â And by the way, I just want to point your attention to how simple it was to create this get documents server action, because you already have the structure,
00:02:51Â right?
00:02:51Â We have already done it in different places.
00:02:54Â You know exactly where it needs to go.
00:02:56Â And the only thing we had to do is use a different lie blocks function to fetch the rooms and the logic and the procedure and the structure is already there.
00:03:06Â We're just re-following the same steps we have created before.
00:03:10Â So now here we are saying all documents and here we can also add the add document BTN in case we want to add more documents and to it,
00:03:23Â we have to pass the user ID and the email.
00:03:26Â So let's just copy that from here and add it right here.
00:03:32Â Next, we're going to exit one of these divs and form a UL, an unordered list with a class name equal to document-ul.
00:03:44Â And within it, we want to map over our documents.
00:03:47Â Before we do that, we can simply check how it currently looks.
00:03:50Â We have the all documents and start a blank document.
00:03:53Â And now below it, we'll create a list.
00:03:56Â So let's map over the room documents.data.map where we get each individual document of a type any for now.
00:04:07Â And we want to immediately return, so that's parentheses, not a function block, an li for each one of these documents with a key equal to document.id.
00:04:18Â As a matter of fact, we can destructure things out of this document, such as the ID, the metadata, and the created at.
00:04:29Â And now instead of document ID, we can simply say ID right here.
00:04:35Â Next, we want to give this li a class name.
00:04:40Â Equal to document dash list dash item.
00:04:45Â And within it, we want to render a link component because each one of these list items will be clickable.
00:04:51Â And once you click it, it will lead to that document details page or to the actual editor.
00:04:58Â This link has to be imported from next link and it'll have an href pointing to forward slash documents forward slash document dot ID.
00:05:09Â Next we can give it a class name equal to flex flex dash one items dash center and a gap of four.
00:05:20Â And since we destructured the ID, we don't have to say document ID.
00:05:24Â We can just say ID.
00:05:26Â Within this link, we'll have another div with a class name equal to.
00:05:31Â Now within this one, we'll show a document photo, but only larger devices.
00:05:36Â So typically it'll be hidden, rounded MD, BG dark 500, padding of two, and on small devices block because on small and larger we want to show it but on
00:05:50Â extra small we want to hide it and here we can put a next image which we can import from next image and to it we can pass a source of forward slash assets
00:06:03Â forward slash icons forward slash doc dot svg with an alt tag of file, a width of 40, and a height of 40 as well.
00:06:14Â Finally, below that div, we can have one more div where we'll put the title and other metadata.
00:06:20Â So we can give it a class name equal to space dash y dash one.
00:06:26Â And a p tag equal to class name of line clamp one.
00:06:33Â So the text doesn't jump out of the screen and text dash LG.
00:06:38Â And here we can render the metadata.title.
00:06:43Â And the one last thing below this p tag, we can have another p tag where we'll have a class name equal to text-sm, font-light,
00:06:55Â text-blue-100.
00:06:58Â And here we can say created, about, and then call the date converter from libutils to which we can pass the created at property.
00:07:12Â This date converter is a function that I created using chat GPT that'll basically take the timestamp and say how many weeks,
00:07:20Â days, hours, or minutes ago was the document created.
00:07:24Â So now we're showing that as well.
00:07:28Â And below the link, I will add a to do for myself here.
00:07:31Â And that is to add a delete button right here.
00:07:35Â We'll do that later on.
00:07:36Â Finally, if we go back to the homepage, you can see the untitled document, which I created 16 hours ago.
00:07:42Â I did take a bit of a break from recording.
00:07:45Â I'm not sure if you think I do this in one sitting or not, but now you get the idea.
00:07:50Â And then the new title that I created one hour ago.
00:07:54Â So this is the latest document which you created.
00:07:56Â And if you click on it, we get nicely redirected to it, which is what we want it to do.
00:08:02Â Also when clicking on them, I'm noticing that there is a loading that appears on top and there should be a bit of a nicer loading component.
00:08:10Â So we can quickly fix that.
00:08:12Â If we go to a collaborative room, I believe.
00:08:16Â There is a loading in the fallback right here.
00:08:19Â So actually here, we want to render our own loader component coming from that slash loader.
00:08:27Â And now if we go into this one, you'll notice that it's in the middle of the screen and it's actually spinning.
00:08:33Â Great.
00:08:34Â It's about all of these little things that make the application so much better.
00:08:39Â You notice how much code we had just to create this input at the top, but it makes a big difference because now you can edit it and to say,
00:08:48Â my new great title, you can use the Enter key to finish it.
00:08:52Â You get immediate feedback that says saving and even on the homepage, it'll be revalidated immediately.
00:08:59Â That's the beauty of Next.js.
00:09:01Â So with that in mind, our application is starting to look more and more like it does on the finished design.
00:09:09Â We have the homepage, we can create a new document, we can check out the editor.
00:09:14Â But this entire time, I've been telling you about Live This, Live That, all the different live functionalities and real-time collaboration functionalities
00:09:24Â that we're going to implement.
00:09:25Â And you might think, Adrian, but this is just some random markdown text editor.
00:09:30Â When are we going to add collaborative features?
00:09:33Â So far, we have only seen live collaborators on the top right.
00:09:38Â Well, now is the time.
00:09:41Â We'll start adding all the different features like live cursors, comments, and so much more stuff.
00:09:47Â So let's do that next.