In this chapter, we're going to go ahead and prepare our application for deployment. I might split this chapter into two parts, depending on how long it will take us just to deploy this to Vercel. And also because after we deploy to Vercel, the next step is to add a wildcard subdomain which will allow Vercel to create infinite subdomains based on our tenants. But keep in mind that in order for that to work, you're going to have to own an actual domain, or you're going to have to purchase a new one. I will of course guide you through the entire process regardless of if you are going to do that with me or not.
So at least you will see how it's done. But if you don't want to do that in the end, I will also show you how you can easily revert the subdomain changes. I mean, it's as easy as removing the middleware and modifying the generate tenant URL method to what it was before. But anyway, let's go ahead and go through with this as we imagined in the first place. As always, ensure that you are on your main branch and that you have merged everything you need to merge.
You can shut down everything. And let's start with bun run build. So what this is going to do is it's going to run some linting and some type checking and throw us any errors if anything here is blocking from building a production build. So this way we will save some time. Usually we would just deploy to Vercel and then we will see the errors.
So in this case, there we go, we have some errors. Error occurred pre-rendering the page sign-in. So let's go inside of sign-in here and what we have to do is we have to export const dynamic force dynamic and we actually have to do this in every page.tsx which we call something in. So I also know that we're gonna have to do it here so we can immediately add it. So that's it for the ALF module.
Let's go ahead and run this again. I'm going to pause the video until we have some results. So the next error I have is the library. So let's go inside of the library page right here and I'm going to add this here and I immediately know that I'm going to have to do it here then as well so let's just add that there we go And I think that resolves the library entirely. So let's do bun run build again.
And I'm going to show you any errors that pop up. And it looks like I have no other errors. You can see that all of my routes have managed to load. So I just want to double check that. As you can see, I've had to modify four page files.
So sign in, sign up, library, and library product ID here. So I'm just curious why the other ones were not problematic. For example, inside of my app here, Home, I have Category. So in here, I'm pretty sure that this also should have this. So I will just preemptively add it here.
And also for the subcategory, basically everywhere where I use any kind of prefetching, I'm going to add it here. So I think that is it for the home and now let's go inside of tenants. So let's first go inside of the home here page. Same thing I'm going to check change this to be this. I think that the reason this doesn't cause any problems is because it recognizes this as a dynamic page because of the params.
I think that's why. But still, let's go and do it here in the page as well. I'm pretty sure it's because of the params. Yeah. So this actually doesn't change anything the fact that we are adding it.
And let's go inside of checkout here and in here we definitely don't need it because we don't prefetch anything So that this is fine. So in the end, I have eight modified files. All of them just have that export cons dynamic added. So you can basically try and do Bundler on build until you have a working result. I'm just going to try one more time since I've added some changes now.
Great. And now what I'm going to do is I'm going to commit these changes. So let's go ahead and do git checkout b28 deployment. Whoops, deployment. Let's do git add, git commit, 28 deployment, and git push u origin 28 deployment.
And now that we have pushed that branch, we can go to our GitHub and in here, let's create a pull request. Since we know every single change that we are going to have, we don't have to wait for our reviewer here. I will just merge this pull request. There we go. So now let's go ahead back to master and let's pull origin so we are up to date.
There we go. And now what we are going to do is we're going to go to Vercel.com. In Vercel.com go ahead and click Add New Project and in here I'm going to select my multi-tenant e-commerce project. Inside of here I'm going to open the environment variables. And I'm going to copy all of my variables inside.
So the database URI and payload secret, they can stay the same. Stripe secret key, stripe webhook secret, next public root domain and app URL will all have to be changed. But we're only going to do that after we deploy. So let's go ahead and hit deploy right here. Let's wait a second.
And... Oh, so in here it's trying to build, so I'm just going to pause and tell you the results. And here we go. You can see that I have now deployed my project. So I'm going to click continue to dashboard here.
And you can see that now I have my Vercel.app application here. And I just want to briefly try it. So What I'm going to try, for example, is logging in. Let's try that. So john at demo.com and demo here.
And there we go. So this, let's see if it works or not. So I'm going to check my network, because we modified those cookies, right? So I don't see the sign that I'm logged in. This is why I want to check this.
I want to see if we have perhaps done something wrong here. There does not seem to be any cookie here whatsoever. And I think that's because it's saving the cookie. If you go inside of Auth, generate Auth cookie, we are saving the cookie under the next public root domain. I think it's because of that.
So what I'm going to do is the following. In order for you to fix this, at least this is what I'm going to do now. So we are exploring in real time. I'm going to go ahead and get my URL. And I'm going to go ahead inside of my settings and then environment variables and in here I will find the next public app URL And I will replace it with my new app URL here.
And I will click Save. And I'm also going to change my next public root domain. So this is not really correct, right. So this is what I will do for now, but this cannot be like this, right? This has to be a actual, you know, shop.com domain.
It cannot be a sub domain on Vercel like this, but just for now, I want to leave it like this. And since we have this we can now also go to Stripe and inside of here We can modify our webhook now. So let's click on Developers, Webhooks, and let's click Add Destination, Events from your account here, and we want to look for Account Updated, and we want to look for checkout session completed those are the two events we look for so let's click continue this will be a webhook endpoint and our URL will be HTTPS, then the domain that you are on, and then slash API stripe webhooks. Like this. And click create destination.
And after that, you will have your new signing secret. And let me just... Yeah, make sure it's not trimmed out. This is very poorly made. I have to click copy here because otherwise it's trimmed.
So yeah, make sure you click copy. I hope that copied it. And then we can go here and change the stripe webhook secret. So I'm going to paste it. There we go.
So this is my new Stripe webhook secret. So I'm going to save this as well. So now I have new webhook secret, new public root domain, and new next public app URL. These three things can stay the same now. And once you've changed your environment variables, go to deployments, select the last one, and click redeploy.
And I'm just going to confirm. And I'm now going to look at the build and unpause the video when it's done. And here we go, I have successfully deployed again. Now I'm going to go click here or I can just open the app from here. And I will just carefully, you know, look at my network tab here, my application, I want to know what's going on in production with my cookies.
So again, I'm going to go inside of login and do john demo.com and demo. Let's click login. And let's see what happens. And now I can see the cookie. So the issue was that the domain, as you can see, was set on the next public root domain, Which in turn, before I updated my environment variables, was not correct.
So you can see that now, inside of here, I have the domain set to this. I have the path. I have the HTTP only. I have the secure. Same site set to none.
So basically everything that we wanted to set is set correctly here. So I'm gonna go inside of my dashboard here just to test if That is working correctly and I'm going to create a new product here. So let me just try that. Test product. $45.
Let's select business and money as the category here. And I will just click Save. There we go. I will now go back into, I almost said localhost, but now it's no longer called that. What I want to do now, there we go.
So we now have this first problem. The problem is that our URL, this one, from utils, from other utils, this one, has noticed that we are no longer in development, so it's using subdomain routing. The problem is, we haven't set up subdomain routing yet. Because of that issue, we cannot really test this out properly, except by manually modifying the URL. So I'm going to show you one way that we can disable subdomain routing with an environment key.
So what I'm going to do is I'm going to add next public enable subdomain routing. And this will be set to false, like this. And now what I'm going to do is go inside of this util right here. And I'm going to check for two things. So const is development will be if process.environment, node environment is equal to development.
And then const isSubdomainRoutingEnabled will be process.environment.nextPublicEnableSubdomainRouting like this. And we can, well, we can always count on this being some value. You can turn it into a Boolean if you want to, like this. There we go. And then we're going to check.
We will use normal routing either if we are in development or if not, is subdomain routing enabled. And I'm not sure if subdomain is one word. It is one word, so Pascal case is correct here. So in development or subdomain routing disabled mode, use normal routing like this. So unless we explicitly pass a variable which will set this to true, we are not going to use this type of routing right here.
So Depending on this, you can also now modify the auth cookie here. It could technically have the same site now, and the domain is not needed in this way. But I think it will still work regardless of this. So I think this is a good change, right? And let's do...
I'm not even going to test it. Maybe this will prove a bad idea. But let me just confirm. I'm just going to add 28 deployment fix so I'm not even gonna create a branch here I'm just going to push this change And the reason I'm going to push the change directly is that everything that gets pushed on the master branch is immediately a new build. So I'm just going to open this build, and I'm going to wait, and then I'm going to try the app again.
So while this successfully deployed, I actually noticed one mistake here. In isSubdomainRoutingEnabled, the way this has to work is by literally comparing it to the string true, like this. Because in here, it really doesn't matter what else you put. It will only be activated if it is set to true, but environment variables can only be strings. So that's the only way we can truly know that the user wants to enable subdomain routing, by writing true like this.
So I would highly recommend doing this change because it's the correct thing to do. So let me just confirm that this logic is fine. I think everything here makes sense. So I will just do another commit here. 28 deployment fix 2.
And direct git push without a new branch. So we save some time here. And this will cause another build here. So again, I'm going to show you the results after it builds. And here we go, another successful deployment.
And this time, hopefully, we will be able to click on this without subdomain routing. Let's click and hopefully no error and it's loading and it loaded. Amazing, amazing job! And I can click add to cart here and it should also completely allow us to purchase this. So let's go to the checkout and this time we don't need to have our webhook running because we changed the webhook secret and this time it should all be running on our deployed app.
So let me go ahead and click pay. And this definitely won't fail this part. But the question is, will our webhook do a proper job here. So this definitely seemed to be working. And let's go back to Fun Road here.
So something here seems off with this button. It should be redirecting me to the root page, but it does not seem to be doing that. But clicking on John seems to be doing that, or maybe it was just loading. I'm not sure which one it was. But okay, now I can go.
And now let's go inside of library here. Looks like no products found, which would mean that something here went wrong, which is completely okay. We're going to explore what happened. So we have the events here and we have logs here. So let's see what happened exactly.
So I think I debugged why we are not creating new orders. I think it's because our webhook never even gets reached and I think it has something to do with how I set up the new destination webhook here. So let's try this again. Click on developers and go to webhooks and this is basically the URL that we want it's this one but this one you can see it doesn't even fail so it never even fires so what I'm thinking is that I have to add a different kind of destination here so let me close this developers webhooks add the destination and this time select connected accounts And then let's do the same thing. So we are looking for account updated, And we are looking for checkout session completed.
Let's click Continue, Webhook endpoint. The URL is our Vercel app, dash API, I mean, slash API, stripe webhooks. And click create destination. So events from connected accounts. I think this is what we have to do.
Reveal the signing secret, copy the signing secret, go inside of your settings, environment variables, and modify the Stripe webhook secret. And yes, you're gonna have to redeploy again. I'm so sorry, but let's go and try this again. I'm going to go ahead and just redeploy my latest change, and then we're going to try the checkout again. So I just redeployed and I'm gonna try the checkout again, hopefully this time creating an order.
So I'm going to click pay here and I can monitor my logs here. So in here we might see after checkout purchase our webhooks should be hit but let's see. So it redirected back And let's see if we have any events here happening. We do have some things, but I still don't think I'm seeing the event I want. Looks like it did succeed, but after some time.
So I'm gonna go ahead and try this again now. So let me go... I'm not gonna try it again, I'm just gonna go here. Perhaps it's just something with connection? I don't know.
But let's see if our library, there we go, finally, I can now view the product and I can leave a rating. Great, perhaps it's just the MongoDB connection, an unlucky moment here, right? And maybe the webhook just needed some longer time to connect. But there we go, I can see the button view in library. Amazing, so our deployment officially now works.
If you want, you can test out some other things here, but I'm pretty satisfied with this. One thing that perhaps we can try is if the media here is working. So I'm going to go and add an image here to my tenant. Here we go and let's write test here. And the reason this went wrong is something that I thought might happen.
I think it's because we haven't added proper way to store our images. We are only using this media folder here. Right, so that's why I wanted to try this first. Don't worry, I will show you what you can do. And I think we can actually also do it very quickly.
But I'm going to leave that for the next chapter. As I said, I just want to deploy to our cell right now. So in this case, you can see I cannot save this. And that's because we haven't added proper storage here. But if you look at payload CMS and search in the docs for the storage adapters here, you can see that there are a lot of options from Vercel, S3, Azure, Google Cloud Storage, and even upload thing.
I think that maybe adding a Vercel blob storage might be the easiest thing. So perhaps we can try it here, but I would rather we do it in the next chapter where I also do the subdomain configuration. For now, we at least got the main parts of the app working, right? Everything is deployed, our webhooks are working, we had a little hiccup with connection, and we learned that we need to set the webhook to listen to connected accounts. And we've also added a very important environment variable which we're going to have to turn to true in production when we want to use subdomain routing.
Amazing, amazing job. So that's it for the 28th deployment chapter. And in the next one, we're going to go ahead and fix these last few issues that we have and configure a wildcard domain for subdomain routing. You