Download Next.js 13 Tutorial Subtitles – Learn App Router with TypeScript

Next js Tutorial for Beginners | Nextjs 13 (App Router) with TypeScript

Next js Tutorial for Beginners | Nextjs 13 (App Router) with TypeScript

Programming with Mosh

1636 segments EN

SRT - Most compatible format for video players (VLC, media players, video editors)

VTT - Web Video Text Tracks for HTML5 video and browsers

TXT - Plain text with timestamps for easy reading and editing

Subtitle preview

Scroll to view all subtitles

[00:02]

Welcome to the ultimate Next.js course.

[00:04]

In this course, you will learn

[00:06]

everything you need to know about

[00:07]

Next.js from the basics to more advanced

[00:09]

concepts. So, by the end of the course,

[00:11]

you'll be able to confidently build fast

[00:14]

and scalable applications with Next.js.

[00:17]

If you have been searching for a

[00:18]

comprehensive, easy-to-follow,

[00:20]

well-organized, and practical course

[00:22]

that takes you from zero to hero, this

[00:24]

is the right Next.js course for you. You

[00:26]

don't need any prior knowledge of

[00:27]

Next.js to get started. Everything you

[00:29]

need is right here, so you won't need to

[00:31]

jump back and forth between random

[00:33]

tutorials.

[00:34]

But, here's the catch. Unlike other

[00:36]

courses, we're not just building a dummy

[00:38]

app. We'll be building a beautiful,

[00:40]

full-stack, production-grade app for

[00:42]

tracking issues. An app complete with

[00:45]

all the features and UI patterns you

[00:47]

would expect in modern applications.

[00:49]

On the home page, we have this beautiful

[00:51]

dashboard that displays the latest

[00:53]

issues and their status. And all of this

[00:55]

data is stored in a MySQL database. We

[00:58]

can go to the issues page, we can filter

[01:00]

issues,

[01:02]

sort them,

[01:04]

and go to different pages.

[01:08]

We can click on an issue to see more

[01:09]

details.

[01:10]

We can assign an issue to a user. So,

[01:12]

here we have full authentication and

[01:14]

authorization.

[01:16]

We can edit an issue.

[01:18]

And here we have this beautiful markdown

[01:20]

editor.

[01:21]

We can also delete an issue, and here we

[01:23]

get this confirmation dialog box.

[01:27]

We'll be building this application using

[01:28]

a cutting-edge stack.

[01:30]

Next.js 13, Tailwind, Radix UI, Prisma,

[01:35]

React Query, React Hook Forms, Zod, and

[01:37]

more. And don't worry if some of these

[01:39]

tools are alien to you. Just like my

[01:41]

other courses, I will walk you through

[01:43]

each one, explaining the what, the why,

[01:46]

and the how. So, if you follow along,

[01:48]

you will master Next.js and will be able

[01:50]

to build full-stack applications with

[01:52]

confidence. I'm Mosh Hamedani, a

[01:54]

software engineer with over 20 years of

[01:56]

experience, and I've taught millions how

[01:59]

to code and become professional software

[02:01]

engineers through my YouTube channel and

[02:03]

online school codewithmosh.com.

[02:05]

If you're new here, make sure to

[02:07]

subscribe as I upload new videos all the

[02:09]

time. Now, let's jump in and get

[02:11]

started.

[02:18]

All right. So, what exactly do you need

[02:19]

to know to take this course? Well, to

[02:21]

take this course, you don't need any

[02:23]

prior knowledge of Next.js because I'm

[02:25]

going to teach you everything from the

[02:27]

ground up. However, you need to have

[02:29]

basic familiarity with React and

[02:31]

TypeScript because Next.js is a React

[02:33]

framework, and if you don't know React,

[02:35]

you're not really the right student for

[02:37]

this course.

[02:38]

Now, if you want to learn React, I have

[02:39]

a great tutorial on my YouTube channel.

[02:41]

The link is below this video. I also

[02:43]

have a comprehensive course that goes

[02:46]

way beyond that. It teaches you

[02:47]

everything you need to know to build

[02:49]

modern applications with React 18 and

[02:52]

TypeScript. The full course is 14 hours

[02:55]

divided into two parts, so you can

[02:57]

easily finish each part. In this course,

[02:59]

you will learn how to build this

[03:01]

beautiful application for discovering

[03:03]

video games. Here we have all the common

[03:05]

UI patterns you see in real applications

[03:07]

like filtering, sorting, infinite

[03:10]

scrolls, and so on.

[03:11]

Again, in case you're interested, the

[03:13]

link is below this video.

[03:18]

Welcome back to our Next.js course. In

[03:20]

this section, we'll be talking about the

[03:22]

fundamentals of Next.js.

[03:24]

First, I'll explain what exactly Next.js

[03:27]

is and why is it so popular. Shortly

[03:30]

after, we'll set up our development

[03:32]

environment and create our first Next.js

[03:34]

project. From there, we'll talk about

[03:36]

some foundational concepts such as

[03:38]

client and server components, data

[03:41]

fetching, caching, as well as static and

[03:43]

dynamic rendering. This section is a

[03:46]

great introduction to Next.js, so let's

[03:48]

jump in and get started.

[04:00]

So, you might be wondering, what is this

[04:01]

Next.js thing everyone is talking about

[04:04]

and why should I bother with it? Well,

[04:06]

Next.js is an incredibly powerful

[04:08]

framework for building fast and search

[04:11]

engine friendly applications. It's built

[04:13]

on top of React, so everything you have

[04:16]

learned about React is still relevant.

[04:18]

But, Next.js takes web development to

[04:20]

the next level. While React is just a

[04:22]

library for creating interactive user

[04:24]

interfaces, Next.js is a comprehensive

[04:27]

framework.

[04:28]

Think of a framework as a collection of

[04:30]

libraries, tools, and conventions that

[04:33]

streamline application development.

[04:36]

For instance, Next.js includes its own

[04:38]

routing library, so we don't need to use

[04:41]

a separate library like React Router.

[04:44]

In terms of tooling, it comes with a

[04:46]

compiler for transforming and minifying

[04:49]

our JavaScript code, a command-line

[04:51]

interface for building and starting our

[04:53]

application, and a Node.js runtime.

[04:57]

Now, you might wonder, what exactly is a

[04:59]

Node.js runtime? Well, there are two

[05:01]

main ways we can execute JavaScript

[05:04]

code. Within a web browser on the client

[05:06]

side, or within a Node.js runtime on the

[05:09]

server. So, a Node.js runtime is just a

[05:11]

fancy term for a program that can

[05:13]

execute JavaScript code. So, Next.js

[05:16]

comes with a Node.js runtime, and this

[05:19]

allows us to do some really cool things.

[05:22]

The first thing is that we can do

[05:23]

full-stack development. So, we can write

[05:26]

both the front-end and back-end code

[05:28]

within the same Next.js project. The

[05:31]

back-end code gets executed within the

[05:33]

Node.js runtime, and the front-end code

[05:36]

gets bundled and sent to the client for

[05:38]

execution within a web browser.

[05:41]

In contrast, when building applications

[05:43]

with React, we have to maintain a

[05:45]

separate back-end project in a

[05:47]

potentially different programming

[05:49]

language.

[05:50]

This Node.js runtime also allows us to

[05:52]

render our components on the server and

[05:55]

send their content to the client. This

[05:57]

technique is called server-side

[05:59]

rendering or SSR, and can make our

[06:01]

applications faster and more search

[06:04]

engine friendly.

[06:05]

We'll talk about it in detail later in

[06:07]

the course.

[06:08]

But, wait, there's more. With Next.js,

[06:10]

we can pre-render certain pages and

[06:13]

components that have static data when we

[06:15]

build our application.

[06:17]

We just render them once and serve them

[06:19]

whenever they're needed.

[06:21]

This technique is called static site

[06:23]

generation and can make our applications

[06:25]

super fast.

[06:27]

So, in a nutshell, Next.js is a

[06:29]

framework for building super fast and

[06:32]

search engine friendly applications.

[06:41]

All right. Now, let's talk about setting

[06:42]

up our development environment. To run

[06:44]

Next.js, you should have Node version

[06:46]

16.8 or higher.

[06:49]

So, head over to nodejs.org and download

[06:51]

the latest version.

[06:53]

Now, in this course, I will be using VS

[06:55]

Code as my editor, just like my other

[06:57]

courses. You're welcome to use your

[06:58]

preferred editor, but I encourage you to

[07:00]

use VS Code because along the way, I'll

[07:03]

be sharing a lot of tips and techniques

[07:05]

for writing code fast.

[07:07]

So, you can get VS Code from

[07:09]

code.visualstudio.com.

[07:12]

Now, here in VS Code window, let's talk

[07:14]

about the extensions I'm going to use in

[07:16]

this course.

[07:17]

So, in this panel, search for

[07:20]

ES7.

[07:22]

All right. Look at this extension.

[07:24]

ES7 plus React, Redux, and React Native.

[07:29]

This extension gives us a bunch of code

[07:31]

snippets, so we can quickly and easily

[07:33]

generate React components.

