Now that we've added authentication using Clerk, let's also use their organizations feature to transform our project from single tenant to a proper multi-tenant b2b application. The first thing I want to do is clean up some of the things I don't like in our current authentication implementation. So because we needed to demonstrate that authentication works, what we did is we enabled the home screen to be a public route. So that's the first thing I'm going to remove. I don't want the home screen to be a public route, meaning that if I am signed out, the only route I want visible are the sign in and sign up routes.
But as you can see I have this weird header here and that is visible on every single route because it was embedded in the layout file. So that's the first thing that I'm going to remove. And depending on what code you have it might not be in a header, it could just be rendered in a normal div. So here's what we can do. I'm gonna go ahead and open Cloud Code and since I'm already speaking whenever I type, I might just use text to speech, which you can also do using this icon right here or any other app like WhisperFlow, SuperWhisper or open source tools like Handy.
Clean up my layout.tsx file and make sure that there isn't any out logic inside besides the clerk provider, meaning that I don't want any header components which use clerks show components or sign in and sign up buttons. All of that will be triggered from other pages, not the root layout. And here is my prompt. So exactly as I said, I don't want any ALT logic inside of my layout.tsx so I'm just going to make sure that ALT is properly spelled here. The only thing I don't want changed is the clerk provider.
So I just don't want to have any header components and I don't want to have any show components or sign in and sign up buttons. And let's go ahead and use auto mode with effort high on Opus 4.8 to do this. There we go. It says done. The app layout now contains no auth UI.
The header, the show, sign in button, sign up button, user button, and unused button imports are all gone. Only the clerk provider, which wraps the theme provider, children and toaster remains. So out actions can be triggered from individual pages. Perfect. So let's take a look at our current changes.
In my layout.tsx I have removed all imports from Clerk Next JS besides the clerk provider. I have removed the unused button component and now what I render is just a clerk provider which renders the theme provider and the children with the toaster inside. To show you the actual final code, this is what it looks like. So very similar to what we had in the beginning, I just left the clerk UI themes, chatCN, CSS. I left the clerk UI themes, chatCN and the clerk provider because all of that is important for clerk setup, but I don't want the actual clerk UI to be rendered here in my root layout file because that will make it visible everywhere.
This is what I wanted. So when I log in, I will then be redirected to this page right here. But obviously we are now missing a logout button from here. So let's go ahead and add that as well. So just as we've cleaned this up, I'm now going to tell it the following.
Now go ahead and clean up my page.tsx. The only thing I want rendered inside is the user button component from Clerk. Let's see if I did this correctly. So now go ahead and clean up my page.tsx. The only thing I want rendered inside is the user button component from Clerk.
Let's see if I did this correctly, so now go ahead and clean up my page.tsx, the only thing I want rendered inside is the user button component from clerk. So I'm once again going to execute this in auto mode. This should be pretty simple. I don't want anything else rendered inside and the reason we can safely render the user button inside app.page.tsx. Let's take a look at this change here.
So once again you can see I deleted everything in here and now it's much simpler actually my app page.tsx as you can see now only renders the user button the reason we can now safely do this is because we have modified our proxy.ts so it no longer includes that home page inside of the public route. If we accidentally left this, then it would probably create some problems. But as you can see now, when a user is logged in, all they see is their user button. And if I sign out, I'm redirected to sign in or sign up pages. And if I try to manually go here, it redirects me back here.
Perfect. So this is the setup that I actually like that is easier for us to develop going forward rather than having to do it later. Before we add organizations, let's do one more thing. So I don't like how my sign in and sign up folders are just here standalone in the app folder. I'd like to put them under one folder so that they're grouped together.
But the problem is if we just create a brand new folder called out and then drag those two folders inside, that would become the part of the URL. So I would have to use out sign in. And that would require us to also change our dot environment variables here. So let's go ahead and use something called route groups. So I'm gonna go ahead and open Cloud Code.
I'm going to open a new conversation because this one is kind of unrelated and I'm gonna do the following. Go ahead and organize my sign in and sign up routes to all be under a singular Next.js route group, meaning you will have to use parentheses in the folder name and call that route group ALF. Looks like My pronunciation of ALF is not really good, but this is what I meant. ALF. Go ahead and organize my sign in and sign up routes to all be under a singular Next.js route group, meaning you will have to use the parentheses in the folder name and call that route group ALF.
Let's go ahead and execute this and see the result. Let's go ahead and look at its thought process because I think it's really interesting. So it said I'll take a look at the current structure of the app directory and see the sign in and sign up routes. And then what it did is the following. Let me check the docs since ClaudeMD warns that this Next.js version differs from what I know and this is exactly why we added that symbolic link from agents.md to claude.md to instruct the whatever agent you're using that this is not the Next.js you know, meaning not the Next.js from their training data because that can be drastically outdated.
So what it did is it read from Node module's Next.dist docs. And in here it found routegroups.md documentation and then it implemented exactly what I wanted an out folder in parenthesis that doesn't affect the URLs but lets us group files like this. So if you take a look at my file structure now, I now have an out folder and inside sign in and sign up route. So they were technically just moved here. But what's important is that they are in parentheses.
So nothing has really changed. Everything works exactly the way it worked before. If I go ahead and try to access localhost 3000, I'm once again redirected to sign in and it works perfectly. And login also works of course. Brilliant.
So now we are ready to go ahead and focus on setting up organizations. One thing I would always recommend whenever you do agentic coding is to create checkpoints so you don't lose your files because we just did a successful refactor of our homepage, of our proxy, of our layout, and of our file structure for the out folder so you can see that I have a combination of five staged and unstaged changes here. It's a pretty good idea for me to commit this so that my upcoming prompts don't accidentally modify what I know works perfectly fine and so that I can always easily revert to this checkpoint if something goes wrong. So I'm going to go ahead and do git add, small-alph refactor And git push. And now all of our changes are committed, so we don't have to worry about them being overridden with some other prompt that we are going to do.
Whenever you use agentic coding to develop with a third party tool, it's a good idea to make it aware of its documentation and how to use it properly, because if it doesn't have that information, it's just going to rely on its training data or it's going to use some kind of web search, which can waste a lot of tokens if it doesn't know what to look for. Thankfully, the Clerk team has prepared skills for us to add to our AI agent. And if you're wondering what is NPX skills, it is the facto standard for distributing skills for AI agents. So you can find the exact same prompt by searching for clerk on skills.sh website. So whether you find the prompt from here or from here is the exact same thing.
What's important is that you are inside of your project and then go ahead and run this command. Now let's go ahead and choose which skills we're going to install. So I would recommend installing the entire core group because we are going to need all of these. Then let's go ahead and add all features as well and under frameworks you can just select Clerk Next.js patterns. You don't need to install the React patterns because the Next.js patterns technically includes that as well.
The React patterns is more of a name if you're developing a single page application and are going to use specific clerk react packages with Vite for example. So you don't have to pick that even though we are using react and you don't have to select anything else because we are not using anything on mobile and we are not using Clerk with Expo. So just make sure you've selected all the features. For me, those are billing, organizations, and technically we don't need testing and webhooks, so you can actually remove those two. So just make sure you have billing and organization selected.
Now, clerk setup, custom UI, CLI, clerk backend API and clerk. I think all of these are useful to have even if we end up not using them, but let's just leave them here. And then go ahead and press enter. In here it's going to ask you for which agents you want to install this for, so just find your agent. I'm going to select Cloud Code here and down here you can find all other options.
So if you are using something different, go ahead and select that. So you can find Open Code here, you can find Codex here, basically whatever is the agent which you're using, go ahead and select it. You should see a green circle next to it. Then it's asking you where to install this. I would highly recommend picking project, meaning install in the current directory.
So the skills are committed with your project so that whoever picks up on this project can continue developing with it with the exact same agent instructions and skills. And for the installation method, feel free to choose symbolic link, which is a single source of truth with symbolic links to all other agents for which you want to install this for. And let's go ahead and proceed with the installation. You will now have a bunch of unsaved or should I say uncommitted changes in your project, so don't worry. All that is is updates in the .cloud folder and .agents folder with the exact skills which we have selected.
So to make sure that these aren't interfering with the changes we are actually going to do, what I would recommend is simply committing all of them. So let's go ahead and do git commit fit add clerk skills as simple as that and then git push. This way you don't have any uncommitted changes so they are not interfering with the changes that we are actually going to do. Now let's go inside of Cloud Code, Open Code, Codex, whatever you're using and verify that you actually have Clerk skills available. So search for Clerk like this and you should now see a bunch of commands which are basically Clerk skills.
If you're not seeing these commands, you can go ahead and use reload skills in Cloud Code which will add new skills and if that's still not working you might have to close and reopen Cloud Code entirely or maybe your entire IDE if you're using an integration like I am. Let's go ahead and implement organizations now. Go ahead and enable organizations in this clerk project. Go ahead and create a new page choose-organization which is going to render the UI for choosing an organization using clerk components. Use clerk organization skill for this task.
Let's take a look. So go ahead and enable organizations in this clerk project. Go ahead and create a new page, choose dash organization, let's call it organizations, actually no it's organization, correct, which is going to render the UI for choosing an organization using the clerk components. Use the clerk organization skill for this task. Let's go ahead and proceed with this prompt.
Let's take a look at what it did. First it decided it's going to use the clerk organization skill for this task, exactly as we expected. Then, it explored the project structure to be aware of where it's working. Then, it verified whether it can use the clerk CLI and whether we are authenticated with the clerk CLI. This is a very similar step as we did in our previous conversation where we set up clerk in the first place.
So at this point, we already have the clerk CLI and we are authenticated with it. So then all it had to do is run clerk enable organizations. And that is essentially the same as us going onto the clerk dashboard and enabling organizations ourselves. Then it went ahead and created the choose organization page exactly as I've instructed it to do so. And it also registered that new page, choose organization in the clerk provider.
And we can actually take a look at the summary down below. So first it enabled organizations in Clerk, via Clerk enable organizations. The membership mode defaults to membership required, exactly as we expect. So signing users without an organization are routed through the Choose Organization Session task. It created the page and it put it inside of the out route group.
So it isn't terribly important if your agent didn't do that. It's just for organization. If you want to, you can instruct it to move the choose organization page to the out route group to be a long sign in and sign up. Rendering clerks task choose organization component, which is the purpose built UI for the choose organization session task which redirects to the root on completion. Perfect.
And then it wired that into clerk provider. Brilliant. This is exactly what we wanted and there aren't that many changes actually. As you can see we have a brand new choose-organization page which now renders the task choose organization within a div like this and the other thing it did is it modified the layout.tsx so that the clerk provider now has task URLs and when it comes to choose organization, so this is an enum, so if it misspells this you will have an error, right? So it needs to be choose organization and it redirects to where?
Well, to exactly the name which I specified for the route. Since I knew that this is an enum in clerk, that's why I chose this name. So it matches. So it makes sense, right? Brilliant!
So let's go ahead and check it out now. Since I already have one account, I'm actually not sure how it's going to behave. Let's log in and see. Will it ask me to create an organization? There we go.
So I'm redirected to tasks, choose organization. So I'm going to create Antonio's organization right here. And then I'm redirected to this page. Brilliant! So now let's go ahead and add one more thing.
So I'm going to tell it to do the following. Now go ahead and add organization switcher just beneath the user button in page.tsx. So this way we can actually see which organization is currently active in our project. And there we go. So with just a very simple simple prompt it added an organization switcher which allows me to create another organization like this and I can now click create organization.
I can also send invites and I can decide whether that's going to be a member or an admin. And from the organization switcher, I can always change between organizations. Just like that, we've implemented an entire B2B suite in our project. And if you go ahead and visit the organizations in your clerk dashboard, you will now see that you have those two organizations right here. You can also verify by going inside of configure organization settings, make sure that you have membership required set to the active option, even though that is a standard.
In here, you can also find some other settings for the organizations, but for now, I would recommend leaving it as is. And before we commit, I just want to demonstrate how the sign up flow and organization creation or organization selection flow looks now in a completely new account. So I'm going to go ahead and click continue with Google and I'm going to enter with a brand new account here And let's see what happens. So the first thing here is the ability to join an organization that I'm actually invited to. Or I can create a new organization.
So this is only visible to me because I invited myself to this organization. But if I go ahead and just create my organization, you will see that instead I have an invitation here. So I have one as in one notification, meaning that this is something I'm invited into. And now I'm part of the same organization as I am in this browser right here. And that is how we are going to implement multi-tenancy and live collaboration in the canvas.
So let's go together through our changes before we commit. So first things first, the clerk provider now has task URLs which redirect the choose organization task to a specific route choose organization. No new imports have been added, just a simple prop to the clerk provider. Next, we have the actual organization switcher added to under our user button. The organization switcher is a component imported from the same place as the user button.
So this is in our global page.tsx. And the last thing that's been added is inside of our auth route group we now have choose-organization which has a page which renders the task choose-organization from clerk-next.js brilliant So let's go ahead and commit all of this, git add and let's do git push. After I pushed these changes to my GitHub repository, Railway did an automatic deployment and something caused it to fail. And it wasn't until closer inspection that I found a very interesting error. If you take a look at this error message which you may or may not have, perhaps they've changed this in the future, but my error message specifically mentions .cloud folder, skills and then clerk next.js patterns.
Now at first I didn't understand how could this file or folder possibly cause the deployment to fail So I went into my code base and I found that exact folder. So inside of .cloud or inside of .agents, if that's what you use, you should have clerk next JS patterns. And then I found this templates folder and then it clicked for me. Inside they have a very small replica of a Next.js application with its own package.json. So that is probably what confused Railway or RailPacks and causes the deployment to fail.
Luckily for us, the fix is very simple. All that we need to do is create a new file .dockerignore and inside put clod and agents So these two folders because agents also has the exact same templates inside. Then go ahead and commit those files. And once you push this, it's going to trigger the redeployment once again. And that will result in a successful deployment.
So adding dockerignore and adding those files or folders inside skips the attempt of RailPacks to initialize that or build that as a standalone Next.js application and successfully deploys our application instead.