Cascade uses Lemon Squeezy as the merchant of record. Lemon Squeezy is a payment gateway that allows you to accept payments from your customers. It is a secure and reliable payment gateway that supports multiple payment methods. It also handles all tax related things for you.
Setup on Lemon Squeezy side
Make sure you are doing all of the below in test mode. You can switch between
test and live in the Lemon Squeezy dashboard.
Next step is to create some test products. You can do that here.Let’s start with a simple product. You can create a product by clicking on the New Product button.Choose Subscription and select $9.99 as the price for collection every month.
Now let’s creat two variants of this Product, we will call it Yearly & Monthly and set the price to $9 & $100 respectively.
Save your product and variants, you should have deftault monthly subscription and yearly subscription now!Go to stores page and copy the store ID.
Go to api keys page and create an API key. Copy it as well.
Name your API key corresponding to your store so you could rotate it later if needed.
Setup on Cascade side
Now that you have your store ID and API key, you can set up Cascade to use Lemon Squeezy as the payment provider.Inside of .env file add the following:
We are using local tunnel for webhook URL, you should replace cascade with
your app name and generate correct connection in the next step.
Visit the Lemon Squeezy setup page on Cascade dashboard at http://localhost:3000/ls-setup
Make sure you are signed in and your user has SUPER_ADMIN role.
Run npx localtunnel --port 3000 --subdomain cascade with replacing cascade with your domain. This will make sure we are able to receive webhooks from Lemon Squeezy locally.You can now click two buttons to create a webhook and create plans in our database that correspond to Lemon Squeezy subsriptions.
Create webhook button will create a webhook on Lemon Squeezy side, so we can receive events. This is just a nice utility to setup webhooks without going to Lemon Squeezy dashboard.
Sync plans button will create plans in our database that correspond to Lemon Squeezy subscriptions. This is needed so we can match Lemon Squeezy events to our plans.
Working with payment utilities
To make sure we incentivise our users to subscribe to paid plans we sometimes need to block them from using our app. We can do this by using payment utilities.useGuardedSpendCredits hook will check if the user has enough credits to spend on the given feature. You need to ensure that you Prisma schema has a field for each feature you want to block.
For example, if you want to block button clicks(a basic example exists here), you need to add a buttonClicks field to your Plan schema & reflect it in your FeatureUsage schema.
When you create plans automatically with syncPlansFromLemonsqueezyVariants
using this guide you need to
manually input the limits for the features in your Database.
model Plan { id Int @id @default(autoincrement()) lemonSqueezyVariantId String @unique name String // Paywalled features, this is the number of credits the user can spend on each feature per month buttonClicks Int? aiCalls Int? fileUploads Int? users User[] // This establishes the one-to-many relationship}
To properly track feature usage you need to use a FeatureUsage model in database. This model will be used to track the usage of each feature for each user. Extent it when needed.
model FeatureUsage { id String @id @default(cuid()) userId String buttonClicks Int @default(0) aiCalls Int @default(0) fileUploads Int @default(0) // Add more features as needed date DateTime @default(now()) user User @relation(fields: [userId], references: [id]) @@unique([userId, date])}
It is really easy to paywall any feature you want and show a dialog to the user to upgrade their plan.
{"docsConfig":{"$schema":"https://mintlify.com/docs.json","theme":"mint","name":"Starter Kit","colors":{"primary":"#757575","light":"#BDBDBD","dark":"#494949"},"favicon":"https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/favicon.svg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=bafb0e0585f96ef45791b8d86b5694e5","logo":{"light":"https://mintcdn.com/stackonfire/ga2IkdDnfRqvsygD/logo/light.svg?fit=max\u0026auto=format\u0026n=ga2IkdDnfRqvsygD\u0026q=85\u0026s=848a8e28c110a7c328693f6e504b607c","dark":"https://mintcdn.com/stackonfire/ga2IkdDnfRqvsygD/logo/dark.svg?fit=max\u0026auto=format\u0026n=ga2IkdDnfRqvsygD\u0026q=85\u0026s=e4e6073c75b000deb9be973fa9231fbb"},"navbar":{"links":[{"label":"Support","href":"mailto:dima@stackonfire.com"}],"primary":{"type":"button","label":"Demo Application","href":"https://cascade.stackonfire.com"}},"footer":{"socials":{"twitter":"https://twitter.com/divdev_","github":"https://github.com/d-ivashchuk/cascade"}},"styling":{"latex":true},"navigation":{"global":{"anchors":[{"anchor":"Demo","href":"https://cascade.stackonfire.com","icon":"laptop"},{"anchor":"Code on Github","href":"https://github.com/d-ivashchuk/cascade","icon":"github"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"stackonfire","hasAudioNarration":false,"actualSubdomain":"stackonfire","customDomains":[],"gitSource":{"type":"github","owner":"d-ivashchuk","repo":"cascade","deployBranch":"main","contentDirectory":"docs","isPrivate":false,"mountPath":"","label":""},"entitlements":{},"buildId":"6ae91f97e285e7410aaeac15:success","clientVersion":"0.0.4131","searchFilterCounts":[{"language":"default","tag":"Documentation","count":14},{"language":"default","tag":"Essentials","count":7},{"language":"default","tag":"Marketing","count":3},{"language":"default","tag":"Examples","count":2},{"language":"default","tag":"Get Started","count":2}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"essentials/payments","slug":"/essentials/payments","pageMetadata":{"title":"Payments","description":"How Cascade handles payments and billing.","icon":"lemon","href":"/essentials/payments"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"How Cascade handles payments and billing.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Frame,Heading,OptimizedImage,Tip,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Frame)_missingMdxReference(`Frame`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`payment-provider-of-choice`,children:`Payment provider of choice`}),`\n`,_jsxs(_components.p,{children:[`Cascade uses `,_jsx(_components.a,{href:`https://lemonsqueezy.com`,children:`Lemon Squeezy`}),` as the merchant of record. Lemon Squeezy is a payment gateway that allows you to accept payments from your customers. It is a secure and reliable payment gateway that supports multiple payment methods. It also handles all tax related things for you.`]}),`\n`,_jsx(Heading,{level:`2`,id:`setup-on-lemon-squeezy-side`,children:`Setup on Lemon Squeezy side`}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`Make sure you are doing all of the below in test mode. You can switch between\ntest and live in the Lemon Squeezy dashboard.`})}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=81a5d5953ec5f6099ec4be6a0cdba4ba`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4528`,width:`4528`,\"data-og-height\":`3696`,height:`3696`,\"data-path\":`images/ls-new-store.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=f0227c6745c4055caf5a2ad946ca9f62 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=041c9ccf9859a31bbf79d2ff2052e1ae 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=d86d297919d27f323f4c8afa7aa745a6 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=36658cb8112901f12fdece3cb6c47eff 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=6640ddf3a896a5d8673a2d792e87195e 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-new-store.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=094840f768bb356c89a15fde9d88e818 2500w`})}),`\n`,_jsxs(_components.p,{children:[`To start accepting even test payments, you need to `,_jsx(_components.a,{href:`https://app.lemonsqueezy.com/settings/store/new`,children:`set up a new store`}),`.`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=3f12f9dd3be58b245f5b3e710eb6faf8`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4436`,width:`4436`,\"data-og-height\":`3532`,height:`3532`,\"data-path\":`images/ls-test.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=8561e18bd6d59310ae032cdcf9caff41 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=86d22e52b206cda4fb1509a921b8429f 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=e95020f4ad7e4cc5a7cec090f235c686 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=0e8ee22816b032c5d55bfdc2a32026cd 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=6d9d87b2a0d639186471b6ccc2f993c7 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-test.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=4f1e9272e9d2545e3a953a05272e3a38 2500w`})}),`\n`,_jsxs(_components.p,{children:[`Next step is to create some test products. You can do that `,_jsx(_components.a,{href:`https://app.lemonsqueezy.com/products`,children:`here`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Let’s start with a simple product. You can create a product by clicking on the `,_jsx(_components.code,{children:`New Product`}),` button.`]}),`\n`,_jsx(_components.p,{children:`Choose Subscription and select $9.99 as the price for collection every month.`}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=322f4ca72ecc278a0409b1613ed053a7`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4528`,width:`4528`,\"data-og-height\":`4532`,height:`4532`,\"data-path\":`images/ls-month-sub.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=2ffb8dadcdb1cfcc43e42b0ad3e6a472 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=e054815a5b26a1281764ea0a8736c4f7 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=3d988dcc1bfadd1f3b35f814f997d553 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=44265cd9dbc9b31056e5eff8aa0328c3 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=39c139d277f65d337ed23cb92c284573 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-month-sub.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=99a861800a57941b0bbd78e2725aafc3 2500w`})}),`\n`,_jsxs(_components.p,{children:[`Now let’s creat two variants of this Product, we will call it `,_jsx(_components.code,{children:`Yearly`}),` \u0026 `,_jsx(_components.code,{children:`Monthly`}),` and set the price to `,`$9 \u0026 $`,`100 respectively.`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=b88fcd39a058990b6a5c715e40b95513`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4528`,width:`4528`,\"data-og-height\":`4532`,height:`4532`,\"data-path\":`images/ls-variant.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=7c8b91a31d6bf36b51884f9b0d6ab3f7 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=3536851e2904e5235ddc738cec6322e3 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=5589e8211ab1c37553b2820cee8d317d 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=c2a501a0df7ecf1793405359ccfd7a53 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=eda059d2a7a6d0157f43cdaa0197c6e0 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=ef2ba9c7e6ee5b388794d5f93417fe22 2500w`})}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=5aa3054ca4b5a6b7899d7efbfa8e419f`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4528`,width:`4528`,\"data-og-height\":`4532`,height:`4532`,\"data-path\":`images/ls-variant-yearly.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=bd59a08618ed604f21ac0e167607fff6 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=c6426ecf187878362c6d9481cf25989e 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=5013f59c8594049580823c42b595b27b 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=e5132a1a883bb940d9d5e64f69a2f8e3 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=b054f89e7863f62fa6f81b8e706cde8e 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-variant-yearly.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=b24bd2691aded19543407565397d91c6 2500w`})}),`\n`,_jsx(_components.p,{children:`Save your product and variants, you should have deftault monthly subscription and yearly subscription now!`}),`\n`,_jsxs(_components.p,{children:[`Go to `,_jsx(_components.a,{href:`https://app.lemonsqueezy.com/settings/stores`,children:`stores page`}),` and copy the store ID.`]}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=700f1e5bb4cd79d58b350c31763cdad4`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4528`,width:`4528`,\"data-og-height\":`2488`,height:`2488`,\"data-path\":`images/ls-stores.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=ed7115e421c8ff3052bdc0f2f235c116 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=4aa4dda053d1e46257cc2ebe64fad541 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=c82000d089e3a84bd3243714a66df67d 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=0e789c9b5ef375cabe170486bade631f 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=a53c09ba2b72f8affc032e813786069b 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-stores.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=158f9fa28399e657e3ab19850da6a078 2500w`})}),`\n`,_jsxs(_components.p,{children:[`Go to `,_jsx(_components.a,{href:`https://app.lemonsqueezy.com/settings/api`,children:`api keys page`}),` and create an API key. Copy it as well.`]}),`\n`,_jsx(Tip,{children:_jsx(_components.p,{children:`Name your API key corresponding to your store so you could rotate it later if needed.`})}),`\n`,_jsx(Heading,{level:`2`,id:`setup-on-cascade-side`,children:`Setup on Cascade side`}),`\n`,_jsx(_components.p,{children:`Now that you have your store ID and API key, you can set up Cascade to use Lemon Squeezy as the payment provider.`}),`\n`,_jsxs(_components.p,{children:[`Inside of `,_jsx(_components.code,{children:`.env`}),` file add the following:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`5`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`#Lemon Squeezy`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`LEMON_SQUEEZY_API_KEY=\"COPY_YOUR_API_KEY_HERE\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`LEMON_SQUEEZY_STORE_ID=\"COPY_YOUR_STORE_ID_HERE\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`LEMON_SQUEEZY_WEBHOOK_SECRET=\"super-secret-long-string\"`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`LEMON_SQUEEZY_WEBHOOK_URL=\"https://cascade.loca.lt/api/lemon-squeezy/webhook\"`})}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`We are using local tunnel for webhook URL, you should replace cascade with\nyour app name and generate correct connection in the next step.`})}),`\n`,_jsxs(_components.p,{children:[`Visit the Lemon Squeezy setup page on Cascade dashboard at `,_jsx(_components.code,{children:`http://localhost:3000/ls-setup`})]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`Make sure you are signed in and your user has `,_jsx(_components.code,{children:`SUPER_ADMIN`}),` role.`]})}),`\n`,_jsx(Frame,{children:_jsx(OptimizedImage,{src:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=622780b584598cb2ac220cadbb1579cd`,style:{borderRadius:`0.5rem`},\"data-og-width\":`4528`,width:`4528`,\"data-og-height\":`4532`,height:`4532`,\"data-path\":`images/ls-setup-dashboard.jpeg`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?w=280\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=d2e516116f2c3f46ae12647338afbefa 280w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?w=560\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=85dfcf20a97574ca2bbdf69bbd95af1a 560w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?w=840\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=2d834832b59cc6e7d2f8fa3bb3db15cd 840w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?w=1100\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=3ffc1e1e28aa6c363cbfde3cf8813665 1100w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?w=1650\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=18dfe49b226cf2fc856548202e6e4dcf 1650w, https://mintcdn.com/stackonfire/yjAbpf2Gzt4acEMi/images/ls-setup-dashboard.jpeg?w=2500\u0026fit=max\u0026auto=format\u0026n=yjAbpf2Gzt4acEMi\u0026q=85\u0026s=f58e37a653a200d9e436f0de36cfe90f 2500w`})}),`\n`,_jsxs(_components.p,{children:[`Run `,_jsx(_components.code,{children:`npx localtunnel --port 3000 --subdomain cascade`}),` with replacing cascade with your domain. This will make sure we are able to receive webhooks from Lemon Squeezy locally.`]}),`\n`,_jsx(_components.p,{children:`You can now click two buttons to create a webhook and create plans in our database that correspond to Lemon Squeezy subsriptions.`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`Create webhook`}),` button will create a webhook on Lemon Squeezy side, so we can receive events. This is just a nice utility to setup webhooks without going to Lemon Squeezy dashboard.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`Sync plans`}),` button will create plans in our database that correspond to Lemon Squeezy subscriptions. This is needed so we can match Lemon Squeezy events to our plans.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`working-with-payment-utilities`,children:`Working with payment utilities`}),`\n`,_jsx(_components.p,{children:`To make sure we incentivise our users to subscribe to paid plans we sometimes need to block them from using our app. We can do this by using payment utilities.`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`useGuardedSpendCredits`}),` hook will check if the user has enough credits to spend on the given feature. You need to ensure that you Prisma schema has a field for each feature you want to block.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`1`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`1`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` guardedUsage`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` useGuardedSpendCredits`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"buttonClicks\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`Guarded usage retuns an object with useful fields for working with paywalled features:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` guardAndSpendCredits`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` showUpgradeDialog`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` setShowUpgradeDialog`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:` isPending`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`spendCreditsMutation`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:`isPending`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` hasRunOutOfCredits`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` featureCreditsLeft`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` availableCredits`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` } `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` useGuardedSpendCredits`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"buttonClicks\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`);`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`For example, if you want to block button clicks(a basic example exists `,_jsx(_components.a,{href:`https://cascade.stackonfire.com/app/usage`,children:`here`}),`), you need to add a `,_jsx(_components.code,{children:`buttonClicks`}),` field to your `,_jsx(_components.code,{children:`Plan`}),` schema \u0026 reflect it in your `,_jsx(_components.code,{children:`FeatureUsage`}),` schema.`]}),`\n`,_jsx(Tip,{children:_jsxs(_components.p,{children:[`When you create plans automatically with `,_jsx(_components.code,{children:`syncPlansFromLemonsqueezyVariants`}),`\nusing `,_jsx(_components.a,{href:`/essentials/payments#setup-on-cascade-side`,children:`this guide`}),` you need to\nmanually input the limits for the features in your Database.`]})}),`\n`,_jsx(CodeBlock,{numberOfLines:`14`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`14`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`model Plan {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` id Int @id @default(autoincrement())`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` lemonSqueezyVariantId String @unique`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` name String`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` // Paywalled features, this is the number of credits the user can spend on each feature per month`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` buttonClicks Int?`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` aiCalls Int?`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` fileUploads Int?`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` users User[] // This establishes the one-to-many relationship`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`}`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`To properly track feature usage you need to use a `,_jsx(_components.code,{children:`FeatureUsage`}),` model in database. This model will be used to track the usage of each feature for each user. Extent it when needed.`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`14`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`14`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`model FeatureUsage {`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` id String @id @default(cuid())`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` userId String`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` buttonClicks Int @default(0)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` aiCalls Int @default(0)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` fileUploads Int @default(0)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` // Add more features as needed`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` date DateTime @default(now())`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` user User @relation(fields: [userId], references: [id])`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` @@unique([userId, date])`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`}`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(_components.p,{children:`It is really easy to paywall any feature you want and show a dialog to the user to upgrade their plan.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`17`,language:`typescript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`typescript`,children:_jsxs(_components.code,{language:`typescript`,numberOfLines:`17`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c>`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Button`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` onClick`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{() => guardedUsage.guardAndSpendCredits(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`10`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`)`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` disabled`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{guardedUsage.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`isPending`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` >`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`guardedUsage`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`isPending`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u0026\u0026`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Loader2`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` className`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"mr-2 h-4 w-4 animate-spin\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` />`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` )}`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`guardedUsage`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`hasRunOutOfCredits`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ?`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Upgrade to spend 10 credits\"`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` :`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"Spend 10 credits\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c/`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`Button`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`>`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`UpgradeDialog`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` open`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{guardedUsage.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`showUpgradeDialog`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` setOpen`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{guardedUsage.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`setShowUpgradeDialog`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` />`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u003c/>`})}),`\n`]})})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Payments","description":"How Cascade handles payments and billing.","icon":"lemon","href":"/essentials/payments"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Payment provider of choice","slug":"payment-provider-of-choice","depth":2,"children":[]},{"title":"Setup on Lemon Squeezy side","slug":"setup-on-lemon-squeezy-side","depth":2,"children":[]},{"title":"Setup on Cascade side","slug":"setup-on-cascade-side","depth":2,"children":[]},{"title":"Working with payment utilities","slug":"working-with-payment-utilities","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"stackonfire","siteName":"Starter Kit","title":"Payments - Starter Kit","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-01-07T01:46:28.667Z","originalFileLocation":"essentials/payments.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"How Cascade handles payments and billing.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Starter Kit\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Payments - Starter Kit\">\u003cmeta data-mint-head property=\"og:description\" content=\"How Cascade handles payments and billing.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Starter Kit\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://stackonfire.mintlify.app/essentials/payments\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://stackonfire.mintlify.site/_mintlify/api/og/v2?division=Essentials\u0026amp;title=Payments\u0026amp;description=How+Cascade+handles+payments+and+billing.\u0026amp;theme=189c6cb9eca4eeabd0ce5610\u0026amp;signature=32826f7f493f76fac7f4131d23b1265cec6164072a1cb3e1bfdb0e4699286256\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Payments - Starter Kit\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"How Cascade handles payments and billing.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://stackonfire.mintlify.site/_mintlify/api/og/v2?division=Essentials\u0026amp;title=Payments\u0026amp;description=How+Cascade+handles+payments+and+billing.\u0026amp;theme=189c6cb9eca4eeabd0ce5610\u0026amp;signature=32826f7f493f76fac7f4131d23b1265cec6164072a1cb3e1bfdb0e4699286256\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/stackonfire/TTqRBDFicbwrDbeB/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Starter Kit\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#757575\">\u003clink data-mint-head rel=\"canonical\" href=\"https://stackonfire.mintlify.app/essentials/payments\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/essentials/payments.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://stackonfire.mintlify.app/#organization\",\"name\":\"Starter Kit\",\"url\":\"https://stackonfire.mintlify.app\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/stackonfire/ga2IkdDnfRqvsygD/logo/light.svg?fit=max\u0026auto=format\u0026n=ga2IkdDnfRqvsygD\u0026q=85\u0026s=848a8e28c110a7c328693f6e504b607c\"}},{\"@type\":\"WebSite\",\"@id\":\"https://stackonfire.mintlify.app#website\",\"name\":\"Starter Kit\",\"url\":\"https://stackonfire.mintlify.app\",\"publisher\":{\"@id\":\"https://stackonfire.mintlify.app/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://stackonfire.mintlify.app/essentials/payments#webpage\",\"url\":\"https://stackonfire.mintlify.app/essentials/payments\",\"name\":\"Payments\",\"description\":\"How Cascade handles payments and billing.\",\"dateModified\":\"2026-01-07T01:46:28.667Z\",\"isPartOf\":{\"@id\":\"https://stackonfire.mintlify.app#website\"},\"breadcrumb\":{\"@id\":\"https://stackonfire.mintlify.app/essentials/payments#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://stackonfire.mintlify.app/essentials/payments#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Essentials\",\"item\":\"https://stackonfire.mintlify.app/essentials/database\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Payments\",\"item\":\"https://stackonfire.mintlify.app/essentials/payments\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://stackonfire.mintlify.app/essentials/payments#article\",\"headline\":\"Payments\",\"name\":\"Payments\",\"description\":\"How Cascade handles payments and billing.\",\"url\":\"https://stackonfire.mintlify.app/essentials/payments\",\"mainEntityOfPage\":{\"@id\":\"https://stackonfire.mintlify.app/essentials/payments#webpage\"},\"dateModified\":\"2026-01-07T01:46:28.667Z\",\"publisher\":{\"@id\":\"https://stackonfire.mintlify.app/#organization\"},\"isPartOf\":{\"@id\":\"https://stackonfire.mintlify.app#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Starter Kit\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Starter Kit\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/essentials/payments.md","siteName":"Starter Kit","nav":{"global":{"anchors":[{"anchor":"Demo","href":"https://cascade.stackonfire.com","icon":"laptop"},{"anchor":"Code on Github","href":"https://github.com/d-ivashchuk/cascade","icon":"github"}]},"anchors":[{"anchor":"Documentation","icon":"book-open","groups":[{"group":"Get Started","pages":[{"title":"Introduction","icon":"rocket","href":"/introduction"},{"title":"Quickstart","icon":"play","href":"/quickstart"}]},{"group":"Essentials","pages":[{"title":"Database","icon":"database","href":"/essentials/database"},{"title":"Authentication","description":"How Cascade handles authentication and authorization.","icon":"user","href":"/essentials/authentication"},{"title":"Payments","icon":"lemon","href":"/essentials/payments"},{"title":"Background jobs","description":"How cascade handles background jobs","icon":"stopwatch","href":"/essentials/background-jobs"},{"title":"Emails","icon":"envelopes","href":"/essentials/emails"},{"title":"Error tracking","icon":"bug","href":"/essentials/error-tracking"},{"title":"User analytics","icon":"chart-mixed","href":"/essentials/user-analytics"}]},{"group":"Marketing","pages":[{"title":"SEO","icon":"window-maximize","href":"/marketing/SEO"},{"title":"Blog","icon":"feather","href":"/marketing/blog"},{"title":"Newsletter","icon":"envelope-open-text","href":"/marketing/newsletter"}]},{"group":"Examples","pages":[{"title":"AI","icon":"robot","href":"/examples/ai"},{"title":"File uploads","icon":"upload","href":"/examples/file-uploads"}]}]}]},"basePath":"","title":"Payments - Starter Kit","buildId":"dpl_5joLUXmnJgwqjrHAS4dxZrQTdxgh","deploymentId":"dpl_5joLUXmnJgwqjrHAS4dxZrQTdxgh","dynamics":["07c022d89b","a74be98ba7"],"chunks":["Frame-B_503rGq.js","DynamicMarkdown-BfddVCX7.js","zoom-image-lightbox-B3yYlvdS.js","lightbox-handle-r17bVUz3.js"]}