
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 get started with the notifications, we can head over to our homepage.
00:00:06Â Right here above the signed in user, we have already left a text, which now we can turn into a component.
00:00:13Â So let's create a new component called notifications.tsx where you can run RAFCE and we can now just import it right here.
00:00:27Â There we go, import from components notifications.
00:00:32Â We can dive into it and start implementing it.
00:00:35Â For this component, we'll use something known as a popover component from Shazien.
00:00:41Â If you click it, it opens up a popover that displays content in a portal.
00:00:46Â That's basically it.
00:00:48Â And this is perfect for displaying some kind of windows like this or displaying notifications.
00:00:55Â So let's install a popover by running the MPX Shazian UI latest add popover component.
00:01:02Â We can copy its usage, paste it right at the top and copy the component and paste it right here instead of this div.
00:01:11Â This will be a client-side component.
00:01:13Â So at the top, we can say use client.
00:01:16Â Back on the homepage, you can see a button that says open.
00:01:20Â And if you click it here, we can place the content for the popover.
00:01:24Â So let's do just that.
00:01:25Â Let's style the trigger just a bit by giving it a class name equal to relative, flex, size of 10, items-center, justify-center,
00:01:39Â and rounded-lg.
00:01:41Â And right within it, we can render a notification bell icon in form of an image.
00:01:48Â Image coming from next image with a source equal to forward slash assets, forward slash icons, forward slash bell.svg.
00:01:59Â with an alt tag of inbox, a width of 24, and a height of 24. And right next to this image, we want to show how many notifications do we actually have.
00:02:12Â So for that, we can define the notification count.
00:02:15Â And thankfully, this will be handled for us by LiveBlocks.
00:02:20Â So first, let's get access to all the inbox notifications by destructuring it and calling the use inbox notifications hook,
00:02:32Â just like so.
00:02:34Â Below it, we can get access to the count of the notifications in a similar manner by calling the use unread inbox notifications count.
00:02:44Â Super simple.
00:02:45Â And we can also filter out the ones that'll be read by saying const unreadNotifications is equal to inboxNotifications.filter where the read ad status
00:02:57Â is not true.
00:02:58Â So now let's use it right here.
00:03:01Â If the count is greater than zero, then we can render a div.
00:03:07Â It'll be self-closing div.
00:03:09Â And this will be that little dot that shows you that there is something new happening in there.
00:03:14Â So it'll be a little absolutely position dot, with a right 2, and top 2, with a Z index of 20, size of 2, rounded a full,
00:03:29Â and BG blue 500. So if I mock the count right now by saying something like, let count is one.
00:03:40Â And if I go back, you can see this circle right here.
00:03:43Â I must have messed up the size, but you get the idea.
00:03:46Â The size should have actually been size-2 instead of 20. Now that we've fixed that, let's focus on the content.
00:03:54Â So this content will have an align equal to end and a class name equal to shad-popover.
00:04:03Â And right within it, we can render a new LiveBlocks component called LiveBlocks.
00:04:10Â UI config coming from React LiveBlocks.
00:04:14Â And we can further configure it by providing an object called overrides.
00:04:19Â And here we can say inbox notification text mention.
00:04:24Â Okay.
00:04:24Â So we are only triggering the mentions and in there we get access to the user.
00:04:30Â which will be a React node, and we can automatically return an empty React fragment where we say user mentioned you.
00:04:39Â So this is a pretty simple way to figure out exactly what's happening through a specific notification.
00:04:46Â Right within it, we can render the inbox notification list coming from Liblox React UI.
00:04:53Â And in there, we can check if unread notifications.length is lower than or equal to zero, then we can render a p tag with a class name equal to padding
00:05:08Â y of two, text-center and text-dark of 500. That'll simply say no new notifications.
00:05:17Â But if we do have the notifications, we can say that right below.
00:05:22Â So we can say unreadNotifications.length.
00:05:28Â is greater than zero.
00:05:30Â And in that case, we can map over the unread notifications by saying unreadnotifications.map where we get each individual notification.
00:05:41Â And for each one, we can return a new component called inbox notification coming from LiveBlocks React UI.
00:05:50Â And it'll be a self-closing component.
00:05:53Â So it looks something like this.
00:05:55Â To it, we need to pass a lot of additional properties though.
00:05:59Â First, we'll be mapping over things, so we need to provide a key.
00:06:03Â And the key will be equal to notification.id.
00:06:06Â After the key, we need to pass the entire inbox notification itself.
00:06:12Â We need to provide a class name of bgdark200 and text-white.
00:06:18Â We can give it an href.
00:06:20Â So once we click on it, where do we want to go?
00:06:22Â Well, we want to go to forward slash documents, forward slash notification dot room ID.
00:06:29Â So yes, we can do navigation as well.
00:06:33Â So let's properly fix this.
00:06:35Â There we go.
00:06:37Â We can say show actions.
00:06:38Â Can we do something with that?
00:06:40Â I'll leave that as false for now.
00:06:42Â Next, we have the kinds.
00:06:44Â So what kinds of notifications do we want to show?
00:06:48Â And how do we want to display them?
00:06:50Â We'll render all kinds of different notifications.
00:06:54Â So let's do that by saying thread first.
00:06:57Â So we can render a thread by having a callback function here that gives us access to the props of that specific thread.
00:07:06Â And then we can render an inbox notification dot thread to which we pass these props.
00:07:13Â And we can pass additional information, such as show actions is false, as well as show room name will also be false in this case.
00:07:26Â And now we can duplicate this thread right here, just below and rename it to text mention.
00:07:35Â So we want to show notifications for threads and for text mentions, but in this case, we'll render a text mention.
00:07:42Â And here we can just say show room name, false, no need to specify the actions.
00:07:48Â And finally, the last thing we have here is the dollar sign, document access.
00:07:55Â And here we can also return props.
00:07:58Â And here we can define how a custom notification would look like by saying inbox notification dot custom like this.
00:08:07Â In it, we can also spread the props by saying dot dot dot props.
00:08:12Â We can give it a title, which is equal to props dot inbox notification dot, uh, I think it's activities.
00:08:22Â Zero and then dot data.
00:08:24Â That's a long one.
00:08:26Â And then on it, there has to be a dot title.
00:08:28Â Next, we can add the aside property, meaning what we will show aside the notification.
00:08:34Â That's going to be an inbox notification dot icon.
00:08:39Â It'll have a class name equal to BG transparent.
00:08:43Â And within it, we can render an image.
00:08:47Â where we want to show the avatar of the person that left a mention.
00:08:52Â We can do that by saying source is equal to, we can copy this entire thing for the title, but I'll modify the end to say avatar,
00:09:02Â or it'll be an empty string right here, just so it doesn't break.
00:09:06Â And we can see avatar as string.
00:09:10Â That's going to help TypeScript to make it work.
00:09:12Â The width will be 36. The height will be 36 as well.
00:09:17Â The alt tag will be equal to avatar.
00:09:20Â And finally, the class name will be rounded-full as it typically is with avatars.
00:09:27Â Finally, within the actual inbox notification custom, we can render the props.children.
00:09:34Â So we can show everything we need within it.
00:09:37Â And now I think we'll have to fix the indentation here.
00:09:41Â I think I didn't close something properly.
00:09:45Â Oh, I was missing just one parenthesis here.
00:09:48Â This was a longer file, so if something doesn't work for you, just let me know.
00:09:53Â And I will leave this entire file in the readme as well, in case you want to just copy it because we did write a lot of stuff here.
00:10:01Â And mostly we're using some pre-done Liblox component that they conveniently created for us to get a beautiful UI, which I can show you right now.
00:10:11Â Moving back here, check out this nice bell icon, but there are no new notifications.
00:10:17Â So I might need to go to my other account.
00:10:20Â I will enter my first collab document because this account also has it.
00:10:26Â And I will actually put it side by side so we can see if we get triggered in real time.
00:10:32Â And now I will add a mention right here for my JavaScript Mastery account and say, hi there.
00:10:41Â And let's send it.
00:10:44Â And even though it took about 10 seconds for the notification to appear, here it is.
00:10:50Â Adrian commented in a thread, hi there.
00:10:54Â This is great.
00:10:55Â And if I click it, it's actually going to lead me directly to that document and that comment.
00:11:01Â Let's test it the other way around.
00:11:03Â I'm going to write another comment right here and tag Adrian.
00:11:07Â And now if I go back.
00:11:10Â We're hoping to see a notification appear right here as well.
00:11:14Â But on this end, we don't have a notification.
00:11:17Â What we can try to do is create a completely separate comment, like a new one, and then tag Adrian right here and say, hi,
00:11:27Â you there.
00:11:27Â And we can see if that works, maybe even adding some kind of an emoji right here.
00:11:32Â And don't forget, there is one thing that we still have to do.
00:11:36Â And that is also sent a notification whenever we add a new user to the document to let them know that they have been invited.
00:11:44Â Okay.
00:11:44Â It's good that we actually see this one.
00:11:47Â So we can see commented in a thread, hi you there.
00:11:51Â And it actually appeared right here.
00:11:53Â So it's good to know that they're working both ways and it invites me directly onto the document.
00:12:00Â So if we quickly go back to the code and search for to do, you'll see that we have left one to do for ourselves, and that is to send a notification to
00:12:09Â the user when the document gets updated with their email.
00:12:14Â So here I'll show you how to trigger a custom notification through LiveBlocks.
00:12:20Â We can do that by saying const notification ID is equal to nano ID.
00:12:29Â We can do it like this.
00:12:30Â Once we have the ID of the notification, we can just create it by saying await live blocks dot trigger inbox notification.
00:12:41Â And we can pass all of the different options such as the user ID, which is their email in this case, the kind of the notification we're sending.
00:12:52Â In this case, this is a custom notification of document So now going back to our notification component, I think this makes a bit more sense.
00:13:03Â You can create different kinds of notification elements for different kinds of notification types, for threads, text mentions,
00:13:12Â and even our custom things, such as when you're invited to a new document.
00:13:20Â Okay.
00:13:20Â So kind is document access.
00:13:22Â We can also set the subject ID to be equal to the notification ID.
00:13:28Â And we can pass all of the activity data, such as the user type.
00:13:34Â We can pass the title.
00:13:36Â This is going to be a template string of something like you have been granted user type access to the document, either viewer or editor.
00:13:45Â And we can also say by, and then we can say updated by.
00:13:50Â We can also pass the updated by right here.
00:13:54Â So updated by dot name.
00:13:56Â We can pass the avatar equal to updated by that avatar.
00:14:00Â And we can pass the email equal to updated by dot email.
00:14:04Â And finally, we need to pass the room ID as the second parameter to this function call.
00:14:12Â And these updated by avatar and email, you can see that we're getting access to them through props.
00:14:18Â Okay.
00:14:19Â So we can then show additional things like the data, title, and so on.
00:14:25Â Great.
00:14:26Â So now that we have done this, we have no more to do's to implement.
00:14:29Â And if I go back, I can try removing the access from contact at JS Mastery Pro.
00:14:38Â There we go.
00:14:39Â So this is the first time we're testing that.
00:14:41Â And I can once again, try to share it and let's see, we're going to give them a viewer access and back on the homepage.
00:14:48Â Look at that.
00:14:49Â I see a little blue notification bell.
00:14:52Â And if I click that, it says, you have been granted viewer access to the document by JavaScript mastery.
00:14:58Â And if I click it.
00:15:02Â you can see that we are there.
00:15:04Â And we can also see that we're here by looking at this live collaborator avatar.
00:15:09Â How cool is that?
00:15:10Â And don't forget, this entire project is completely mobile responsive, even the editor, which is very hard to do with full markdown editing features for
00:15:22Â it to be fully mobile responsive.
00:15:24Â So if you go to the homepage, everything is looking great.
00:15:27Â Even the models, and if you go in, also the share, everything works flawlessly.
00:15:34Â Which means that we came to the end of this phenomenal build, which I really enjoyed.
00:15:40Â And I hope you did too.
00:15:41Â So, in the typical JavaScript Mastery style, the last thing we have to do is deploy it to the internet.
00:15:48Â So, let's do that next.