In this chapter, we're going to implement billing and the credit system into our project. In order to do that, we first have to enable billing in Clerk. We then have to create a pricing page. After we've done those two, we can start and add rate limiting or usage or credit system in our application. This will include adding some new models to Prisma schema and creating the util for rate limiting.
After that, we're going to have to create the usage component, which will show to the user how many credits they have and finally we're going to have to update some procedures to actually call this util for rate limiting to trigger credit spent. So let's start with enabling billing. So this is the first time I'm using a Clerk billing. It was announced recently, and the moment I heard it, I just knew it had to be an incredible developer experience. And I think that you will be shocked at how good it is, because we all know that Clerk's developer experience is immaculate.
They have completely solved the issue of complicated code. Everything regarding Clerk is super easy, super fast, and super simple to do. And billing is one of the most complicated parts of building the authentication, especially if we are doing it with Stripe. So you're going to be so impressed by the fact that we won't even need a webhook for this entire process. More so, we won't even have to build a single component besides our custom usage component, which actually has nothing to do with billing.
Let's go ahead and do that. You can find information about Clerk Billing in their documentation here. You can scroll and find Billing and in here you can select B2C. You can also do B2B but in this case it will be B2C SAS. The first thing we have to do is enable billing.
So we have to go to billing settings. This will redirect you to your project. So you click into configure and down here billing settings. Go ahead and click create a plan And the first thing we're going to do is we're going to create a free plan. So I'm going to go ahead and open this and in here you can set the name of the plan and you can set the slug like this.
So this is what we are going to use in our code base to check if the user is on that plan, right? So we're going to check if free underscore user is active. That means the user is currently on the free tier. And in here, make sure to check publicly available. This basically means that this will appear on the pricing table.
So you can create that, and then you can click add another user plan. And for example, call this pro, like this, and give it a monthly fee of $29. And if you're wondering, can I easily combine this into an annual discount? Yes, you can. Just enable annual discount and in here set it to something like 25.
So if they pay monthly, it's going to be $29 a month, but if they choose to pay annually we're going to reduce the price to $25 per month so you're going to get $300 instantly from them and in return they're going to have a bit of a cheaper plan. You can of course assign the price to whatever you want and click save. So right now in your subscription plans, whoops, right here you should have two subscription plans one free and one pro which is billed monthly or annually. So in here let me just go and click on the settings here and in here let's just click enable billing. There we go.
So now billing is enabled and in here you can choose your payment gateway. So if you want to you can add your own Stripe account but you can also choose Clerks payment getaway which is a zero conflict payment getaway it is ready to process and test payments immediately and this is amazing you're gonna see how simple this is so to recap go inside of configure go inside of billing settings and make sure that you click enable. Make sure that you have a message billing is enabled. After that, go ahead and create two subscription plans right here. And now let's go ahead and let's add a pricing table to our app.
So as always make sure that you are on your main branch. Make sure that you synchronize your changes and if you want to go inside of source control and confirm that the last change was adding authentication. What we have to do now is we have to implement the pricing page. So let's go inside of source, app, home, and let's create a new folder called pricing. Inside page.tsx.
Like this. Let's mark this as use client and then let's go ahead and let's import image from next image and let's import pricing table from clerk nextjs And let's go ahead and export this page. So I'm going to export it like this. And inside of here, for now, let's just do pricing table. Let's just do that and nothing more.
If you now go into your app, just make sure you have it running, and if you go to forward slash pricing, it will redirect you to the login page, so Let's just make sure to add that here. So forward slash pricing, like so. Now you should be able to go to the localhost 3000 pricing. There we go. We have a pricing table.
So we didn't have to code a single component. All we have to do is style it a little bit now. So let's go ahead and do that. So I'm gonna go back instead of here, and I'm going to add a class name, flex, flex column, maximum width of 3xl, mx-auto and full width. I will then add a section around our pricing table.
And I'm going to create a div inside of here with an image component. And then in here, I will add an h1 element, and then I'm going to add a paragraph. Now let's go ahead and style this. Starting with the section, which will have space y6, padding top of 16vh, onto Excel padding top of 48. Then on this div encapsulating the image, let's give it a class name of flex, flex column and items center.
For the image itself, give it a source logo SVG alt vibe with 50 and height 50 as well and give it a class name hidden md-block. Then in the h1 go ahead and add the text pricing and give this a class name text muted foreground text center text small and MD text base and now let's just go to the pricing table appearance and let's add elements here pricing table card and let's change this to use the border shadow none rounded large Just make sure you're putting the exclamation points here. And just like that, we have a pricing table that clearly reflects the two plans that we created in Clerk Dashboard. So now let's go ahead and let's modify the descriptions of these and let's show some features which will be active once we upgrade. So let's go inside of our clerk dashboard here, go inside of configure and in here subscription plans.
Select the free one and let's go ahead and give it a description for getting started like this and click Save. And then in here let's add a feature and let's go ahead and call this feature five monthly credits like that make sure it's publicly available and let's click create feature and let's click save and just by doing that and refreshing you will immediately see the new description reflected here and you will also see the new feature five monthly credits. And now if you want to do this is where you add even more features for example public projects something like that so for example we don't even have private or public projects. All projects are private in our case, but for example, here you can see how that would look like. And now let's go ahead and let's modify the other plan, which is the pro plan.
So go back here, back inside of our subscription plans, and select the pro plan. So this one can have the description of for more projects and usage. And then go inside of the features here. And let's go ahead and add a new feature called 100 credits per month, like this. Let's go ahead and let's add private projects like that.
Let's add custom domains. Basically, whatever you plan to extend this application with, you can add here or maybe some collaboration like three editors per project. Just think of a bunch of features you would add to your app. And let's do remove the vibe badge. Imagine that we would create some kind of feature that adds the vibe badge and click save.
And you can, of course, you know, drag and drop this however you like. I just wanted us to add a lot of features here simply because the pricing table looks better if you add more features here. And I absolutely love how this looks. So now that we have this finished, let me just go ahead and do one thing. I want to go inside of layout right here, and I want to modify the clerk provider and its appearance here.
And I want to add variables here, color primary, and I'm just going to set it to the light mode of our cloud theme, which is this. And when you save this, you can see that immediately it will pick up the theme that we are using throughout the project. And I just think this looks amazing. Now let's just go back to the pricing here. And let's enable dark mode if we need it.
So I'm going to import dark from clerk themes and I'm going to import use current theme. Make sure this is marked as use client. Go ahead and add this and then simply in the appearance go ahead and add base theme checking if the current theme is dark. Then use dark, otherwise it's undefined. And now this page will support dark mode as well.
And if you try and subscribe, you can see that you are redirected to login. So you don't have to immediately try and subscribe, simply because I want to demonstrate the entire upgrade process. You can see that when I login, by default, every user is in the free tier. You didn't even have to write the code for that. We automatically added this user to the free tier.
If you click subscribe here, you can see how nicely this looks. As I said, you don't have to do this now. If you can, fine, sure. But you're going to have to create a new account to test out our usage tryouts. So you can see how this looks.
I think it's just, you know, amazing. And one thing that I want to fix that we forgot about is when I scroll, I want this navbar to stop being transparent because it just looks weird. So let's quickly fix that by going inside of source, hooks, and let's create useScroll.ts like this. And inside of here, let's go ahead and do import use state use effect from react, export const use scroll. And let's add the threshold to be 10.
Define the state is scrolled and set is scrolled. Use state by default is going to be false. Call use effect with for now an empty dependency array. Like this. And inside, create a handle scroll arrow function, which we'll call setIsScrolled to be window.scroll.y which is above the threshold.
And then let's add a window.addEventListener here to listen for scroll and handle scroll. And then simply call handle scroll. And in the return method, call window remove event listener, scroll, handle, scroll. Just like that. And add the threshold inside.
And all you have to do is return isScrolled. There we go. So now that we have useScroll in our app, we can go back to the navbar inside of home module UI components navbar. And in here you can now easily get isScrolled, use isScrolled, useScrolled, my apologies, from hooks useScroll. And then make this a dynamic class name by wrapping it inside of curly brackets and adding the cn util so we have to import cn from lib utils I'm going to keep the static classes as the first argument and then I'm going to check if is scrolled Let's do back BG background and border border So now if you scroll ever so slightly you can see that the navbar starts to stop being transparent and a border appears.
Amazing! Now that we have this and now that we have the billing, let's go ahead and just check a couple of things. So now this upgrade button should take you to the pricing. If yours doesn't, make sure you check the project view here and make sure that you have a button. Let me just find it.
Here it is, button with a link redirecting to pricing like that. And now it's time to create the usage model. So in order to do that we're going to have to install a package called rate limiter flexible. So let me just close this and this, and let me do npm install rate limiter flexible, like this. Let me show you the version.
So I'm using 7.1.1, that's my version. Let me do npm run dev. And then in here, I'm gonna go ahead and do the following instead of Prisma schema, I'm going to create a new model called usage, right here at the bottom, model usage. Let's go ahead and give it a key, which will be a type of string and that's going to be the id and then a points which will be integer and finally expire which will be an optional date time So this will be my usage model. Now let's go ahead and let's do npx prisma migrate dev.
We don't need to clear our database because this is not really conflicting with any other models. We're just adding a new one. So I'm going to call this migration usage. Let's go ahead and add the name, usage, and there we go. Now that we have the new usage model here and the new migration ready.
Let's go ahead and let's implement the usage tracker. So this is what I'm going to do. I'm gonna go ahead and create a new lib that I'm going to call usage.ts and inside of here I'm gonna go ahead and add an import for the rate limiter so specifically it's going to be a rate limiter prisma right here and let's go ahead and do export async function get usage tracker like this and for now I'm just going to define const usage tracker to be new rate limiter prisma store client will be our Prisma from the database, like this. And tableName will be usage. So just make sure it matches exactly the model we named here.
And for the points, let's go ahead and by default, give everyone five points. And for the duration, let's go ahead and let's do 30 days. So 30 times 24 times 60 times 60. Now what I like to do is I like to do const three points, and let's go ahead and give everyone three points so you can replace this like so. Then let's do const duration to be 30 times 24 times 60 times 60.
So you can add a little comment, 30 days, for example. And now that we have this, let's just return the usage tracker. And now let's go ahead and let's create a function called consume credits. So export async function, consume credits. And in here, let's go ahead first.
And let's extract user ID to be a wait out from clerk next JS server like so and make sure to execute this if there is no user ID we can throw new error here user not authenticated that's the first thing And then let's go ahead and do const usageTracker to be awaitGetUsageTracker. Basically this function which we defined above. And then in here, const result to be awaitUsageTracker.consume passing the user ID and then how many points do we want to take from them. So for that I'm going to define cost generation cost, cost to be one. So let's go ahead and add that here.
So we're going to subtract one point from the user every time we consume credits. And then let's just return result. And then let's create the last function, export asynchronous function get usage status again extract user ID from a wait out if there is no user ID throw new error, user not authenticated. And then let's do const usageTracker here to be await getUsageTracker. And then result will be await usageTracker.getUserID.
So we are looking at how many points we have left. There we go. So we are basically using this very, very cool library, which can inject directly into Prisma. And I'm just going to open the documentation now for it so you can read more. So here it is, Node Rate Limiter Flexible.
Basically, Node Limiter flexible counts and limits the number of actions by key and protects from DDOs and brute force attacks at any scale. It works with all key Redis, Prisma, Dynamo, Process, Memory, Cluster, PM2, Memcached, Mongo, MySQL, SQLite, and Postgres. Also works in the browser. It offers atomic increments. All operations are in memory or distributed environment use atomic increments against race conditions.
So if that's something you were wondering about, yes, we solve the problem of race conditions by using this package. It is extremely fast, it is flexible, ready for growth, and it is friendly. Now, should it be used exactly the way I'm using it? I'm using it as a simple rate limiting for premium credits. I haven't really seen any advice not to do it, but since it solves a bunch of problems out of the box and it's just an NPM package, I thought it was a no brainer to use it, given the fact that we can easily add it to Prisma, right?
So that's why I chose this package. I explored a bit what we should use, should we develop our own, and this ended up being the best decision. Great, so now that we have these three functions, a function to get the usage status by the current user ID key, a function to consume credits for the current user, and the overall function to get the usage tracker, which right now doesn't make too much sense. This could have been a constant, but don't worry, it will make sense later. So now let's go ahead and let's actually create the procedure for the rate limiting here.
So I'm going to go ahead and go inside of source. I will create a new module called usage. And in here, I'm going to create server. And then I'm going to create procedures.ts. Let's go ahead and do get usage status from lib usage.
Let's import create TRPC router from TRPC init and protected procedure. Then let's go ahead and export const usage router to be create TRPC router status is going to be protected procedure, query, asynchronous method, and then in here, let's open a try and catch block, return null in the catch block, and In the try, attempt to get the result from await getUsageStatus and return the result. As simple as that. So we don't really worry about catching these errors and displaying something since This is a query, right? So once you've done this, go ahead and add that to your TRPC routers here.
So usage, usage router. There we go. And yes, if you want to, you can move everything usage-related into this module. Perhaps you can move it out of the usage. For now, I will leave it here.
But yeah, if you want to, you can create a lib here. I think it will make more sense, actually. OK, now that we have this, let's go ahead and let's create the usage component. So this one will be interesting. Let's go inside of source, modules, projects, UI, components, and let's create usage.tsx.
So in here, I want to create an interface props which accepts the points and milliseconds before next refresh. And for the imports, let's go ahead and let's import link from next link. Let's go ahead and let's import the crown icon from Lucid React. And let's import format duration and interval to duration from date FNS. And finally, the button from components UI button.
Now in here let's go ahead and let's add the usage like so. Let's return a div with a class name rounded top extra large bg background border border bottom background, border, border, bottom, 0, adding 2.5. Another div inside with a class name, flex, items, center, and gap x of 2. In here, a div, which will have one more div inside, and this inner div will have a class name of text small. And let's go ahead and simply render the number of points that we have, and then let's just say you have that many free credits remaining.
And you can change this into a paragraph so we don't use so many divs. And then after that, add another paragraph with a class name of TextExtraSmall and TextMutedForeground and inside resets in then add a space like this open curly brackets format, duration inside of it interval to duration and set the start to be new date, and set the end to be new date, and inside date.now plus milliseconds before next. And then add a new prop here, I mean a new param in this interval to duration, my apologies, format duration function, which takes the format to be months, days, and hours. So it's going to display in those intervals. And I think that's it.
I think that's all we need. And then outside of this div right here, go ahead and add a button and a link inside. The link will have an href to the pricing page. We're going to render a crown icon and text upgrade. The button will have an as child, size small, variant will be the new one that we created, tertiary, I guess, class name ML Auto.
Now that we have this, let's go ahead and display the usage prop. In order to display it, we have to go inside of our messages form component. So it is inside of projects UI components message form. And then let's go ahead above this and let's do show usage and end and then render the usage like so. Import the users from .slash usage, passing the points to be 0, and milliseconds before next to be 0.
Just make sure you have imported the usage component. So now, go into any random project that you have. So I'm gonna go ahead and go inside of this one that I already have. And once this loads, nothing changes. But if I go inside of the message form and if I change the show usage to true and if I refresh you will see zero free credits remaining resets in nothing and we have a button to upgrade that's what I wanted to see And now what we're going to do is we're actually going to fetch the usage from our new router.
So let's go ahead to the top here and before the form let's do const data usage to be useQuery which you can import from let me just find 10 stack react query. Here it is. And in here past the RPC usage status, like this query options. And once you have the usage, let's go ahead and define the show usage to be double exclamation point and then usage and then in here you're going to do if you pass the points to be usage remaining points and in here usage milliseconds before next and now let's refresh And it looks like it does not exist yet. I think that is because, yes, so it's not going to exist right now, because in order for this to be written to the database, let me just start NPX Prisma Studio so you can see what I'm talking about.
We have this new model called usage. Right now, we have the fields, key, points, and expire, but nothing exists here. It will not be created by itself. It will be created after the very first consume credits function is called. So the first time we do dot consume and take some points, that's when it's going to be stored in the database.
So let's go ahead and let's do that. So the first one we can do it for is the messages procedures. So let's consider messages server procedures and in the create here let's go ahead and do that. So before we even create the message here, Let's go ahead and let's do a wait and let's call consume credits like so. And now this will already work but I want to do I want to just wrap this into try and catch because get usage usage dot consume will have an error object right because there is an error that we have to catch and that is the error which says you have no more points.
So we have to catch that here. So let's do it by wrapping this inside of try, like so, and then open catch, And let's get the error. And the first thing we're going to do is we're going to check if error is actually an instance of error. This basically means that something else happened, right? This doesn't mean that we hit the rate limit.
This just means something literally failed. Maybe it's the database connection, right? Because this works by connecting to the database. So maybe that failed. So it would be incorrect to just throw a TRPC error saying rate limit exceeded if consume credits fail.
That's why in here, I will throw new ERPC error here with the code bad request and a message something went wrong. Right, So I have no idea what happened here, but it's not something we expect. Otherwise, it is. So if it is not an instance of error, that means this is the rate limit response. So in here, add a code to many requests and add a message.
Let's see, you have no more, or maybe you have run out of credits. Something like that. Basically, a message indicating to the user that they have no more points. And now, just for fun, I'm going to modify my usage here, and I'm going to set two free points. So let's go ahead and try it out now.
I'm going to do build a landing page, something that reliably works for me. And we should have done one thing here immediately. Oh yes, we forgot the ingest API. We forgot to do that. Npx ingest-cli.
Whoops, my bad. And let me just refresh this and you can see that now when you refresh, you have one free credit remaining which resets in 29 days and 23 hours. Do I have my Prisma Studio running? I do. So if I go here now in the usage and reset, once we call this consume method, you can see that I have a key which is the user ID with some prefix here.
And you can see when this will expire and I can also see how many points I have spent so far. So I only spent one point so far. And basically that is how this is going to work. So just for fun, I will do build a landing page again. And this time, I will refresh and I will have no free credits remaining.
So if I try one more time, I should get the error, you have run out of credits and we just got that error. Amazing, you successfully implemented usage. Now you probably noticed a little bit of a weird thing here, and that is that we call consume credits before we even know that this succeeded. So if you want to, you could move this consume credits function into the background job, and then only consume the credit after you successfully save the result to the database. It will depend on what you want to protect.
If you want to protect your resources, you will most likely add this before you even call something like ingest.send. You don't even want to spend any OpenAI credits if someone doesn't have enough credits. But if you were to pass this in the background job, you would also need to pass the user ID in the event data. So just be mindful of that. And then you would also have to modify the consume credits overall, because in here we rely on it using ALF, and I'm not sure how this will work if it is invoked from a background job.
I just think that it will throw user not authenticated because background jobs by default are not authenticated. They are like webhooks, right? So that's why I decided to do it in the procedure rather than in the background job. Now what we have to do is this to do right here. So let's remove this.
Let's add query client dot invalidate queries, the RPC usage status query options like this. So now when we create a new message, we automatically invalidate the queries. And one easy way to reset this is to just go inside of your Prisma Studio and just bring back the points for your user to be zero and click save. And this way you will not have spent any points so you are now back at three credits remaining so if I go ahead and do test and send the message now it should automatically upgrade and there we go you can see now it says one so that is thanks to this invalidation here And now we can also fix this to do here as well. So if error.code error.data?code is equal to too many requests, let's go ahead and do router.
We don't have router so let's add it const router use router from next navigation make sure you add this import and just do router dot push forward slash pricing like that so now when you hit too many requests it will and you can see this is kind of the not perfect thing if you spend your credit on a bad query we take the credit away from you and you don't get the result so yeah not exactly perfect but I think it's pretty good so far, right? Let's go ahead and just, I purposely am just going to use stupid queries now just to get that error. There we go. So once I run out of credits, I am redirected to the pricing page. Perfect.
Now there is one more place where we need to do this exact thing. So I'm going to go inside of messages procedures just so I can copy the try and catch for my consume credits here. And now let's go ahead and go inside of projects, server procedures. Procedures right here. And find the create right here.
And simply call that try catch before you create a new product. And import consume credits like this and then go inside of project form component And we have to do the same thing. So first things first, query client invalidate queries and pass in the RPC usage status query options. And then in here, if error data code is too many requests do router dot push forward slash pricing there we go so now you have the exact same thing happening from here So if you try test from here, same thing happens. You have run out of credits and you are redirected here.
Amazing! But right now, if we were to upgrade, nothing would change. So let's go ahead and fix that. So in order to fix that, we have to go inside of our usage in the lib here. And then what we have to do is we have to get inside of here the status.
So has, and let's do await out. Const hasPremiumAccess will be has, plan, and then pro. So how do I know it's pro? Well because inside of the clerk configuration here the slug is pro. So maybe has pro axis would be better.
And then what I'm going to do is I'm just going to add const pro points 100, like this. And then if I have has pro access, it's going to be row points, otherwise it's going to be three points like that. And here's a quick tip. If you also want to change the duration, which I wouldn't recommend, you know, there's also, If you look at all of these apps, ChatGPT, Claude, Lovable, Bolt, Repl.it, I've noticed that not all of them have annual plans. And the reason for that is it is safer for them to bill you monthly simply because they don't know how many credits you can spend.
So that's why I recommend not changing the duration for the pro access. But even if you wanted to, the way this rate limiter works is that it will not update the duration. Right? So you can update the points in the middle of an existing database record for rate limit, but you cannot do it for expiration. Just in case you were interested, But in this case, it doesn't really matter, because it is safer for us business-wise to track monthly usage and do monthly billing.
Even if a user is on an annual plan, we're just going to give them the same amount of points, 100 points per month. Great. Now that we have this done, let me just check, I think this is the only place here where I have to do that. And now, let's just do a comparison. So when I click on one of my projects, it says zero free credits remaining.
I will click upgrade, I will click subscribe, pay with test card. That's it. That was clerk billing. I don't know if you just saw that, but that was it. I can now go inside of my manage account, billing, and I can find that I am on this plan.
And from here, I can see cancel subscription, I can switch, I can remove monthly, whatever I want. So I think this is insanely good. And let's see if it worked. So right now, I think that... There we go.
I have to refresh, right? And then it says 96 free credits remaining. So we have officially upgraded, right? I can now send another broken message. And it works.
So we successfully added a hundred points. It seems like it has subtracted the existing points we spent during the free trial. So that's something we could improve, but overall it works when the user is pro, we use a larger amount of points here. So now what we have to do is we have to change the text. This is no longer free credits, this is just credits now.
And we can also remove all of the upgrade buttons. We no longer need them. So let's do that. I'm going to go inside of the usage.tsx here. And let's see.
So this is from Auth, which means that in here, we can access has from useAuth from clerk-next.js. I have has here, so I'm going to change. Let's go ahead and do on is as pro access as plan row as question mark plan pro. So let's check if it has ProAccess, then it's an empty string, otherwise it is free. So now it should just say 95 credits remaining, no free credits.
And let's hide this button if I don't have pro access. So only show this for users who don't have pro access. There we go. And let's do the same thing in the project view. So I'm just going to copy this go inside of the project view.
I'm going to add it here. I'm going to import use out from clerk next j s. I'm going to move it here. And then if I don't have pro-axis, I'm going to show this button right here. So if I don't have row access, only then show the button.
And there we go, now the button doesn't exist. If you want to use the reverse logic, if you want to create const is free tier, then you would do has plan and be careful here, it's not free, right? You always have to go inside of here, inside of your plans, select the plan you want, and then check the slot. It's free user. This is the one you want.
That's the mistake I made when I developed, so I'm just warning you. But in here we used this type of logic, so it's fine. And I think that that might be it regarding billing. It was that simple to do. I'm super impressed by this.
No webhooks, nothing. I mean, 90% of this chapter wasn't even adding billing. It was adding usage, rate limiting, right? So amazing, amazing job. I am super satisfied by this.
So let's go ahead and merge all of this. I believe this chapter is called 17 Billing and let's just mark things. So we enabled billing, created pricing page, added rate limiting, updated the Prisma schema, created the util, we created the usage component, and we updated procedures to trigger credit spend. Yeah, one more thing I wanted to show you. If you want to, you can also implement something like usage procedure.
And then in the middleware, you could check for the consume status maybe that would be something fun for you to try and then you would have a more abstracted routers and procedures to work with Maybe homework for you if you want to after you finish the project. Okay, so I'm going to go ahead and I will create a new branch here. 17 billing like this. I'm going to stage all of my changes. I'm going to add 17th billing commit here, and I'm going to publish the branch.
Just a quick reminder, there's a CodeRabbit free extension, which you can use, and it will review all of your files for you. Now let's go ahead and let's open a pull request here. And let's see the summary of our billing changes. And here we have the summary. We introduced a usage and credit tracking system for users with separate limits for free and pro plans.
We added a new pricing page with dynamic theming and a detailed pricing table. We added a usage component to display remaining credits and reset time with an upgrade prompt for non-pro users. NavBar now dynamically changes style based on the scroll position. As per the enhancements, Project and Message Creation now deducts credits and prevents actions if credits are exhausted, redirecting users to the pricing page when necessary. Usage status is now displayed and updated in relevant forms and components.
The upgrade button is only shown to users without a pro plan. Perfect! So that's exactly what we did. As always, a more in-depth walkthrough here. And we have a sequence diagram explaining exactly what happens right so when user tries to submit a and create a new project or a message we call the mutation in here we call the consume credits and in here we call the database to check and update the usage and then if we have credits available we return with success and we proceed with the creation and then we simply return the creation results but if credits are exhausted we throw too many requests and we redirect the user to pricing.
Amazing! Exactly what we developed and in here we also have the diagram for our get usage status method which simply reads the usage and it returns it. Perfect! So in here we have some actionable comments. This one recommends adding a default false in case has doesn't load, which is actually a good advice, we could do that.
In here it recommends wrapping this instead of try and catch and fallbacks to soon. So this can happen if the dates are incorrect. And yeah, This might be a good idea because it's kind of weird that the entire page fails just because the date renders incorrectly. So we could actually do this in the next chapter so we ensure some kind of security here so it doesn't ruin the entire experience. And then in the usage.ts for all of the functions it recommends adding error tracking but we don't have to do that simply because we track in the TRPC.
So I'm going to merge this pull request, I'm going to keep in mind the changes it suggested and then I'm going to change back to my main branch here and I'm going to click on the synchronize changes button and okay and then I will confirm that we just merged that right here 17 billing. Perfect! Amazing, amazing job! We have finished billing and see you in the next chapter.