[07:36]

The next extension is TypeScript.

[07:40]

It's this one here.

[07:41]

JavaScript and TypeScript Nightly.

[07:44]

And the last one is

[07:47]

Tailwind CSS

[07:50]

IntelliSense.

[07:52]

Now, if you have never worked with

[07:53]

Tailwind before, don't worry. It's super

[07:55]

easy, and I'm going to hold your hands

[07:56]

through the entire course.

[08:05]

All right. To create our first Next.js

[08:07]

project, open up a terminal window and

[08:09]

run NPX create-next-app

[08:14]

@ You can use the latest version, but in

[08:17]

this course, I'm going to use version

[08:19]

13.4.

[08:20]

So, I strongly recommend you to use the

[08:22]

same version, so you don't have any

[08:24]

difficulties going through the course.

[08:26]

Let's go ahead.

[08:28]

Now, it's asking if you want to install

[08:30]

this package, create-next-app version

[08:32]

13.4.13.

[08:35]

Let's proceed.

[08:37]

All right. Now, it's going to ask us a

[08:39]

bunch of questions about our new

[08:40]

project. The first question is the name

[08:42]

of our project. I'm going to use

[08:44]

next-app.

[08:47]

The next question is if you want to use

[08:48]

TypeScript in this project. The default

[08:51]

answer is yes, so let's press enter to

[08:53]

accept it. The next question is about

[08:56]

using ESLint, which is a common code

[08:58]

analysis tool that we can use to find

[09:01]

common errors like syntax errors,

[09:03]

formatting issues, and so on. Again,

[09:05]

we're going to accept the default value,

[09:06]

which is yes.

[09:08]

The next question is about using

[09:09]

Tailwind CSS. One more time, we're going

[09:11]

to accept yes. The next question is

[09:13]

about using the source directory. A lot

[09:16]

of Next.js projects don't use the source

[09:18]

directory, so I'm going to select no

[09:20]

here.

[09:21]

The next question is about using the new

[09:24]

app router. I'm going to talk about this

[09:26]

later in this section, but very briefly,

[09:28]

in Next.js 13, we have two types of

[09:31]

routers. We have the new app router and

[09:33]

the legacy pages router. In this course,

[09:36]

we're going to use the new app router.

[09:38]

So, let's select yes.

[09:40]

The last question is about customizing

[09:43]

the default import alias. We're going to

[09:45]

select no.

[09:46]

All right. Now, it's going to install

[09:48]

all these dependencies, so you see we

[09:50]

have React, React DOM, Next, TypeScript,

[09:53]

and so on.

[09:57]

All right. All of dependencies are

[09:59]

installed. So, now let's go into this

[10:01]

folder

[10:02]

and run npm run dev.

[10:07]

This starts at development server on

[10:09]

port 3000. So, let's control and click

[10:12]

on this link.

[10:16]

And this confirms that our first Next.js

[10:18]

project is up and running.

[10:27]

Let's talk about the key files and

[10:28]

folders in this project. So, at the top

[10:31]

we have the app folder or this is also

[10:33]

called the app router. This is the

[10:35]

container for our routing system. So, in

[10:38]

Next.js our router is based on the file

[10:40]

system. So, unlike React router, we

[10:43]

don't have to configure our routes and

[10:45]

map them to our components. We can

[10:47]

simply create files and folders to

[10:49]

represent our routes. We'll talk about

[10:51]

them in the next lesson. So, in the app

[10:53]

folder we have a favicon. We have our

[10:56]

global CSS file.

[10:58]

A layout file, which is a basic React

[11:00]

component that returns

[11:02]

an HTML and body element. This

[11:04]

represents the common layout for our

[11:06]

pages.

[11:07]

Now, inside the body element we have

[11:09]

children, which is replaced by a page

[11:11]

dynamically at runtime depending on

[11:13]

where the user is in our application.

[11:16]

Now, in this folder we also have a page

[11:18]

file, page.tsx.

[11:20]

This represent our home page. Now, for

[11:22]

this demo, let's delete everything here

[11:26]

and

[11:28]

replace it

[11:30]

with a simple markup.

[11:32]

So, we're going to return a main

[11:33]

element.

[11:34]

Inside main we want to add an h1 and say

[11:37]

hello world.

[11:39]

Now, back to the browser.

[11:41]

Here we have fast refresh. So, anytime

[11:43]

we make any changes to our TypeScript or

[11:45]

CSS files, the changes are reflected

[11:48]

immediately. Now, here we have a bit of

[11:50]

styling issue because there is a

[11:52]

gradient, a linear gradient applied to

[11:54]

the body element.

[11:56]

So, let's go to our global CSS file.

[11:59]

Down the bottom,

[12:01]

look at the styles applied to the body

[12:03]

element.

[12:04]

The background attribute is set to a

[12:06]

linear gradient and that is why we have

[12:09]

this weird style here.

[12:11]

So, simply remove the background

[12:13]

attribute and

[12:15]

the issue goes away. Beautiful. Now, I

[12:17]

want to apply a padding here so the

[12:19]

content is not so close to the edges of

[12:21]

the screen.

[12:22]

So, let's set padding to

[12:25]

1 rem.

[12:27]

Okay?

[12:29]

That is better.

[12:31]

So, we're done with the app folder.

[12:33]

Now, in this project,

[12:35]

after the app folder, we have the public

[12:37]

folder. This is where we can put our

[12:39]

public assets like images. In this case,

[12:41]

we have two SVG files here, which are

[12:44]

vector graphics. One is Next, the other

[12:46]

is Vercel, which is the company that has

[12:49]

created Next.js.

[12:51]

Now, in the root we have a bunch of

[12:53]

configuration files.

[12:55]

We have one for ESLint, another for

[12:57]

Next, PostCSS, Tailwind, and TypeScript.

[13:02]

For the most part, we don't have to

[13:03]

touch these configuration files, but if

[13:05]

the situation changes in the future,

[13:07]

we'll come back and revisit them.

[13:16]

All right, I told you that routing in

[13:17]

Next.js is based on the file system. So,

[13:21]

here in the app folder,

[13:22]

we can create a new folder

[13:25]

called users.

[13:27]

Now, to make this publicly accessible,

[13:29]

here we should add a page file

[13:32]

in this folder. So, page.

[13:34]

Now, the extension can be JS, JSX, or

[13:38]

TSX for TypeScript. In this course, we

[13:40]

use TypeScript, so I'm going to go with

[13:43]

TSX.

[13:44]

Now, make sure to name this file

[13:46]

correctly, page in lower case, because

[13:48]

this is one of the conventions that

[13:50]

Next.js looks for.

[13:52]

So, the routing system in Next.js is

[13:54]

based on convention, not configuration.

[13:57]

Okay?

[13:58]

So, here we have a page file.

[14:00]

Now, in this page file, we should export

[14:02]

a React component that will be rendered

[14:05]

when the user is at this location,

[14:07]

/users.

[14:09]

Earlier we installed a very useful

[14:11]

extension in VS Code. With that

[14:13]

extension, we can generate a React

[14:15]

component using this shortcut, r a f c

[14:19]

e. That is short for React arrow

[14:22]

function component with an export. Now,

[14:24]

the way I remember this is rafce. Okay?

[14:28]

So, let's generate it. Beautiful. Now,

[14:31]

here we have multiple cursors activated,

[14:33]

so we can rename this component to

[14:35]

something more meaningful like users

[14:38]

page.

[14:39]

The name we assign here doesn't really

[14:40]

matter in terms of routing. This is just

[14:42]

for better organization of our code.

[14:44]

Okay?

[14:45]

Now, let's press escape to deactivate

[14:48]

multiple cursors.

[14:49]

So, back to the browser. Now, let's go

[14:52]

to /users

[14:54]

and here's our new users page.

[14:56]

Beautiful.

[14:57]

Now, one thing you need to know about

[14:58]

this routing system is that if you add

[15:01]

any other files in this folder, let's

[15:03]

say test.css,

[15:06]

this file is not going to be accessible.

[15:08]

So, if you go to /users/test.css,

[15:13]

look, we get this not found page. So,

[15:16]

this is how the new app router is

[15:18]

different from the old pages router. In

[15:21]

the pages router, if you put any files

[15:23]

in this folders, those files would be

[15:25]

publicly accessible, but this is not the

[15:27]

case with the new router. Okay?

[15:30]

So, let's delete this file.

[15:33]

Now, here we can also create nested

[15:35]

routes. So, inside the users folder,

[15:38]

we can add a new folder called new.

[15:41]

And in this folder we add

[15:44]

a new page file. So, page.tsx.

[15:48]

One more time, let's create a React

[15:50]

component

[15:51]

and we're going to call this new user

[15:54]

page.

[15:56]

Good. So, now we can go to users/new

[16:01]

and see this new page. Beautiful.

[16:03]

Now, let's talk about navigation. So,

[16:06]

we're going to go back to our home page.

[16:08]

So, here we press command and P on Mac

[16:10]

or control and P on Windows

[16:13]

to look up files by their name.

[16:15]

If we type page, we can see all our page

[16:17]

files. So, the first item is our home

