Back to Blogs
Building a Responsive Navbar in Next.js with Clerk Authentication

Building a Responsive Navbar in Next.js with Clerk Authentication

5 min read
By Bhargav

Building a Responsive Navbar in Next.js with Clerk Authentication

A step-by-step tutorial on how to develop the Navbar.tsx component

Prerequisites

Before we start, ensure you have the following setup:

  • Node.js installed
  • A Next.js project initialized (npx create-next-app@latest my-app)
  • Clerk authentication set up (npm install @clerk/nextjs)
  • Tailwind CSS configured (npm install tailwindcss postcss autoprefixer and setup Tailwind)

Step 1: Setting Up the Navbar Component

Create a new file in your project inside the components folder:

/components/Navbar.tsx

Now, let's set up the basic structure:

"use client";
import React from "react";
import Link from "next/link";

const Navbar = () => {
  return (
    <nav className="flex justify-between items-center px-4 py-3 bg-gray-800 text-white">
      <Link href="/">
        <h1 className="text-lg font-bold">My App</h1>
      </Link>
      <button className="bg-blue-500 px-4 py-2 rounded">Menu</button>
    </nav>
  );
};

export default Navbar;

Explanation:

  • use client: Ensures the component runs on the client side.
  • We define a <nav> with a logo and a menu button.
  • Link (from Next.js) is used for navigation.
  • Tailwind CSS classes provide styling.

Step 2: Adding Icons for Better UI

We'll use Heroicons, a popular icon library.

Install Heroicons:

npm install @heroicons/react

Update Navbar to Include Icons:

import { Bars2Icon, BookOpenIcon } from "@heroicons/react/24/solid";

const Navbar = () => {
  return (
    <nav className="flex justify-between items-center px-4 py-3 bg-gray-800 text-white">
      <Link href="/">
        <span className="flex items-center gap-2">
          <BookOpenIcon className="h-6 w-6 text-blue-400" />
          <h1 className="text-lg font-bold">My App</h1>
        </span>
      </Link>
      <button>
        <Bars2Icon className="h-6 w-6" />
      </button>
    </nav>
  );
};

Explanation:

  • We added a BookOpenIcon as the logo.
  • The Bars2Icon represents a menu button.

Step 3: Implementing Clerk Authentication

We'll use Clerk to manage user authentication.

1. Install Clerk

npm install @clerk/nextjs

2. Import and Use Clerk

Modify the Navbar to show different content based on login status.

import { useUser, SignOutButton } from "@clerk/nextjs";

const Navbar = () => {
  const { user } = useUser();

  return (
    <nav className="flex justify-between items-center px-4 py-3 bg-gray-800 text-white">
      <Link href="/">
        <h1 className="text-lg font-bold">My App</h1>
      </Link>
      
      {user ? (
        <div className="flex items-center gap-4">
          <p>Welcome, {user.fullName}!</p>
          <SignOutButton>
            <button className="bg-red-500 px-4 py-2 rounded">Sign Out</button>
          </SignOutButton>
        </div>
      ) : (
        <Link href="/sign-in" className="bg-blue-500 px-4 py-2 rounded">
          Sign In
        </Link>
      )}
    </nav>
  );
};

Explanation:

  • useUser() from Clerk checks if a user is signed in.
  • If user is logged in, display their name and a Sign Out button.
  • If user is not logged in, show a Sign In button.

Step 4: Adding a Mobile-Friendly Sidebar Menu

For better user experience, let's add a sidebar.

1. Install UI Components

npm install @radix-ui/react-dialog

2. Import and Use the Sidebar (Sheet)

Modify the Navbar.tsx to include a sidebar:

import {
  Sheet,
  SheetTrigger,
  SheetContent,
} from "@/components/ui/sheet";
import { Button } from "./ui/button";

const Navbar = () => {
  return (
    <nav className="flex justify-between items-center px-4 py-3 bg-gray-800 text-white">
      <Link href="/">
        <h1 className="text-lg font-bold">My App</h1>
      </Link>

      <Sheet>
        <SheetTrigger asChild>
          <Button variant="ghost">
            <Bars2Icon className="h-6 w-6" />
          </Button>
        </SheetTrigger>
        <SheetContent className="p-6 bg-white text-black">
          <Link href="/profile">Profile</Link>
          <Link href="/settings">Settings</Link>
        </SheetContent>
      </Sheet>
    </nav>
  );
};

Explanation:

  • Sheet (sidebar) opens when clicking the menu button.
  • Inside, we add navigation links like "Profile" and "Settings".

Step 5: Displaying User Avatar

Users should see their profile picture in the Navbar.

1. Create an Avatar Component

import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar";
import avatarUtil from "@/utils/avatarUtil";

const { color, initials } = avatarUtil(user?.fullName || "");

<Avatar>
  <AvatarImage src={user?.imageUrl} alt={user?.fullName || ""} />
  <AvatarFallback style={{ backgroundColor: color }}>{initials}</AvatarFallback>
</Avatar>;

Explanation:

  • AvatarImage shows the user's profile picture.
  • AvatarFallback shows their initials if no image is available.

Final Navbar.tsx

After implementing all the steps, our final Navbar.tsx looks like this:

"use client";
import React from "react";
import {
  Bars2Icon,
  ArrowLeftStartOnRectangleIcon,
  BookOpenIcon,
} from "@heroicons/react/24/solid";
import Link from "next/link";
import { SignOutButton, useUser } from "@clerk/nextjs";
import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar";
import { Separator } from "./ui/separator";
import avatarUtil from "@/utils/avatarUtil";
import {
  Sheet,
  SheetTrigger,
  SheetContent,
  SheetClose,
} from "@/components/ui/sheet";
import { Button } from "./ui/button";
import { usePathname } from "next/navigation";

const Navbar = () => {
  const { user } = useUser();
  const pathname = usePathname();
  const { color, initials } = avatarUtil(user?.fullName || "");

  return (
    <nav className="flex justify-between items-center px-4 py-3 bg-gray-800 text-white">
      <Link href={user ? "/orders" : "/"}>
        <span className="flex items-center gap-1">
          <BookOpenIcon height={24} width={24} className="text-blue-400" />
          <h1>Tailor Book</h1>
        </span>
      </Link>

      <Sheet>
        <SheetTrigger asChild>
          <Button variant="ghost">
            <Bars2Icon height={24} width={24} />
          </Button>
        </SheetTrigger>
        <SheetContent>
          {user && (
            <div>
              <Avatar>
                <AvatarImage src={user.imageUrl} alt={user.fullName} />
                <AvatarFallback style={{ backgroundColor: color }}>
                  {initials}
                </AvatarFallback>
              </Avatar>
              <SignOutButton>
                <SheetClose>
                  <ArrowLeftStartOnRectangleIcon height={24} width={24} />
                  Sign out
                </SheetClose>
              </SignOutButton>
            </div>
          )}
        </SheetContent>
      </Sheet>
    </nav>
  );
};

export default Navbar;

Now you have a fully functional, mobile-friendly, authenticated Navbar! 🚀