
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
How do I remove the blur effect from my CSS?
I removed but the blur is still there. Any ideas?
filter: blur(5px);
Does work for removing blur from modals?
backdrop-filter: none;
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
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
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:02 All right, let's talk about logging in Next.js.
00:00:06 When your app's running, logging is key to keeping track of what's happening, catching errors and debugging.
00:00:13 But not all loggers are created equal.
00:00:15 So what are our options?
00:00:17 Well, the first one is the good old console log.
00:00:21 Yep, that's it.
00:00:22 Easy, built-in, familiar, great for quick logs, but super basic.
00:00:27 No structured logging, no extra features, not really built for larger apps.
00:00:32 The second one is Winston.
00:00:34 A logger for just about everything.
00:00:38 It has cool features like customizable formats and different log levels like error, warn, and info.
00:00:44 And you can also send logs to multiple places like consoles, files, and even databases.
00:00:49 But all that flexibility comes with a performance hit.
00:00:52 There's also the Bunion Logger, a simple and fast JSON logging tool.
00:00:56 It's completely JSON based, so the logs are easy to parse and analyze, especially for server-side use.
00:01:02 But it's a bit older and might feel a bit limited compared to other options.
00:01:08 And finally, there's Pino.
00:01:09 Super fast, all-natural JSON logger.
00:01:13 Lightning fast, output slogs in JSON, super handy for tracking and monitoring, and it's lightweight with minimal overhead.
00:01:21 Perfect for high-performance applications like Next.js.
00:01:24 And it's the one we'll use in our Next.js application.
00:01:28 But why did I make that choice?
00:01:30 Well, long story short, Pino is fast, structured, efficient, so if you want something reliable that doesn't slow the app down,
00:01:37 I found Pino to be the way to go.
00:01:39 Now, logging in general may seem simple, but picking the right tool can make a huge difference in performance and clarity.
00:01:45 So, let's give Pino a shot.
00:01:47 We can install it by running mpmipino in our terminal, and along Pino, we'll use Pinopretty, an add-on that formats JSON logs into a more readable format
00:01:57 for development.
00:01:58 Pino outputs everything as compact JSON strings, which are great for machines, but we need something that's human readable.
00:02:05 So that's why we can install PinoPretty as well.
00:02:08 It is as simple as running MPMI PinoPretty.
00:02:13 Now let's create a new file within the lib folder.
00:02:17 And I'm going to call it logger.ts.
00:02:20 Within it, we can start implementing the logger by saying const logger is equal to pno, which we need to import from the top by saying import pno from pno.
00:02:34 And we can call it as a function and pass the options into it.
00:02:38 First, we need a level inside of which we want to log.
00:02:42 And in most cases, that's going to be just the info.
00:02:45 But as you can see, Copilot suggests that we can get access to the log level based on environment variables.
00:02:51 So let's do that.
00:02:52 Process.env is equal to log level or info.
00:02:56 Next, we also need to define our environment.
00:02:59 Sometimes we are running Next.js application on what's known as the edge.
00:03:04 or Edge runtime, and sometimes we're running it in a production.
00:03:07 And in this case, I found PinnoPretty to have issues working with Edge runtimes when used with NextAuth.
00:03:15 Very interesting issue, but to fix it, we don't need to use PinnoPretty in production, but just locally.
00:03:21 So we can extract that environment variable by saying isEdge and make it equal to process.env.next underscore runtime.
00:03:34 And if it's triple equal to edge, that means that we are on edge.
00:03:38 Next, we can also figure out if we are in production by saying const is production.
00:03:43 And that's going to be equal to the node environment, triple equal to production.
00:03:47 Now we can say transport.
00:03:49 How do we want to transport our error?
00:03:51 Well, we can say if not is edge and not is production.
00:03:59 In that case, we can return an object, else we'll return undefined, meaning nothing.
00:04:06 Within this object, we can say target is going to be pnopretty, with options of colorize is set to true, ignore, PID and host name.
00:04:20 We don't need that kind of info because it's just going to clutter the view.
00:04:24 And the translate time can be set to SYS, system, standard.
00:04:32 Great.
00:04:33 So now we have the transport.
00:04:34 And finally, I can change the formatters a bit more by changing the level of the formatter by getting its label and then simply returning the level to
00:04:44 be equal to label to uppercase like this.
00:04:48 Again, don't worry about this too much before you see it in action because once you do, it'll make sense.
00:04:53 And finally, we can define the timestamp and set it to be equal to pino.std.
00:05:00 No, it's not a sexually transmitted disease.
00:05:02 It just means standard.
00:05:04 So we're taking the standard time functions and we're taking the ISO time so we know when the log happened.
00:05:10 Now, let's try to add logs at different places.
00:05:13 Of course I have to export default logger and I'll head over to mongoose.ts.
00:05:21 This is where we're defining our mongoose and MongoDB connection.
00:05:24 So let's try to add a log to show whether MongoDB is connected or not.
00:05:29 Here we say if there is a cached connection, then return that cached connection.
00:05:34 Well, let's log that by saying logger.info and we can say using existing mongoose connection.
00:05:43 Okay, pretty cool.
00:05:45 Let's try to add some additional loggers.
00:05:48 Like right here where we're doing just a console log, we can now replace this with a logger.info and then pass the connected2db as a message into the info
00:05:59 instead of asConsoleLog.
00:06:01 And check this out, we can also use our logger.error.
00:06:06 by passing it a message and then an additional error object.
00:06:10 Let's also add loggers within our error handling by heading over to error.ts.
00:06:15 And then whenever we're just returning the formatted response, let's actually log it out.
00:06:21 So right here, we have return format response on handle error.
00:06:26 I will still return it, but now I will add something above it.
00:06:30 I'll say logger dot error.
00:06:33 And this logger of course has to come from dot dot slash logger.
00:06:38 And to it, I'll pass an object where err is equal to error.
00:06:43 And as the second parameter, I'll pass a template string where I'm going to render the response type dot to uppercase.
00:06:54 And then to it, append the error of error.message.
00:06:59 So now we're logging the exact message that we have here.
00:07:02 We can do something similar for all other instances of errors, like the dot error right here, where we can say logger.error.
00:07:11 In this case, we can also pass in the err equal to error, and we can simply say validation error, and then maybe append the validation message to it as well.
00:07:21 We can do the same for the basic error type, which is going to be logger.error.
00:07:26 In this case, we don't know too much about the error, so we can simply pass the error.message.
00:07:31 And finally, just before we return this default error, we can do the same thing.
00:07:36 Locker that error.
00:07:38 We can pass in the object of err equal to error, and then say an unexpected error has occurred.
00:07:45 So now, what do you say?
00:07:46 Shall we test it out?
00:07:48 Let's head over to our page.tsx and let's actually bring back the test function that I deleted.
00:07:55 Hopefully you can just bring it back as well.
00:07:57 If not, just type it out.
00:07:59 You basically have to do cons test, throw an error, catch it, and then also call the test right here.
00:08:05 And here, instead of throwing a validation error, I'll actually say await db connect, which is a function that tries to connect us to the database.
00:08:14 So we can see whether we get those logs.
00:08:16 Now, if you go to the homepage, you'll see type error, the worker script or module file name must be an absolute path starting with yada yada.
00:08:26 This is because new packages, pino and pino-pretty, are causing issues when bundled with Next.js.
00:08:32 To fix this, we'll have to use server external packages.
00:08:36 Let me show you what that is.
00:08:38 Head over to next.config.ts and add a new object called server external packages.
00:08:45 Actually, it's going to be an array.
00:08:47 And to it, pass pino and pino-pretty, like this.
00:08:51 So server external packages.
00:08:54 What does that mean?
00:08:55 Well, if you think of your app as a backpack and the packages you use, like the items you're packing for a trip, normally Next.js tries to put as many
00:09:04 items or packages as it can into the backpack, which is your app bundle.
00:09:08 This is usually good because it means everything is in one place and ready to go when you need it.
00:09:13 But sometimes, you have items that you'd rather keep separated from the main backpack.
00:09:18 Maybe they're too big, or perhaps they work better when they're not squished with everything else.
00:09:24 And that's where server external packages comes in.
00:09:27 It tells Next.js, hey, don't put these specific items in the main backpack, keep them separated.
00:09:33 If you do that, reload the application and go back to your terminal, you should be able to see connected to MongoDB and then later on using existing Mongoose connection.
00:09:46 This is pretty cool.
00:09:47 We also have this one undefined, which is coming from here.
00:09:51 We don't need to console log that result.
00:09:53 But in this case, I wanted to show you how an error looks like.
00:09:56 So if I try to throw a new error that says test error, instead of trying to establish a MongoDB connection, That's going to look something like this.
00:10:07 Error, test error.
00:10:08 Or even better, if we try to bring back those validation errors, if I can.
00:10:13 Let me see if I can do that.
00:10:14 There we go.
00:10:16 I'll go back forward and I'll paste this new thing.
00:10:20 Throw new validation error coming from lib HTTP errors.
00:10:25 Let's see how this looks like.
00:10:27 Well, check this out.
00:10:29 It says error, server error, title is required, JavaScript is not a valid tag, and then gives us more additional error information in case we need it.
00:10:39 But again, just having these logs being shown to us right here, it's super useful to know whether we're using the existing Mongoose connection,
00:10:47 whether the new one is being created, whether something is wrong, whether we're not passing the right properties or validation error or values to our inputs.
00:10:56 In general, it's just good to have proper logging to be on top of what our application is doing while we're developing it.
00:11:03 So with that said, I'll head over here and say, implement logging, commit, and push.
00:11:11 With that in mind, you made your application that much more scalable and this project and your knowledge that much more enterprise ready.