[16:20]

page. This is the one we're looking for.

[16:22]

Now, on this page, let's add

[16:26]

an anchor.

[16:27]

So, here we add

[16:29]

an anchor. We set href to /users

[16:32]

and give it a label like users.

[16:35]

Now, there is a problem with this way of

[16:38]

implementing navigation. Let me show

[16:40]

you.

[16:40]

So, let's go back to our home page.

[16:44]

All right.

[16:45]

Now, I'm going to open up dev tools.

[16:48]

Here in the network tab,

[16:49]

look at all the requests sent to the

[16:51]

server.

[16:52]

The first one is our HTML document. The

[16:55]

second one is a font. The third one is a

[16:57]

CSS file. And after that, we have a

[17:00]

bunch of JavaScript files.

[17:03]

Now, I'm going to clear this list.

[17:05]

Look what happens when we click on the

[17:08]

users link.

[17:10]

Let's go back to the network tab. Look,

[17:12]

all these resources are re-downloaded.

[17:15]

This is not the optimal way to implement

[17:17]

navigation because in a real

[17:19]

application, we probably have a

[17:21]

navigation bar on the top, a side panel

[17:24]

on the left. So, as the user navigates

[17:26]

from one page to another, we don't want

[17:28]

to reload all these repetitive parts. We

[17:31]

only want to replace the content area,

[17:33]

right?

[17:34]

This is where we use the link component

[17:36]

in Next.js. So, back to our code.

[17:39]

We're going to replace this anchor

[17:41]

with the link component that is defined

[17:44]

in next/link

[17:46]

library.

[17:48]

Okay? Let's replace it here as well.

[17:51]

Good.

[17:51]

Now, back to our home page.

[17:53]

Once again, I'm going to bring up the

[17:55]

network tab

[17:56]

and clear this list.

[17:59]

Now, look what happens when we click on

[18:01]

the users link.

[18:03]

Look, we only have two requests and

[18:05]

these requests are for downloading the

[18:07]

content of the users page. So, we're not

[18:10]

re-downloading a font, a CSS file, and a

[18:13]

bunch of JavaScript files.

[18:15]

This is what we call client-side

[18:16]

navigation. Now, there's more to

[18:18]

navigation. We have a comprehensive

[18:20]

section about this topic later in the

[18:21]

course. This was just a basic overview.

[18:31]

In Next.js projects, we have two

[18:33]

environments where we can render our

[18:35]

components and generate HTML markup.

[18:38]

Either on the client within a web

[18:40]

browser or on the server within a

[18:42]

Node.js runtime. Rendering components on

[18:45]

the client is similar to how React

[18:48]

applications work. We refer to this

[18:50]

technique as client-side rendering or

[18:52]

CSR.

[18:54]

On the flip side, we have server-side

[18:56]

rendering or SSR, where components are

[18:58]

rendered on the server. So, what are the

[19:01]

differences? Well,

[19:02]

with client-side rendering, we have to

[19:04]

bundle all our components and send them

[19:07]

to the client for rendering. This means

[19:09]

as our application grows, so does our

[19:11]

bundle size because it must contain all

[19:14]

of our components. Now, the larger the

[19:16]

bundle, the more memory we need on the

[19:18]

client to load all these components. So,

[19:21]

this approach is resource heavy.

[19:23]

The other problem is that search engine

[19:25]

bots, which are machines that browse and

[19:27]

index our websites, can't view our

[19:29]

content because they can't execute

[19:31]

JavaScript code, so they cannot render

[19:33]

our components like a web browser.

[19:36]

And last but not least, any sensitive

[19:38]

data we have in our components or their

[19:40]

dependencies like API keys will be

[19:43]

exposed to the client. Now, if we render

[19:46]

our components on the server, we can get

[19:48]

rid of all these problems. We only send

[19:50]

the essential components to the client

[19:52]

and prevent our bundle from becoming

[19:55]

unnecessarily large. Also, because the

[19:57]

server handles most of the rendering, we

[20:00]

need less resources on the client. Plus,

[20:03]

because rendering is done on the server

[20:04]

and we send the actual content to the

[20:06]

client, search engine bots can view and

[20:09]

index our pages. And finally, we can

[20:12]

keep sensitive data like API keys on the

[20:15]

server.

[20:16]

So, these are all the great benefits of

[20:18]

server-side rendering.

[20:20]

However, with server-side rendering, we

[20:22]

lose interactivity.

[20:24]

So, server components, which are

[20:26]

components that are rendered on the

[20:27]

server, cannot listen to browser events

[20:29]

like click, change, submit, and so on.

[20:33]

They cannot access browser APIs like the

[20:35]

local storage. They cannot maintain

[20:37]

state or use effects. These

[20:40]

functionalities are only available in

[20:42]

client components.

[20:44]

So, in real-world applications, we often

[20:46]

use a mixture of server and client

[20:48]

components. We should default to server

[20:51]

components and use client components

[20:53]

only when we absolutely need them.

[20:55]

Here is an example. Let's imagine we

[20:57]

want to build a page to show a list of

[20:59]

products. To build this page, we

[21:02]

probably need several components like

[21:04]

navbar, sidebar, product list, product

[21:07]

card, pagination, and footer.

[21:10]

Now, in standard React applications, we

[21:12]

have to package all these components and

[21:14]

send them to the client for rendering.

[21:16]

But in Next.js, we can keep all these

[21:18]

components on the server and minimize

[21:21]

the bundle size. There is just one

[21:23]

exception.

[21:24]

To add a product to a shopping cart, we

[21:26]

need to handle the click event of a

[21:27]

button. Typically, we implement this

[21:30]

functionality in the product card

[21:31]

component. So, we have to make it a

[21:33]

client component. That's one option, but

[21:36]

there's a better way.

[21:37]

We can keep this component on the server

[21:39]

and do most of the rendering there, and

[21:41]

instead extract a small component that

[21:45]

only contains the add button.

[21:47]

With this change, we only ship a tiny

[21:49]

component to the client and keep

[21:51]

everything else on the server. Let's see

[21:53]

this in action.

[21:55]

Back to our project. In Next.js, all

[21:57]

components inside the app folder are

[22:00]

server components by default. So, that

[22:02]

means all the pages we have created so

[22:04]

far, these are server components and are

[22:08]

rendered on the server. Let me show you.

[22:10]

So, back to the browser. Let's bring up

[22:13]

the network tab and

[22:15]

look at the first request.

[22:17]

This is the HTML document that we get

[22:19]

from the back end. So, look. We have our

[22:21]

content here. We have our hello world

[22:23]

and the users link. This is exactly what

[22:26]

search engine bots see when they browse

[22:28]

our website. In contrast, if we used

[22:31]

client-side rendering, which is how

[22:33]

standard React applications work, search

[22:36]

engine bots wouldn't be able to see our

[22:37]

content. They would see a blank page

[22:40]

because all components, all the content

[22:42]

is rendered on the client. Okay?

[22:45]

So,

[22:46]

back to our project. All components

[22:48]

inside the app folder are server

[22:50]

components by default. Now, if you have

[22:52]

worked with Next.js before, I should

[22:54]

mention that the pages router doesn't

[22:56]

support server components. So, going

[22:58]

forward, you should stop using it and

[23:00]

switch to the new app router. Okay?

[23:03]

Now, let's create

[23:05]

a new folder here

[23:06]

called components.

[23:09]

Earlier, I told you that this folder is

[23:11]

not publicly accessible unless we add a

[23:13]

page file inside it. So, that means we

[23:15]

can colocate our project files like our

[23:18]

components and other building blocks

[23:21]

with our pages. We can put them next to

[23:23]

each other, and this is perfectly fine.

[23:25]

So, here in the components folder, let's

[23:27]

add

[23:29]

a new file called product card.tsx.

[23:33]

Here, we create a basic React component.

[23:36]

Now, earlier, I told you that server

[23:38]

components cannot have interactivity.

[23:41]

So, they cannot handle browser events

[23:43]

like click, change, and so on.

[23:46]

So, that means if we add

[23:48]

a button here

[23:50]

and handle the click event

[23:53]

we get a runtime error. Let me show you.

[23:56]

So, let's pass a basic arrow function

[23:59]

and log something on the console.

[24:03]

And we set the label to add to cart.

[24:06]

Now, let's add this component to our

[24:08]

home page.

[24:09]

So, we go to our first page file

[24:12]

and add our new product card component.

[24:17]

Now, back to the browser. Look, we got

[24:19]

an error saying event handlers cannot be

[24:22]

passed to client component props.

[24:25]

If you need interactivity, consider

[24:27]

converting part of this to a client

[24:29]

component.

[24:30]

Like here, we have two options. One

[24:32]

option is to make this entire component

[24:34]

a client component. So, we go to the top

[24:38]

and use the client directive. So, in

[24:41]

quotes, we type use client. That's all

[24:43]

we have to do.

[24:45]

With this, we tell the Next.js compiler

[24:47]

to include this file or this component

[24:50]

in our JavaScript bundle.

[24:52]

And that means if this component is

[24:54]

dependent on other components, those

[24:56]

