
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Â And the next step is to authenticate our users.
00:00:03Â To authenticate our users, I found a very convenient doc page from LiveBlocks.
00:00:09Â Not this one that opens up once you click this button, but I will link it below this lecture.
00:00:14Â It's this one.
00:00:15Â Setup ID token permission with Next.js.
00:00:18Â It's a nice step-by-step guide.
00:00:21Â So let's follow it.
00:00:22Â First step is to install LiveBlocks node package.
00:00:25Â So let's copy it and paste it in the terminal.
00:00:29Â The second step is to set up the authentication endpoint.
00:00:33Â So we can copy it and now we'll create a new API route within our Next.js application.
00:00:38Â So let's close all of the currently open files and go to app, create a new folder called API.
00:00:46Â Within it, create a new folder called LiveBlocks and then within it, create a new file called route.ts and then simply paste what you copied.
00:01:01Â Let's make a couple of modifications to this to further optimize it.
00:01:05Â First of all, I want to extract the part where we set up our instance of LiveBlocks so we can use it in multiple places.
00:01:13Â I'll copy this part and I'll go to our lib and create a new file called LiveBlocks.ts and I'll paste it here.
00:01:25Â Of course, for this to work, we have to import LiveBlocks and we won't leave the secret in plain text.
00:01:32Â Rather, I will copy it.
00:01:35Â And say process.env.liblocks, underscore secret, underscore key as string.
00:01:46Â So TypeScript knows that something will be there.
00:01:49Â And we can say export const liblocks.
00:01:53Â So now we'll be able to use it anywhere.
00:01:55Â But of course, let's head over to .env.local and let's paste it right here.
00:02:01Â liblocks underscore secret underscore key is equal to this key right here.
00:02:08Â Next, we can import liblocks from add forward slash lib forward slash liblocks.
00:02:14Â And we don't need this other instance of LiveBlocks coming from LiveBlocks node because we have already created our specific version of it.
00:02:22Â Next, you can see that they created some pseudo code right here for fetching our user.
00:02:26Â LiveBlocks wanted to be agnostic when it comes to the type of authentication you're using.
00:02:31Â So you're free to use something else.
00:02:33Â In this case, we're going to make it work with clerk.
00:02:36Â So to make that happen, we can say const.
00:02:39Â Clark user is equal to await current user coming from Clark Next.js server.
00:02:48Â And that's it.
00:02:49Â You just call it like this.
00:02:51Â Next, we can do a simple check and see if there is no Clark user.
00:02:56Â We can redirect coming from Next navigation to forward slash sign in.
00:03:01Â Next, we want to form the user in a way that LiveBlocks accepts it.
00:03:06Â So let's simply say const user is equal to an object and give it an ID of Clark user dot ID, and then give it the info where we can provide additional
00:03:19Â information about the user.
00:03:20Â Now we can destructure some of these properties directly from the Clark user by saying const ID is equal to, and that's coming from Clark user inside of
00:03:32Â curly braces.
00:03:33Â And now we can say just ID is ID.
00:03:36Â or shorthand ID.
00:03:39Â We can also get some of the other parts like first name, last name, email addresses, plural, image URL, and that's it.
00:03:54Â So now we can add this additional info, such as ID within the info as well.
00:04:00Â Name will be a string of first name, last name.
00:04:04Â Email will be email addresses zero, that email address.
00:04:09Â Avatar will be image URL.
00:04:13Â And finally, we want to create a special color for each one of these users.
00:04:17Â So we can say color.
00:04:18Â And you could generate randomly any kind of color right here.
00:04:23Â What I would prefer to do is to create some function that would generate it.
00:04:28Â So I believe one of the last snippets you'll copy is this libutils.ts file.
00:04:34Â So copy it.
00:04:35Â And then we can go to libutils and then override everything that's here right now.
00:04:41Â You'll notice that here we have a list of colors that are bright, and then we have some function that returns a random color.
00:04:49Â And don't ask me if this was generated using chat GPT.
00:04:53Â Now, if we go here, we can simply call that function under color by saying get user color from libutils, and we can pass the ID that we can use to automatically
00:05:07Â generate it.
00:05:07Â Now, once we have the user, we're trying to identify that user by their email.
00:05:13Â So we'll say user.info.email and group IDs will be just set to an empty array like this.
00:05:22Â Finally, under user info, we'll pass user.info.
00:05:27Â And this is it.
00:05:28Â So this is the way to authenticate users in LiveBlocks.
00:05:32Â Let's go back to the doc page and see what else we have to do.
00:05:36Â We have already set up the client side and we have added the auth endpoint there.
00:05:42Â So that's good.
00:05:43Â And then we need to set permissions to access a specific room.
00:05:48Â Or in other words, we need to create a room whenever we create a new document.
00:05:53Â So let me show you how to do that.
00:05:56Â For now, I will just copy this part right here for creating a room and I'll create a new folder under lib called actions and create a new file called room.actions.ts.
00:06:10Â Within here, we want to say export const and we want to create a function that doesn't create a room, rather it creates a document,
00:06:19Â which in our case is synonymous with a room.
00:06:23Â So we can say export const create document is equal to an async function that accepts the user ID and the email.
00:06:33Â And that'll be of a type create document params.
00:06:38Â And of course that's an arrow function.
00:06:40Â Before we create a room, we have to get a room ID.
00:06:44Â So we can do that by saying const room ID.
00:06:48Â is equal to, and here you can use any kind of ID generator.
00:06:52Â Typically, I use uuidv4.
00:06:54Â In this case, you can run npm install.
00:06:57Â Something like nano ID is good as well.
00:07:01Â And then at the top, you can import nano ID from nano ID like this, and just call it nano ID.
00:07:13Â Once we have the room ID, we can open up a new try and catch block.
00:07:18Â In the cache, we can say console.log and something like error happened while creating a room, and then console.log the error.
00:07:31Â And then in the try, we'll try to actually create a room.
00:07:36Â Before we do that though, we have to form the metadata for that room.
00:07:40Â By saying const metadata is equal to an object where we have a creator ID of the user who created that room equal to user ID,
00:07:51Â their email, and the title, which for now will be untitled.
00:07:57Â And finally, we can paste what we copied.
00:08:00Â which is the way to create a room.
00:08:02Â We can import LiveBlocks, not from LiveBlocks node, rather from dot dot slash LiveBlocks, because that points to our own instance where we have already
00:08:13Â added the key.
00:08:14Â And when it comes to the level of access that we want to have, we can say const user accesses.
00:08:20Â That'll be of a type room access equal to an object.
00:08:25Â where we have an email and it'll have a permission of room right.
00:08:31Â So users can edit different documents.
00:08:34Â That means that now we can remove these different types of accesses and simply say const room is equal to await liblocks.createRoom.
00:08:43Â Here we can pass the room ID.
00:08:47Â which is now dynamic, and then we can pass the metadata, the user accesses, and the default accesses, which will be just an empty array.
00:08:58Â And make sure to spell this properly.
00:09:00Â This will be users accesses.
00:09:02Â That's what create room is accepting, as you can see here.
00:09:05Â Once we have the room, we want to revalidate a path from next cache.
00:09:10Â So make sure to import that, and that way a new document will appear on the front end whenever we create a new room.
00:09:17Â And finally, we can return this new room.
00:09:21Â But whenever you're returning stuff from the server action, you have to actually parse and stringify it.
00:09:27Â So I'll call parse stringify from utils and then pass a room right here.
00:09:34Â Oh, and I almost forgot, this right here is a server action.
00:09:37Â So this will only be happening on the server because LiveBlocks right here, this instance is LiveBlocks note, which means it runs on server,
00:09:47Â not on client side, which means that at the top, you have to add the use server directive to ensure that this code runs on the server.
00:09:57Â And now we have this server action that we can call from our front end.
00:10:02Â And where will we do that?
00:10:04Â Well, we'll do it from the homepage.
00:10:06Â When a user presses start a blank document, that'll create a new document, which is at the same time, a new room.
00:10:15Â Right now on the documents page, we cannot see anything because we haven't yet created a valid room.
00:10:21Â But if we go back to the homepage.
00:10:24Â You can see click me button, which is just a fake dummy button.
00:10:27Â But now we can turn it into an actual list of documents to show, which at the start will be none.
00:10:34Â But the most important part is the actual button that'll allow us to create this room using the new server action we have created.