
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.
👉 Bunny (create your free account and get one extra free month): https://jsm.dev/jsm-bunny
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
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
In this lesson, we learn how to create a reusable video card component that can be utilized on multiple pages of the application, such as the homepage and profile page. The card will display various information about the video, including the thumbnail, creator details, and viewer engagement metrics.
Key takeaways:
00:00:02 In this lesson, let's build a reusable video card that we can reuse on the homepage as well as on the profile page.
00:00:10 It'll look something like this.
00:00:12 It'll have a large thumbnail with some overlay buttons to quickly copy a shareable link.
00:00:18 If you're a creator, maybe you'll be able to see some settings, and then we can also show the duration of the video.
00:00:23 At the bottom, we can show the creator, whether it has been publicly shared or not, the name and when it was shared, as well as the number of views that
00:00:32 that video got, as well as a simple title.
00:00:35 So let's implement it and then we'll be able to see their application with all of these great looking dummy cards.
00:00:41 So to start creating a card, let's head over into components and let's create a new component called VideoCard.tsx.
00:00:52 and run RAFCE right within it.
00:00:55 Then we'll need to import this single card within our homepage, right below the H1.
00:01:02 I'll call it VideoCard, just so we can see it right here.
00:01:05 And there we have it.
00:01:06 Of course, to be able to render some cards, we need to pass some props so that each one is different.
00:01:12 So in this case, you have to ask yourself, what are some of the props that each one of these cards will have?
00:01:18 And just note down on a piece of paper different elements or props that it'll have, such as the link that it'll open, the ID,
00:01:27 the thumbnail, the author that created it, when they created it, the number of views, the title, duration.
00:01:34 We need all of these different pieces of information right here.
00:01:38 So how would this look like in action?
00:01:40 Well, let's pass some props to it.
00:01:42 First, of course, we'll need the ID of the card.
00:01:45 For now, I'll pass something like 1. We need a title, and in this case, I will copy the title right here from the design.
00:01:52 Next, we need a thumbnail.
00:01:55 And if I'm not mistaken, I provided a thumbnail right here within the assets.
00:01:59 So, if you search for thumbnail, you'll see that we have thumbnail 1, 2, 3, and so on.
00:02:06 So I can simply copy the path to this file.
00:02:10 So it ends up looking something like this, forward slash assets, forward slash samples, forward slash thumbnail1.png.
00:02:18 Next, we'll need some kind of a date as to when this image was created.
00:02:22 So you can say created at, and then pass over a string of a JavaScript date object.
00:02:29 Feel free to type anything right here.
00:02:31 Next, we need a user image.
00:02:33 For now, we can use a dummy image.
00:02:36 I think we have it under assets, images, json.png, with a username equal to json.
00:02:44 And we can specify a dummy number of views, like 10. Visibility, in this case, let's say that it is public.
00:02:51 And iteration in seconds, let's make it something like 156. So this is all the pieces of data that we're providing to a single video card.
00:02:59 So now we can head back over to our homepage, head into the video card, accept those props, and then render them within the layout.
00:03:07 So, let's do just that.
00:03:09 I will destructure these different types of props, such as the ID, the title, the thumbnail.
00:03:17 We also have the user image, username, created at, views, visibility, as well as the duration.
00:03:26 and we get access to all of these which are of a type video card props and as you can see as soon as I imported the props it let me know that I misspelled
00:03:39 visibility so this is pretty useful and now we can put them to use each card will be a clickable link so we can use the link component and we can make
00:03:48 it point to forward slash video forward slash the ID of that specific card and we can also give it a class name equal to video dash card If we do this,
00:04:02 you can start seeing a nice layout appear right here for the first card that we have.
00:04:07 Next, we can render an image right within it, coming from next image with a source rendering the thumbnail with an alt tag of thumbnail,
00:04:17 a width of about 290, a height of about 160, and a class name equal to thumbnail.
00:04:25 So now if you save it, you should be able to see this dummy thumbnail that I provided to you before.
00:04:30 Make sure to specify the name correctly.
00:04:32 So in this case, I have an empty space and then parentheses and then the number right here.
00:04:36 After that, below the image, we can render an article.
00:04:40 Typically, an article is like a div for a card.
00:04:43 And within it, we can render a div.
00:04:46 And within that div, a figure.
00:04:48 That'll render the user image.
00:04:50 So we can render the image.
00:04:52 It'll have a source of user image.
00:04:56 an alt tag of avatar, a width of about 34, height of 34 as well, a class name of rounded-full, and an aspect of square.
00:05:11 If you save it, you should be able to see a little JSON appear right here.
00:05:16 And we can also, below it, render a fig caption.
00:05:20 with an H3 of username and with a P tag of visibility.
00:05:28 So if you do this, you can now see that Jason created this publicly.
00:05:32 We can head over below the figure and we can display an aside that'll consist of an image with a source of forward slash assets,
00:05:43 icons i.svg.
00:05:46 This is for the views with a width of 16 and the height of 16 as well.
00:05:54 And below it, we can render a span.
00:05:56 That'll show the current number of views.
00:05:59 So now you can see on the right side, 10 views.
00:06:02 Most importantly, we can head below the div and render an H2.
00:06:07 That'll render the title.
00:06:10 And then with a space, maybe we can show the created ad right after.
00:06:15 So I'll say created at dot to locale date string.
00:06:22 And then maybe we can pass a specific format to it, because if you just leave it like this, you'll see that it won't know how to do it.
00:06:29 So I'll provide en us to it, as well as a comma with some additional options, such as a year of numeric, a month of short.
00:06:41 and a day of numeric as well.
00:06:44 Now we have to see whether we're getting this created ad.
00:06:48 Oh, it looks like I misspelled it.
00:06:50 Created ad was supposed to be a date.
00:06:53 So whatever I have typed right here, I'll have to wrap it within a new date.
00:06:59 There we go.
00:07:00 And maybe you don't need these additional numbers.
00:07:02 You can just leave it as a date.
00:07:05 So now if you wrap it, you can see that it'll actually pull that date and display it in a very human readable format.
00:07:12 I think in this case, it's not even needed because I already included it in the title.
00:07:17 So I can remove it from the title here.
00:07:20 And there we go, now it makes more sense.
00:07:22 So let's say that we want to know when we recorded this video.
00:07:25 So it's always good to show it next to the title in this type of application.
00:07:29 Next, we can head below the article and display a button overlay that would allow us to copy the link to that video.
00:07:36 So I will give it an onClick, which for now will be set to an empty callback function.
00:07:41 Later on, we'll implement the copy functionality.
00:07:44 But I will give it a class name of copyBtn.
00:07:48 And then within it, I will render an image with a source of forward slash assets, forward slash icons, forward slash link.svg with an alt tag of copy,
00:08:01 a width of 18, a height of 18, And we can close it right here.
00:08:07 Now that we have introduced the click functionality, we have to make the card client side.
00:08:12 So I'll say use client right here at the top.
00:08:15 And you should be able to see a little button that you cannot click yet because it leads to a 404, but later on you'll be able to click on it and it'll
00:08:23 actually just copy the URL.
00:08:25 And let's not forget about the duration.
00:08:27 So right below the button, we can display a duration only if it exists.
00:08:34 So duration and a div with a class name of duration.
00:08:41 And here, we wanna wrap it within math.seal duration divided by 60, and then say minutes, because typically it is in seconds.
00:08:53 So if I close this properly, you'll see that it says three minutes right here at the bottom, right?
00:08:58 And that makes sense because our video is 156 seconds long.
00:09:02 And at this point, we can also remove this H1 from the homepage.
00:09:06 It's no longer needed.
00:09:08 And we might as well ask ChatGPT to generate a couple of these different cards.
00:09:13 Let's see, we have about eight images.
00:09:17 And we could ask AI to generate more of these cards.
00:09:21 This is a very simple task for AI, but of course, the one that definitely saves us some time.
00:09:26 Typically, you would have to duplicate all of them, right?
00:09:29 So what I want to do is copy the data for this video card and head over into constants, index constants.
00:09:38 Then at the bottom, I will say const dummy cards.
00:09:43 is equal to an array where I can paste an object with all of these properties for the first cards we have created.
00:09:51 So I am going to go ahead and change these from equal signs to key and value pairs and add a comma at the end of each one of these lines.
00:10:02 That'll end up looking something like this.
00:10:04 If you want a video on keyboard shortcuts that allowed me to do this super quickly, just let me know.
00:10:10 But there we go.
00:10:11 So now we have extracted the data for this first card, and it is within an array.
00:10:16 So what I want to do now is ask AI to generate seven more, because I think we have eight thumbnails as samples right here.
00:10:24 So I'll simply select this block of code, press Command-Shift-P, and call Juni to help me.
00:10:30 Juni is an AI agent built into WebStorm and this task should be super simple for it because in the previous courses I gave it so much harder tasks and
00:10:39 it actually went ahead and updated like 10 files at once and made it work.
00:10:44 So this should be super easy.
00:10:46 I'll say create seven more objects for dummy video information.
00:10:53 Follow the same structure, but think of new data.
00:10:59 I'll just press enter.
00:11:00 And you can now see that it is thinking.
00:11:02 And there we go.
00:11:03 Very quickly, it figured out exactly what it needs to do.
00:11:06 And it modified the file with seven new objects for dummy video info with new information.
00:11:13 So you can see that now the second one is Sarah.
00:11:16 And it actually recognized that we have a second thumbnail for this one.
00:11:20 It called it product demo walkthrough.
00:11:22 Then we have thumbnail 3, this time by Michael Scott, and it actually provided additional user images.
00:11:30 And I might actually just provide these assets for you, so we have all these different people right off the bat.
00:11:36 It randomized iterations, the views, and everything.
00:11:39 So you can use Juni to do this, or what I'll do is I'll just provide this array within the video kit below, so you can copy it if you need to.
00:11:47 Now we can head back over to our page and instead of displaying one card, what we can do is map over our dummy cards dot map.
00:12:00 For each one, we get a card or card info, and then we want to display a video card to which we can pass all these props like this one by one,
00:12:11 or instead we can just spread out the card properties like this.
00:12:18 So now if you remove the old one and we can just check whether the types are correct, it seems like it's complaining that visibility should be of type
00:12:26 of visibility.
00:12:28 So if we check out what that is, it seems like it is saying that it should be there public or private.
00:12:34 In this case, we can just make it accept a string for now as we're working with dummy pieces of data.
00:12:40 So I'll say type of visibility is a string and now that's okay.
00:12:45 Perfect.
00:12:46 And let's not forget to give each video card a key equal to card.id because we're mapping over different elements.
00:12:54 And would you look at that?
00:12:55 Even on mobile, this is looking great.
00:12:57 We're showing different images, but let's just make sure that we properly render the avatar.
00:13:03 For you, it should already be rendering, but what I will do is just add a fallback.
00:13:10 So I'll point to assets, images, dummy.jpg.
00:13:16 So if I save it right here, they're all going to be dummies, or maybe instead I can use JSON.
00:13:21 But in your case, you should be able to see different profile photos for all of them as I have added all of these people to the assets for you.
00:13:29 But with that in mind, I'll also copy this dummy cards mapping and move it over to the profile page, just to show you how reusable everything is.
00:13:39 So head over to the profile ID, remove this H1 as we don't need it and instead just map over the dummy cards.
00:13:47 If you do that and open up the app on desktop you'll see, well, this not looking good.
00:13:53 Obviously we have to put these videos in some kind of a grid.
00:13:57 So I'll wrap it within a section that'll have a class name equal to video grid.
00:14:05 And then I'll put these videos right here and I'll make sure to copy this over to the profile page.
00:14:12 So I'll head over to the ID profile and we'll also have to do that with the homepage.
00:14:16 So I'll head over to root homepage.
00:14:19 and just wrap it within a section that'll put these videos within a grid.
00:14:25 So now, back on the home page, you can see that we have this beautiful layout of all of these different cards.
00:14:30 If you click onto them, they'll lead to a specific video page.
00:14:35 And you know what?
00:14:36 Let's actually create a route for that page already.
00:14:40 You already know how we did the routing for the profile page.
00:14:43 So we'll do something very similar here.
00:14:46 I'll first create a new route.
00:14:48 So that's going to be within root.
00:14:51 directory called video, and then a new directory, the dynamic one, called video ID within square brackets.
00:15:02 And within that one, we'll have a new page.tsx.
00:15:07 where we can run RAFCE.
00:15:09 I'll wrap it with a main that'll have a class name of wrapper and page.
00:15:16 And within here, we can say that this is a video details page.
00:15:21 So now, if I click on one of these, you'll see that now we're on a video details page, and each one of these videos will have its own details page.
00:15:30 What matters more as well is that now we can also display the cards for a profile.
00:15:35 If we go here, maybe we're going to show some different kinds of cards, right?
00:15:40 That that user has posted, but on the homepage, we'll show the cards that other users or the videos that other users have posted.
00:15:48 So already this is looking like a finalized application.
00:15:53 I think we can call it a day.
00:15:54 Thank you so much for watching and I'll see you.
00:15:57 Well, just kidding, right?
00:15:59 We have just implemented the UI.
00:16:01 Now is the time that we focus on implementing real logic to this application.
00:16:07 So before we can begin even creating the form for uploading a video, we first have to have the user that'll upload that video,
00:16:17 right?
00:16:17 Or record their screen.
00:16:19 So that means that the next step will be to implement the authentication page.
00:16:23 So let's do that next.