components will automatically become

[24:58]

client components and will be included

[25:01]

in our JavaScript bundle. So, we don't

[25:03]

have to repeat this directive on every

[25:05]

client component. Okay?

[25:07]

So, here's one option. Now, if you go

[25:09]

back to the browser

[25:10]

the error is gone. But there is a better

[25:12]

way.

[25:13]

To make our applications faster and more

[25:15]

search engine friendly, we want to

[25:17]

render our components on the server as

[25:19]

much as possible and use client

[25:21]

components only when absolutely

[25:23]

necessary. So, here

[25:26]

our product card could have some complex

[25:28]

markup. We want to render all that

[25:30]

markup on the server and move this

[25:32]

button to the client.

[25:34]

So, I'm going to extract this button and

[25:36]

put it inside a separate component.

[25:39]

So,

[25:40]

here in the components folder, let's add

[25:42]

a new file

[25:44]

add to cart.

[25:47]

Again, we create a basic React

[25:49]

component. On the top

[25:52]

we use the client directive and then we

[25:55]

move

[25:56]

this button to our new component.

[26:01]

Like this.

[26:02]

Okay? So, now we have a client component

[26:05]

and we're going to use this in our

[26:07]

product card.

[26:10]

Okay?

[26:12]

With this, we can remove use client from

[26:14]

this file. So, this component will be

[26:16]

rendered on the server. And that means

[26:19]

where we have a client component, in

[26:21]

this case, where we have this button,

[26:23]

there's going to be a hole or a slot

[26:25]

where React will later inject our client

[26:27]

component. Okay?

[26:29]

Now, if you go back to the home page,

[26:31]

again, we don't see any errors. So, this

[26:33]

is how we can create and use client and

[26:35]

server components.

[26:38]

Hey guys, I hope you've been having fun

[26:40]

watching this tutorial. I just wanted to

[26:42]

mention that this tutorial is the first

[26:44]

hour of my complete Next.js course. So,

[26:47]

after you finish this, if you want to

[26:49]

learn more, I highly recommend you to

[26:51]

enroll in the full course because it's

[26:53]

much faster and easier than jumping

[26:55]

between a bunch of random, disconnected

[26:57]

tutorials here on YouTube. The full

[26:59]

course is 5 hours long and teaches you

[27:02]

everything you need to build full-stack

[27:03]

applications with Next.js. It also comes

[27:07]

with a certificate of completion and a

[27:09]

30-day money-back guarantee. So, if

[27:11]

you're not happy, ask for a full refund,

[27:13]

you get all your money back, no

[27:14]

questions asked. In case you're

[27:16]

interested, the link is below this

[27:18]

video.

[27:25]

Now, there are two ways we can fetch

[27:26]

data. We can fetch it on the client or

[27:29]

on the server. To fetch data on the

[27:31]

client, we typically use the state hook

[27:33]

to declare a state variable and the

[27:35]

effect hook to call the back end, get

[27:38]

the data, and put it into our state

[27:39]

variable. Now, in my React course, I

[27:41]

talked about React Query as a better

[27:43]

alternative to manually using the state

[27:46]

and effect hooks. But regardless of how

[27:48]

we fetch data, fetching data on the

[27:50]

client in client components has all the

[27:53]

problems we talked about in the previous

[27:55]

lesson. So, over time, our bundles would

[27:57]

get larger because we have to ship more

[28:00]

and more components to the client. Also,

[28:02]

this approach is resource intensive

[28:04]

because all the rendering is done on the

[28:06]

client. Plus, our content or our data is

[28:09]

not visible to search engines, and this

[28:11]

approach is less secure because our API

[28:14]

keys or any kind of sensitive data will

[28:17]

end up on the client. But there is one

[28:19]

extra problem. The problem is that with

[28:21]

this approach, there's always an extra

[28:24]

round trip to the back end. So, when a

[28:26]

React application loads, first the

[28:28]

browser downloads the HTML template as

[28:31]

well as the CSS and JavaScript files

[28:33]

from the back end. Then, it will send an

[28:35]

extra request to fetch data from the

[28:38]

back end. So, there's always an extra

[28:41]

round trip to the back end. Now, we can

[28:43]

fetch data in our server components and

[28:45]

get rid of all these problems. Let me

[28:48]

show you.

[28:49]

In this lesson, we're going to use JSON

[28:51]

Placeholder to get some dummy data into

[28:53]

our application. In case you are not

[28:55]

familiar with JSON Placeholder, it's a

[28:57]

fake API for getting some dummy data.

[29:01]

So, head over to

[29:02]

jsonplaceholder.typicode.com.

[29:05]

On this page, you will find various

[29:07]

endpoints for getting dummy data like a

[29:10]

list of posts, comments, albums, photos,

[29:13]

to-dos, and users.

[29:15]

In this lesson, we're going to get a

[29:16]

list of users into our application.

[29:19]

So, look. Each user object has a bunch

[29:21]

of properties like ID, name, username,

[29:24]

and so on.

[29:25]

So, back to our project

[29:27]

let's go

[29:28]

to the app folder and then open the

[29:30]

users folder and then go to this page.

[29:34]

Now, this is a server component, and in

[29:36]

server components, we can use the fetch

[29:39]

function that you are probably familiar

[29:41]

with.

[29:42]

This function is defined in browsers,

[29:43]

and with this, we can send HTTP requests

[29:46]

to the back end.

[29:48]

So, here we pass the URL of our

[29:50]

endpoint, which we grab from here.

[29:53]

So, copy

[29:55]

and paste it.

[29:56]

Now, this returns a promise, so we have

[29:58]

to await it

[30:00]

to get the response.

[30:02]

Now, because we're using await here, we

[30:03]

have to make this component async.

[30:07]

Now, this is the beauty of this

[30:08]

approach. With this approach, we don't

[30:09]

have to use a state variable, we don't

[30:11]

have to use the effect hook with zero

[30:14]

dependencies. There's no ceremony. We

[30:16]

just call fetch to get the data. And all

[30:19]

of this happens on the server. You'll

[30:21]

see that in a minute.

[30:22]

So, we get the response. Then we call

[30:25]

response.json.

[30:27]

This also returns a promise,

[30:29]

so we await it

[30:31]

to get the data, in this case,

[30:33]

our users.

[30:34]

Next, we map these users to a bunch of

[30:37]

list items, exactly like how we render

[30:39]

them in a React application.

[30:42]

So, for our markup, let's replace this

[30:44]

div with a fragment. Here we add an h1

[30:48]

called users.

[30:50]

Then we add an unordered list, and here

[30:52]

we map

[30:54]

these users.

[30:55]

We grab each user.

[30:57]

Now, if you type user. Look, we don't

[30:59]

see anything because the compiler

[31:01]

doesn't know about the type of these

[31:03]

user objects. So, if you hover our mouse

[31:05]

over this constant, look, the type of

[31:08]

this constant is any, which means we

[31:10]

don't know. It could be anything.

[31:12]

This is where we can use some TypeScript

[31:14]

magic to improve our code.

[31:16]

So, outside of this component,

[31:19]

we define an interface

[31:21]

or a type called user.

[31:25]

And here we say that each user has a

[31:27]

property called ID of type number.

[31:30]

It also has name of type string and so

[31:33]

on. We could list all the properties we

[31:35]

have here, but that is not necessary for

[31:37]

this lesson, so we're going to keep

[31:39]

things simple. So, with this interface,

[31:41]

we're defining the shape of our user

[31:43]

objects, okay?

[31:45]

Now, where we declare this constant,

[31:48]

we annotate it with its type, which is

[31:51]

user array.

[31:53]

Okay? With this,

[31:55]

when we type user.

[31:58]

we can see the properties of user

[32:00]

objects. So, this is the benefit of

[32:02]

using TypeScript. With TypeScript, we

[32:04]

get auto-completion when we're coding,

[32:06]

and also if we have any kind of errors

[32:08]

like typos, we can catch those errors at

[32:11]

build time, before we run and deploy our

[32:14]

application, okay?

[32:16]

So, here we're going to map each user to

[32:17]

a list item.

[32:19]

First, we give it a key,

[32:21]

which we set to user.id.

[32:24]

And here we render user.name.

[32:27]

That's all we had to do. So, our code is

[32:29]

simpler, there's no state and effect

[32:31]

hook here. Our bundle is going to be

[32:33]

smaller because this component will be

[32:36]

on the server.

[32:37]

Now, back to the browser, let's go to

[32:39]

the users page. Here's our users,

[32:41]

beautiful. Now, let's bring up the

[32:43]

network tab

[32:46]

and refresh the page.

[32:48]

So, take a look at the document that we

[32:50]

received from the back-end.

[32:52]

So, all our users are rendered right

[32:54]

here. This is because rendering is

[32:56]

happening on the server. In contrast, in

[32:59]

typical React applications or wherever

[33:02]

we use client-side rendering, the

[33:03]

browser initially gets a blank document.

[33:07]

Then it will call the back-end to fetch

[33:09]

the data and then render the content.

[33:11]

So, there's always an extra round trip

[33:13]

to the back-end, and our application is

