
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! 🚀