🚀 Building a Role Based Navigation in NextJS using Clerk
Originally posted on the House of Giants Blog: https://houseofgiants.com/blog/building-role-based-navigation-nextjs-clerk
We’ve been working on a few projects with fairly complex navigation systems here at House of Giants. Different user types need to see different parts of an application and are separate in what they can see based on the role that they’re assigned. As these applications grow these navigation systems can become unwieldy. We’ve developed a system that we think works pretty well.
At a high level, here are a few of the things we’ve found that make role-based navigation tricky:
Let’s see how we can alleviate some of these issues.
🛠️ Step 1: A Modular Navigation Structure
Using a modular approach gives us the ability to change only what we need, only for the user types that are affected. Keeping logic separate ensures that changing one piece doesn’t create a litany of issues for other users.
1. Define Individual Navigation Items
Start by setting up a single source of truth for all navigation items. This keeps things consistent and eliminates redundancies. These are just basic objects, customize them and their data based on your needs.
2. Create Reusable Navigation Sets
At this point we found it helpful to define some commonly used groupings. This lets us build different navigation layouts without repeating ourselves. ✨
3. Organize Navigation into Sections
With items and sets defined, we can further organize the navigation into logical sections. This keeps everything structured and makes it easy to add or remove sections later. We’ve opted to create a new Set to further ensure that no duplicate routes are provided. A value in a set may only occur once, duplicates are omitted.
In our case, we’re adding a text value to our sections, this acts as the parent dropdown label for the set of navigation items.
4. Configure Role-Based Access
Here’s where we map user roles to the sections they should see. This keeps role-based logic centralized and easy to adjust 🔒 – keep in mind here, we’re using Clerk.com role names here, yours may be different.
5. Build the Navigation Hook
We decided that building a custom hook here would serve us best when building the UI for the navigation. Our hook assembles the navigation based on the user’s role and will return only the sections relevant to each user.
You’ll see above that we’re creating a function called getNavigationItems and passing this function the userRole from Clerk. We then define the sectionNames based on that userRole, or default to the nav a basic user would see, providing us with a clean fallback.
We then map over those section names and return the title as well as the nested navigation items.
Finally, we define our hook. We get the User’s role from Clerk using the sessionClaims object that is returned with await auth(), thus returning our navigation object, which will look something like this:
🌟 Why This Works
This setup has some awesome advantages:
Example Usage
Here’s how you might use this navigation structure in a Sidebar component:
File: Sidebar.js
📝 Best Practices
A few tips to keep your navigation organized and manageable:
This approach provides a solid foundation for a scalable, maintainable navigation structure. By organizing navigation into modular components, you get a flexible system that grows with your app—without becoming an absolute nightmare to maintain.
Remember, the goal is to strike a balance between flexibility and simplicity. This setup does just that, making it practical for real-world applications. 👌
🔥