[33:16]

not search engine friendly. So, to fetch

[33:18]

data, whenever possible, we should fetch

[33:21]

it in server components.

[33:29]

Fetching in server components has an

[33:31]

extra benefit, and that is caching. What

[33:34]

is caching? Well, the idea of caching is

[33:37]

to store data somewhere that is faster

[33:39]

to access.

[33:40]

Basically, there are three places where

[33:42]

we can get the data from. We can get it

[33:44]

from the memory, from the file system,

[33:46]

or from the network. Now, as we go down

[33:49]

this list, getting data becomes slower.

[33:52]

For example, getting data from the

[33:53]

network is always slower than getting it

[33:56]

from the file system. For this reason,

[33:58]

Next.js comes with a built-in data

[34:01]

cache.

[34:02]

So, whenever we use the fetch function

[34:04]

to get some data, Next.js will

[34:07]

automatically store the result in its

[34:09]

data cache, which is based on the file

[34:11]

system. So, the next time we need the

[34:13]

same piece of data, that next time we

[34:15]

hit the same URL, Next.js is not going

[34:18]

to go to JSON Placeholder, it's going to

[34:20]

get the data from its data cache, from

[34:22]

the file system. Of course, we have full

[34:25]

control over this caching behavior. If

[34:27]

you have data that changes frequently,

[34:30]

we can disable caching or treat data in

[34:32]

cache as fresh for a certain period of

[34:35]

time. Let me show you.

[34:37]

So, here when we call the fetch

[34:38]

function, we can pass a second argument,

[34:41]

which is an options object. Let me put

[34:44]

this on a new line, so you can see

[34:46]

clearly.

[34:48]

In this object, we can set cache to

[34:50]

no-store

[34:52]

to disable caching. That's one option,

[34:55]

and this is useful if you have data that

[34:57]

changes frequently. In those situations,

[34:59]

we always want to show fresh data to our

[35:01]

users, right?

[35:03]

The other option is to keep data fresh

[35:05]

for a certain period of time.

[35:08]

To do that, instead of setting cache to

[35:10]

no-store,

[35:11]

we set next to an object.

[35:14]

In this object, we can specify

[35:16]

configuration parameters that are

[35:18]

specific to Next.js.

[35:20]

So, here we can set revalidate to value

[35:22]

like 10,

[35:24]

and this means Next.js is going to run a

[35:26]

background job and get fresh data from

[35:29]

the back-end every 10 seconds. So, this

[35:32]

is how caching works in Next.js.

[35:34]

Now, one thing you need to know is that

[35:36]

this caching behavior is only

[35:38]

implemented in the fetch function. So,

[35:41]

if you use a third-party library like

[35:43]

Axios, you're not going to get this.

[35:45]

You're not going to get the data cache.

[35:54]

In Next.js, we have another performance

[35:56]

optimization technique called static

[35:58]

rendering or static site generation. The

[36:01]

idea of static rendering is that if you

[36:03]

have pages or components that have

[36:05]

static data, we can have Next.js render

[36:08]

them once when we build our application

[36:11]

for production. So, next time those

[36:13]

pages or components are needed, Next.js

[36:16]

is not going to re-render them. It's

[36:18]

going to get their payload or content

[36:20]

from its cache, which is based on the

[36:22]

file system. This is static rendering,

[36:25]

meaning rendering at build time. In

[36:27]

comparison, we have dynamic rendering,

[36:29]

which happens at request time. Let's see

[36:32]

this in action.

[36:33]

So, back to our users page, let's add a

[36:36]

timestamp above the list of users. So,

[36:39]

here we add a paragraph and render.

[36:42]

First, we create a new date object, and

[36:44]

then call toLocaleTimeString.

[36:48]

With this, we can see when this page was

[36:50]

rendered.

[36:51]

Now, back in the browser, let's refresh

[36:53]

a few times. So, look, the timestamp is

[36:56]

changing. This only happens in

[36:58]

development mode. But if we build this

[37:00]

application for production, you'll see

[37:02]

that the timestamp is not going to

[37:04]

change because Next.js will treat this

[37:07]

page as a static page. And here's the

[37:09]

reason.

[37:10]

Earlier, I told you that by default,

[37:12]

whenever we use the fetch function,

[37:14]

Next.js will cache the data. So, it

[37:17]

treats our data as static or unchanging

[37:19]

data. So, when rendering this page,

[37:22]

Next.js sees that this page has static

[37:24]

data, so it decides to render this page

[37:27]

statically at build time. But if we

[37:30]

disable caching, Next.js thinks the data

[37:33]

on this page is going to change, so it's

[37:35]

not going to render this page

[37:36]

statically, it's going to render it at

[37:38]

request time.

[37:39]

To see this action, let's go back to the

[37:42]

terminal window,

[37:43]

stop this process.

[37:45]

Now, earlier we used npm run dev to

[37:48]

start this application in our

[37:49]

development server. Now, to build this

[37:51]

for production, we run npm run build.

[37:58]

All right, here you can see all the

[38:00]

routes that are generated when we build

[38:02]

our application for production.

[38:04]

So, this is our root route or the home

[38:06]

page. We have a route for our favorite

[38:08]

icon.

[38:09]

We have one for the users page, another

[38:11]

for the users/new page, and so on.

[38:14]

Now, look at the icon before each of

[38:16]

these routes. Here, we only see circles.

[38:19]

Now, down here, you can see that a

[38:21]

circle means static. So, these pages are

[38:24]

automatically rendered as static HTML.

[38:27]

Now,

[38:28]

if you start this application in

[38:29]

production, which we can do by running

[38:32]

npm start,

[38:34]

and then go back to the browser,

[38:36]

let's refresh.

[38:37]

Look, the timestamp is not changing

[38:40]

because this page was rendered

[38:41]

statically at build time.

[38:43]

Now, back to this page, let's disable

[38:45]

caching and rebuild this application for

[38:47]

production.

[38:49]

So, as a second argument, we pass an

[38:51]

options object, and here we set cache to

[38:54]

no-store.

[38:56]

Okay?

[38:57]

Now, back to the terminal, let's stop

[38:59]

this process,

[39:00]

and rebuild the application.

[39:06]

Lovely. Now, look at the icon

[39:09]

before the users route. Instead of a

[39:12]

circle, we have a lambda. And down here,

[39:14]

you can see that lambda means rendering

[39:17]

on the server. So, server-side renders

[39:19]

at run time.

[39:21]

Now, let's start the application in

[39:23]

production.

[39:25]

Back to the browser, let's refresh.

[39:27]

Now, look, every time you refresh, the

[39:29]

timestamp changes.

[39:31]

Let's recap everything you have learned

[39:33]

about rendering. In Next.js, rendering

[39:35]

can happen on the client or on the

[39:37]

server. If it happens on the server, it

[39:40]

can happen at build time, which is

[39:42]

called static rendering, or at request

[39:45]

time, which is called dynamic rendering.

[39:48]

So, that brings us to the end of this

[39:49]

section. In the next section, we'll talk

[39:51]

about styling Next.js applications. So,

[39:54]

I will see you there.

[39:59]

Welcome back to our Next.js course. In

[40:01]

this section, we'll explore various ways

[40:03]

to style our applications and make them

[40:05]

beautiful.

[40:06]

We'll cover global styles, CSS modules,

[40:09]

Tailwind, and Daisy UI. So, let's jump

[40:12]

in and get started.

[40:23]

Earlier in the course, we briefly talked

[40:24]

about our global style sheet in the app

[40:27]

folder.

[40:28]

So, let's open up globals.css.

[40:31]

In this file, on the top, we have three

[40:33]

directives to import the base styles

[40:35]

from Tailwind. Now, we're going to talk

[40:37]

about Tailwind later in this section,

[40:39]

but very briefly, Tailwind is a very

[40:41]

popular CSS framework, okay?

[40:44]

Then after that, we have this root

[40:46]

selector. This is where we typically

[40:48]

define custom properties like foreground

[40:51]

RGB, and so on.

[40:53]

Then we have media prefers-color-scheme:

[40:56]

dark. With this CSS feature, which is

[40:58]

relatively new, we can detect if the

[41:01]

user is in the dark mode or not. If so,

[41:03]

you can see that the value of these

[41:06]

custom properties is overwritten.

[41:09]

Now, down here,

[41:10]

you can see that we have used the value

[41:12]

of this custom property as the color of

[41:15]

the body element. So, we are not using

[41:18]

background start and end RGB. They were

[41:21]

used earlier when we had a gradient on

[41:23]

our home page. So, before going further,

[41:25]

let's do a bit of cleanup here. I'm

[41:26]

going to delete these two lines, and

[41:30]

these two lines from here.

[41:32]

And also, let's go back to the terminal

[41:34]

and make sure

[41:36]

that we're running this application in

[41:38]

development, so anytime we make any

[41:40]

changes here, we can see the changes

[41:42]

immediately. So, npm run dev.

[41:46]

Good. Now, back to this file.

[41:49]

So, this is our global style sheet, and

[41:51]

we should use it for styles that are

[41:52]

truly global in our application, styles

[41:55]

that apply to all pages, like anything

[41:57]

to do with the body element, our

[41:59]

headings, our hyperlinks, and so on.

[42:01]

Anything that is specific to a page or a

[42:04]

component, we should implement it

[42:06]

somewhere else. So, one thing you

[42:07]

shouldn't do here is you shouldn't

[42:09]

define custom classes like user list,

[42:13]

because this only applies to a

[42:14]

particular component or page. With this

[42:17]

approach, as we build more and more

[42:19]

components, this global style sheet

[42:21]

grows really large and becomes

[42:23]

unmanageable. And more importantly, as

[42:26]

we change or delete our components,

[42:28]

we'll have to remember to come back and

[42:30]

do some cleanup here. Otherwise, over

[42:32]

time, we'll have a lot of dead styles in

[42:34]

this file. If you have been working with

[42:36]

CSS for a while, you know what I'm

[42:38]

talking about.

[42:39]

So, reserve this file for styles that

[42:41]

are truly global. For styles that are

[42:44]

specific to a page or a component, use

[42:46]

CSS modules or Tailwind, which we're

[42:48]

going to talk about next.

[42:56]

All right, let's talk about CSS modules.

[42:58]

A CSS module is a CSS file that is

[43:01]

scoped to a page or a component. It's a

[43:04]

way to prevent styles from clashing or

[43:07]

overriding each other. If you have been

[43:09]

working with CSS for a while, you know

[43:11]

that if you have the same class defined

[43:13]

in two different places in two different

[43:15]

style sheets, these classes can override

[43:18]

each other depending on how we import

[43:20]

these style sheet files. CSS modules aim

[43:23]

to solve that problem. Let's see how

[43:25]

they work.

[43:26]

So, here in the components folder,

[43:28]

we have a component called product card.

[43:32]

Now, let's say you want to create some

[43:33]

styles for this component. So, here we

[43:36]

add a new file.

[43:38]

We can call this file anything, but it's

[43:40]

better to call it the same as the

[43:42]

component, so product card. What matters

[43:45]

is that the extension has to be dot

[43:48]

module.css.

[43:51]

Okay?

[43:52]

Now, in this file or in this CSS module,

[43:54]

we can define classes that are scoped to

[43:57]

our product card component. So, let's

[43:59]

define a class called card.

[44:02]

And of course, we can define this class

[44:04]

somewhere else without worrying that

[44:06]

these classes would clash, okay?

[44:08]

So, here we can apply a padding of 1

[44:11]

rem,

[44:12]

and a border of 1 pixel solid

[44:16]

CCC.

[44:19]

Now, we go back to our component,

[44:21]

and import

[44:23]

this style sheet. So, we type import

[44:26]

styles

[44:27]

from current folder,

[44:29]

productcard.module.css.

[44:32]

The name we assign here doesn't matter,

[44:34]

but typically we go with styles, and

[44:36]

this will be a JavaScript object. So,

[44:39]

the classes that we define in this CSS

[44:41]

module will end up being properties of

[44:44]

that object.

[44:45]

So, here if we type styles,

[44:48]

we should see those properties, but I

[44:50]

don't know why IntelliSense is not

[44:52]

currently working for me, so I apologize

[44:54]

for that. So, here we should see the

[44:55]

classes we have defined like card, and

[44:58]

so on. And that means in CSS modules, we

[45:01]

cannot use hyphens

[45:03]

when naming these classes, like card

[45:06]

container, because this is not a valid

[45:08]

name for a JavaScript property. So, in

[45:11]

these files, always use the camel case

[45:13]

notation. So, we remove the hyphen and

[45:16]

make the first letter of the second word

[45:19]

uppercase, okay?

[45:20]

Now, let's just simplify things. We go

[45:22]

with card.

[45:24]

Back to our component.

[45:26]

So, we have this object.

[45:28]

Now,

[45:29]

on this div, we set class name to

[45:32]

we use our curly braces and set it to

[45:34]

styles.card.

[45:37]

Now, back to the browser.

[45:41]

Here on the home page, you can see the

[45:42]

style applied to our card. But, let me

[45:44]

show you something interesting.

[45:46]

Let's right-click here, and inspect this

[45:49]

in Chrome DevTools.

[45:51]

Here's our div. Look at the class name.

[45:53]

This is not the class that we created,

[45:55]

right? This is auto-generated. So, what

[45:57]

is happening here is that this project

[46:00]

uses a tool called PostCSS for

[46:02]

transforming our CSS class names. So,

[46:05]

back to our project.

[46:08]

Here in the root folder,

[46:10]

we have a file called postcss.config.js.

[46:14]

In this file, currently we have two

[46:16]

plugins. One is Tailwind, the other is

[46:19]

autoprefixer. Now, for the most part, we

[46:21]

don't have to touch this configuration

[46:23]

file, but if you're an advanced PostCSS

[46:25]

user, you know this is where you can

[46:27]

provide your custom configuration.

[46:30]

So, when building our application,

[46:31]

Next.js uses PostCSS to transform our

[46:35]

class names and generate unique class

[46:38]

names that don't clash. This is how CSS

[46:41]

modules work. Now, one last thing before

[46:43]

we finish this lesson.

[46:45]

Currently, I've put

[46:46]

the CSS file and the TypeScript file

[46:49]

next to each other. If you don't like

[46:51]

mixing up your CSS and TSX files, you

[46:54]

can group them in folders. So, here we

[46:56]

can create a folder

[46:58]

like product card.

[47:01]

This is a container for our component.

[47:03]

In this component, we can have a TSX

[47:05]

file and a CSS file, okay?

[47:08]

And of course, we can use the same

[47:09]

technique with our pages. So, we can use

[47:12]

CSS modules to define styles that are

[47:14]

local to a particular page.

[47:23]

All right, let's talk about Tailwind.

[47:25]

So, Tailwind is a very popular CSS

[47:28]

framework that uses the concept of

[47:30]

utility classes.

[47:32]

So, here on tailwindcss.com,

[47:34]

you can see that we have a bunch of

[47:36]

classes like flex,

[47:38]

pt-4, which is short for padding top

[47:41]

four, text center, and so on.

[47:43]

So, here we have a ton of small utility

[47:45]

classes, and we can combine them to

[47:47]

style our application.

[47:49]

Some people love it, some people hate

[47:51]

it. I have to confess that I also have a

[47:53]

love-hate relationship with Tailwind,

[47:55]

but I think I love it more than I hate

[47:57]

it. If you have never used it before, I

[47:59]

strongly encourage you to give it a

[48:01]

chance, because these days, a lot of

[48:03]

projects are built with Tailwind. So, if

[48:05]

you want to upgrade your skills and

[48:07]

expand your job opportunities, you

[48:09]

should have Tailwind in your skill set.

[48:12]

So, in Tailwind, we have a ton of small

[48:15]

utility classes.

[48:16]

For example, for controlling paddings,

[48:19]

we have a bunch of classes that start

[48:20]

with P, followed by a number, which can

[48:22]

be 1 2 3 4, and so on. The larger the

[48:25]

number, the more padding we'll have.

[48:28]

We also have px for applying horizontal

[48:30]

padding. This is the same as applying a

[48:33]

left and a right padding. We also have

[48:35]

py for vertical padding. We have pt for

[48:39]

padding top, pr for padding right, pb

[48:42]

for padding bottom, and pl for padding

[48:46]

left. Now, you don't have to memorize

[48:48]

any of this stuff. As you practice,

[48:50]

you'll get the hang of them pretty

[48:51]

quickly.

[48:52]

Now, for margins, we have similar

[48:54]

classes, but they start with M, followed

[48:57]

by a number, mx for horizontal margin,

[49:00]

my for vertical margin, and so on.

[49:03]

Now, for styling text, again, we have a

[49:05]

ton of classes. For example, for

[49:07]

controlling the size, we have text-xs,

[49:10]

which is extra small. We have text

[49:13]

small, text base, which is like the

[49:15]

regular size. We have text large, x

[49:17]

large, 2x large, and so on.

[49:20]

For applying colors, we have classes

[49:22]

that start with text, followed by a

[49:24]

color.

[49:25]

So, if you Google Tailwind color

[49:27]

palette,

[49:29]

on this page,

[49:31]

you can see the default color palette

[49:33]

that comes with Tailwind. So, we have

[49:36]

all these beautiful colors, and for the

[49:38]

most part, we don't need to customize

[49:40]

them. They just look great as they are,

[49:42]

but you can always customize these and

[49:45]

use colors that are specific to your

[49:46]

brand.

[49:47]

Now, look for example for sky, we have

[49:50]

various shades of blue that start with

[49:52]

50 and go all the way to 950. The larger

[49:56]

the number, the darker the color. You

[49:59]

will see an example of this later in

[50:00]

this video. Now, back to our slide. For

[50:03]

controlling the background color, we

[50:04]

have a bunch of classes that start with

[50:06]

BG followed by a color code. Now, for

[50:09]

controlling the thickness of font, we

[50:12]

have a bunch of classes like font thin,

[50:14]

font light, normal, medium, bold, and so

[50:18]

on. That's the idea of Tailwind. Now,

[50:20]

there are a lot more classes in Tailwind

[50:22]

that we can cover here, but our focus

[50:24]

here in this course is on Next.js and

[50:26]

not Tailwind. I just want to show you

[50:28]

the basics so you can learn the rest on

[50:30]

your own.

[50:31]

So, let's see these classes in action

[50:32]

and then I will explain why you may want

[50:34]

to use Tailwind.

[50:36]

So, back to our project.

[50:38]

Earlier we used the CSS module to style

[50:41]

our product card. Let's see how we can

[50:43]

use Tailwind instead of a CSS module to

[50:45]

style this component. So,

[50:48]

in this file, we don't need to import

[50:50]

our CSS module.

[50:53]

Instead, we can apply

[50:55]

Tailwind utility classes right here.

[50:58]

Now, in this lesson, I'm going to use a

[51:00]

different set of styles than the styles

[51:02]

we applied in our CSS module so you can

[51:04]

see more of Tailwind in action.

[51:07]

So, we're going to give this some

[51:08]

padding which I type P- Now, if you

[51:11]

press control and space, you can see all

[51:14]

the padding classes. So, we have P-0

[51:17]

which is equivalent to padding zero.

[51:20]

We have padding one which is equivalent

[51:22]

to 0.25 REM or 4 pixels. And as the

[51:26]

number increases, we get more padding.

[51:29]

So, this IntelliSense comes with the

[51:31]

extension that we installed at the

[51:33]

beginning of the course.

[51:34]

So, let's give this a padding of five.

[51:37]

A vertical margin

[51:39]

of five.

[51:41]

Now, I want to give it a background

[51:42]

color so we type BG-

[51:45]

Now, look again in IntelliSense, we can

[51:48]

see all the colors. I'm going to go with

[51:50]

sky-

[51:52]

400.

[51:54]

Now, to make the text white, here we

[51:56]

apply text- white.

[51:59]

We can make it large.

[52:01]

So, here we use text XL or 2XL, 3XL, and

[52:05]

so on.

[52:06]

Again, on the right side you can see the

[52:08]

actual size that is applied. So, for

[52:10]

text XL, font size is 1.25 REM or 20

[52:14]

pixels.

[52:16]

Now, here's the part that gets

[52:17]

interesting. Here we have pseudo

[52:19]

selectors like hover

[52:21]

and with this, we can apply styles when

[52:24]

we hover over this box or this div.

[52:26]

So, we can change the background color

[52:28]

to BG sky 600 or 500 to make it slightly

[52:34]

darker.

[52:35]

Now, back to the browser. Here's our

[52:37]

div. If you hover over it, you can see

[52:39]

the color changes.

[52:41]

So, this is how we style our

[52:42]

applications with Tailwind. Now, the

[52:44]

selling point of Tailwind is that we can

[52:46]

style our components right here in our

[52:49]

component file. We don't have to juggle

[52:51]

back and forth between a CSS file and a

[52:53]

component file. Everything is in one

[52:55]

place. Now, some people argue that this

[52:58]

violates the separation of concerns

[53:00]

principle, but I have to disagree with

[53:03]

that because the whole idea of

[53:05]

separation of concerns is organize our

[53:07]

code into distinct sections or modules,

[53:10]

each having a separate concern.

[53:13]

If you follow this principle, we'll have

[53:15]

more opportunities for reuse. But in

[53:17]

this case, this React component itself

[53:20]

is a module and defines the reuse

[53:22]

boundary. So, what we have inside this

[53:25]

boundary is purely implementation

[53:27]

detail. We can have markup with

[53:29]

JavaScript and style all next to each

[53:32]

other. What is inside is irrelevant to

[53:34]

the outside world as long as this

[53:36]

component or this module is reusable.

[53:39]

That's just what I think. If you

[53:40]

disagree or don't like using Tailwind,

[53:42]

that's totally fine. But again, if you

[53:44]

want to expand your job opportunities, I

[53:46]

highly encourage you to learn Tailwind

[53:48]

because it's in high demand these days.

[53:50]

But there's one more benefit to using

[53:52]

Tailwind and this is the reason I

[53:53]

personally love Tailwind. With Tailwind,

[53:56]

when we build our application, our final

[53:58]

CSS bundle will only have the utility

[54:01]

classes that we have used in our markup.

[54:04]

So, if tomorrow we delete this div, none

[54:07]

of these classes will be in our final

[54:09]

CSS bundle unless we have used them

[54:11]

somewhere else. So, with Tailwind, we

[54:13]

don't have to remember to clean up as we

[54:16]

change or delete our components. With

[54:18]

CSS modules, if we delete this

[54:21]

component, we have to remember to delete

[54:23]

the CSS file as well. Or, if we change

[54:26]

the structure here, we might still have

[54:28]

unused classes in our CSS module. So, we

[54:31]

have to remember to come back and clean

[54:32]

up. So, that's the selling point that

[54:35]

convinced me to start using Tailwind.

[54:37]

But on the flip side, I don't like that

[54:39]

over time, as our markup gets complex,

[54:42]

we'll have a lot of these classes and

[54:44]

the code is kind of hard to read, but

[54:46]

it's just a matter of getting used to

[54:47]

it. It's not terribly bad, but it's

[54:49]

something that put some people off early

[54:51]

on, but over time, I think the benefits

[54:54]

outweigh the downside.

[55:02]

All right, and let's talk about DaisyUI.

[55:05]

DaisyUI is a very popular component

[55:07]

library for Tailwind. It's kind of like

[55:09]

Bootstrap for Tailwind. So, if you head

[55:12]

over to daisyui.com,

[55:14]

you can see all these components.

[55:17]

For example, we have accordions, alerts,

[55:20]

we have breadcrumbs, buttons, cards,

[55:24]

carousel, chat bubbles, and so on. Very,

[55:27]

very useful. It's very easy to use, so

[55:30]

let's go

[55:31]

to the installation page.

[55:33]

First, we have to install

[55:35]

Daisy

[55:36]

as a development dependency. So, I'm

[55:39]

going to copy this line.

[55:40]

Now, back in VS Code, I've opened my

[55:42]

terminal window. You can open it from

[55:44]

terminal, new terminal.

[55:47]

Now, let's paste that.

[55:51]

Good. Next,

[55:53]

we should add Daisy as one of the

[55:56]

plugins of Tailwind. So, we should go to

[55:59]

Tailwind configuration file in the root

[56:02]

of our project. So, that is right here.

[56:07]

Currently, there are no plugins. So,

[56:09]

let's copy

[56:11]

this line and

[56:13]

paste it here.

[56:15]

That's literally all we have to do.

[56:18]

Now, let's see how we can use these

[56:20]

components. So, as an example,

[56:24]

we're going to look at the button

[56:26]

component.

[56:27]

So, here we have a bunch of classes like

[56:30]

BTN, BTN- neutral, BTN-primary,

[56:33]

secondary, and so on. Exactly like

[56:35]

Bootstrap. Under these classes use

[56:38]

Tailwind. So, instead of us manually

[56:40]

combining a bunch of small Tailwind

[56:42]

classes to create a button, we can just

[56:45]

use the button that comes with Daisy.

[56:47]

And of course, we can always customize

[56:49]

these buttons, okay?

[56:51]

So, to create a button,

[56:53]

look, we should have an example down

[56:55]

here. There you go. This is just a basic

[56:57]

button. We also have neutral, primary,

[57:00]

secondary, and so on.

[57:01]

So, back to our code.

[57:04]

Let's style this component that we

[57:07]

created earlier. Add to cart. So, here

[57:10]

we have a button.

[57:12]

We set class name to BTN, BTN-primary.

[57:16]

We don't have to import anything in this

[57:18]

file, okay?

[57:19]

Now, back to the home page. Here's what

[57:21]

we get. Let's remove this blue

[57:22]

background because it looks kind of odd.

[57:25]

So,

[57:26]

we're going to go back to

[57:28]

product card.tsx

[57:31]

and I'm going to remove all these

[57:34]

Tailwind classes.

[57:35]

Okay?

[57:36]

So, here's what we are left with. Now,

[57:39]

in Daisy, we have the concept of themes.

[57:42]

For example, if you look at this page,

[57:45]

themes,

[57:47]

you can see all the available themes.

[57:50]

Now, in this lesson, I'm going to use a

[57:52]

theme called winter. And you can always

[57:55]

preview these themes. So, on the top,

[57:57]

you can select them and see what your

[57:59]

application looks like. Here's the dark

[58:02]

mode. Here we have the cupcake theme,

[58:04]

and so on.

[58:05]

Now, to use a theme, there are two steps

[58:07]

we have to follow. First, we have to go

[58:10]

in Tailwind configuration file and add

[58:13]

this section for DaisyUI. So, here we

[58:15]

activate the themes we want to use.

[58:18]

So, let's copy

[58:20]

this section

[58:22]

and go back to tailwind.config.ts.

[58:26]

Right after plugins, we paste this.

[58:28]

So, we have DaisyUI. We have themes. I

[58:31]

don't want to use any of these. I only

[58:32]

want to use

[58:34]

the winter theme.

[58:36]

The second step is to apply this theme

[58:39]

on our HTML element. So, back in the

[58:41]

documentation, look, here we have a data

[58:44]

attribute for specifying the theme.

[58:46]

To do that, we have to go to our layout

[58:48]

file

[58:50]

because this is where we have our HTML

[58:52]

element. So, we set data-theme

[58:55]

to winter.

[58:58]

Now, back to our home page, our button

[59:00]

looks blue. Beautiful.

[59:01]

Now, let's go to the users page and

[59:04]

put these users inside a table. So,

[59:07]

let's go to the users page

[59:10]

and replace

[59:12]

this unordered list with a table. So, we

[59:15]

select this and press command and D on

[59:18]

Mac or control and D on Windows to

[59:20]

activate multiple cursors. Now, we can

[59:23]

change these two elements in one go. So,

[59:25]

we change it to a table.

[59:28]

Then, we press escape to deactivate

[59:31]

multiple cursors.

[59:32]

Now, inside this table, you want to have

[59:34]

a t head. Inside a t head, we want to

[59:36]

have a t r, and inside the t r, we want

[59:39]

to have two t h elements. Let's press

[59:42]

tab.

[59:43]

Here's our markup, beautiful.

[59:45]

Now, here we want to have two columns.

[59:46]

The first one is username, the second is

[59:49]

user email.

[59:51]

Now, after the t head element,

[59:53]

we should add a t body.

[59:56]

Then we move

[59:57]

mapping over users inside t body

[60:00]

and replace l i with t r. So, once

[60:04]

again, we press command and d on Mac or

[60:06]

control and d on Windows to change both

[60:09]

these elements in one go. So, let's

[60:11]

change it to t r.

[60:13]

Now, inside this t r,

[60:15]

we want to have two t h elements. So, t

[60:18]

h * 2.

[60:20]

Let me put it on a separate line.

[60:23]

Good. In the first t h, we want to

[60:25]

render user.name.

[60:28]

In the second, we want to render

[60:30]

user.email.

[60:32]

Now, currently, we don't have email in

[60:34]

the interface that we defined for our

[60:36]

users. That is why we get a compilation

[60:39]

error. So, this is another benefit of

[60:40]

using TypeScript. The TypeScript

[60:42]

compiler tells us about these issues

[60:45]

before we run or deploy our application.

[60:48]

We can catch these errors at compile

[60:49]

time or even while coding. So, up here,

[60:53]

we have the user interface.

[60:56]

Let's add an email property of type

[60:58]

string.

[60:59]

Now,

[61:01]

the error goes away. Lovely. So, back to

[61:04]

the browser.

[61:05]

Here's what we get. Now, let's apply a

[61:07]

couple of classes from Daisy to make

[61:09]

this table look a little bit nicer.

[61:11]

So, back to our code.

[61:13]

Here's our table.

[61:15]

We set class name to

[61:17]

table and table-

[61:19]

bordered.

[61:21]

And of course, you can find these in the

[61:23]

documentation for the table component in

[61:25]

DaisyUI.

[61:27]

Okay, this is much better.

[61:29]

Now, I made a mistake earlier. When

[61:31]

rendering these rows, I used the t h

[61:34]

element.

[61:36]

That is why they appear as bold, but we

[61:39]

should use t h only as the column of our

[61:41]

tables.

[61:43]

So, let's change all of these t h

[61:44]

elements to t d. Once again, we select

[61:47]

one of them

[61:48]

and we press command and d to select

[61:51]

more of them.

[61:53]

So, now we have four cursors. Let's

[61:55]

change all of them to t d.

[61:58]

Okay, here's what we get.

[62:00]

Now, we no longer need the time stamp,

[62:01]

so

[62:02]

let's remove it from here as well.

[62:06]

Good. So, we're done for now. In the

[62:08]

next section, we're going to talk about

[62:10]

routing and navigation in more detail.

[62:14]

Hey guys, I hope you've been having fun

[62:15]

watching this tutorial. I just wanted to

[62:17]

mention that this tutorial is the first

[62:20]

hour of my complete Next.js course. So,

[62:23]

after you finish this, if you want to

[62:24]

learn more, I highly recommend you to

[62:26]

enroll in the full course because it's

[62:28]

much faster and easier than jumping

[62:30]

between a bunch of random, disconnected

[62:32]

tutorials here on YouTube. The full

[62:35]

course is 5 hours long and teaches you

[62:37]

everything you need to build full stack

[62:39]

applications with Next.js. It also comes

[62:42]

with a certificate of completion and a

[62:44]

30-day money-back guarantee. So, if

[62:46]

you're not happy, ask for a full refund,

[62:48]

you get all your money back, no

[62:50]

questions asked. In case you're

[62:51]

interested, the link is below this

[62:53]

video.

Keep this transcript

Save it to LunaNotes and it becomes a real note in your library — editable, searchable, and ready to turn into flashcards or a diagram. Free to start.

Save to LunaNotes

Or download subtitles for another video.

These subtitles were extracted using the Free YouTube Subtitle Downloader by LunaNotes.

Related videos

Download Subtitles for FastAPI React B2B SaaS Project Tutorial

Download Subtitles for FastAPI React B2B SaaS Project Tutorial

Enhance your learning experience by downloading accurate subtitles for the FastAPI + React B2B SaaS full project tutorial. Captions help you follow complex concepts like organizations, users, billing, and roles with ease, ensuring you never miss important details.

Download Subtitles for Learn This Skill to Thrive in 10 Years

Download Subtitles for Learn This Skill to Thrive in 10 Years

Enhance your understanding by downloading subtitles for the video 'Learn This Skill If You Want To Thrive In The Next 10 Years.' Subtitles help you grasp key concepts clearly and make learning accessible anytime, anywhere.

Download Subtitles for Introduction to DaVinci Resolve Full Course

Download Subtitles for Introduction to DaVinci Resolve Full Course

Enhance your learning experience by downloading accurate subtitles for the Introduction to DaVinci Resolve full course. Captions help you follow along effortlessly, improve comprehension, and make the tutorial accessible anytime, anywhere.

Download Subtitles for Beginners Faceless Instagram Theme Page Tutorial

Download Subtitles for Beginners Faceless Instagram Theme Page Tutorial

Enhance your learning experience with downloadable subtitles for the comprehensive Beginners Faceless Instagram Theme Page Tutorial. Follow every step clearly in this 5.5+ hour guide, making it easier to grasp key concepts and strategies for 2026. Perfect for non-native speakers and those who prefer reading along.

Download Subtitles for 'How Transistors Run Code' Video

Download Subtitles for 'How Transistors Run Code' Video

Enhance your understanding of computing with downloadable subtitles for the "How Transistors Run Code" video. Access clear, accurate captions to follow along easily and reinforce your learning experience.

Most viewed

Untertitel für 'Nicos Weg' Deutsch lernen A1 Film herunterladen

Untertitel für 'Nicos Weg' Deutsch lernen A1 Film herunterladen

Laden Sie die Untertitel für den gesamten Film 'Nicos Weg' herunter, um Ihr Deutschlernen auf A1 Niveau zu unterstützen. Untertitel helfen Ihnen, Wortschatz und Aussprache besser zu verstehen und verbessern das Hörverständnis effektiv.

ดาวน์โหลดซับไตเติ้ล DMD LAND 3 The Final Land Day 1

ดาวน์โหลดซับไตเติ้ล DMD LAND 3 The Final Land Day 1

ดาวน์โหลดซับไตเติ้ลสำหรับวิดีโอ DMD LAND 3 The Final Land Day 1 เพื่อช่วยให้เข้าใจเนื้อหาได้ง่ายขึ้น และเพิ่มความสะดวกในการติดตามทุกช่วงเวลา เหมาะสำหรับผู้ชมที่ต้องการความชัดเจนและเข้าถึงข้อมูลอย่างครบถ้วน

Descarga Subtítulos para NARCISISMO | 6 DE COPAS - Episodio 63

Descarga Subtítulos para NARCISISMO | 6 DE COPAS - Episodio 63

Accede fácilmente a los subtítulos del episodio 63 de '6 DE COPAS', centrado en el narcisismo. Descargar estos subtítulos te ayudará a entender mejor el contenido y mejorar la experiencia de visualización.

Subtítulos para TIPOS DE APEGO | 6 DE COPAS Episodio 56

Subtítulos para TIPOS DE APEGO | 6 DE COPAS Episodio 56

Descarga los subtítulos para el episodio 56 de la tercera temporada de 6 DE COPAS, centrado en los tipos de apego. Mejora tu comprensión y disfruta del contenido en detalle con nuestros subtítulos precisos y accesibles.

Download Subtitles for Your Favorite Videos Easily

Download Subtitles for Your Favorite Videos Easily

Enhance your video watching experience by downloading accurate subtitles and captions. Enjoy better understanding, accessibility, and language support for all your favorite videos.

Found this transcript useful?

Take it with you. One click puts it in your own LunaNotes library.

Save to LunaNotes

Start taking better notes today with LunaNotes