Lora is a sample AI chatbot application which lets users choose from a number of models and charges them on a per-token basis. It demonstrates a few features:
- Representing a usage-based billing model using meters, products, and prices
- Starting a subscription using an embedded Checkout Session
- Registering usage from a given user via meter events
- Integrating the Customer Portal for lightweight subscription management
- Consuming webhook events to freeze service on cancelled accounts
For the sake of demonstration, the per-token prices you'll use today will be more than 100x higher than usual. This is to ensure that you'll be able to get some real numbers without having to run too many test prompts.
Author's Note 1: This application is built toward the 2025-02-24.acacia API version, but the more recent 2025-03-31.basil has introduced breaking changes which impact this integration. In particular, the attributes of a Checkout Session have changed. The accounts we've created for you are configured to use 2025-02-24.acacia, and if you're logged into the account, the API reference will show you that version. However, if you plug in API keys from an account on the latest version, this integration won't work.
Author's Note 2: There is a minimal OpenAI integration included in this application. If you have an OpenAI account, you can plug in your own API keys to get real LLM responses rather than lorem ipsum. You can also explore OpenRouter.ai, which uses the OpenAI integration shape but lets you plug in other models, some of which are free.
You can find every place which needs updates by searching for TODO, but here's a summary:
- Set up Embedded Checkout in the
Subscribecomponent. This will also require setting up the code which creates a Checkout Session in the server'susersservice. - Update
clients/stripein the server to fetch our prices. - Set up the flow for creating meter events when somebody submits a prompt. You'll make changes from the prompt form all the way through to the server's
chatservice. - Set up the code which updates a user's account status if their payment fails.
- Redirect users to the Customer Portal in order to complete actions like updating their payment method or canceling their subscription.
The commands below were written for a bash terminal on a Unix system. If you're on Windows, we recommend working with Ubuntu on WSL, but the commands should also run in PowerShell.
mkdir -p ~/stripe
cd ~/stripeIf you're unfamiliar with cloning repositories, we have instructions below for whether or not you have an SSH key.
My GitHub account has an SSH key
git clone git@github.com:stripe-certification/billing_node_react_ilt.git
cd billing_node_react_iltMy GitHub account doesn't have an SSH key
You can quickly clone the repo by using the GitHub CLI. You can install it via:
- Unix systems with
brew:brew install gh - Windows systems:
winget install --id GitHub.cli - Other: https://github.com/cli/cli#installation
gh auth login
gh repo clone stripe-certification/billing_node_react_ilt
cd billing_node_react_iltYou can install the Stripe CLI with brew by running:
brew install stripe/stripe-cli/stripe.
If you're on a Windows machine or don't have brew, check here for other installation commands.
We'll use Node v22.15.0 on this application. You can set it up with nodenv by running:
nodenv install 22.15.0
nodenv local 22.15.0If you don't already have nodenv installed, then you can do so with their easy installation package: npx @nodenv/nodenv-installer.
The client and server run separately in this project, so we recommend opening two terminals side-by-side.
In the first terminal, install the server dependencies:
cd ./code/server
npm installIn the second terminal, install the client dependencies:
cd ./code/client
npm installYou'll need to set up the environment variables on both sides of the project.
- Make sure you're logged into the account we created for you (
sessions-dev). - Go to the Dashboard's API key page so that you'll have the publishable and secret keys on hand.
- Run
stripe loginto get your CLI synced with your account. Once that's complete, runstripe listen --print-secretto get your webhook secret. - From your terminal in
code/server, runcp ./.env.example .envto set up your.envfile. Plug in the values for the Stripe secret, publishable, and webhook keys. - From your terminal in
code/client, runcp ./.env.example .envto set up your.envfile. Plug in the value for the Stripe publishable key.
The Lora billing model depends on 4 products, 3 of which are metered. All of them have both monthly and recurring prices. You should have created these resources on your account earlier today, but if you haven't yet, then you'll find the instructions and commands for doing so in the Companion App's M4-1.
- From your terminal in
code/server, runnpm run dev. - From your terminal in
code/client, runnpm run dev. - Open
localhost:3000and the Lora app should open right up!
Visit the Customer Portal Settings page in your Stripe Dashboard to configure the billing portal.
- Navigate to
localhost:3000. You should see a landing page with a “Sign Up” section at the bottom. - If the client and server are communicating properly and you’ve created your prices, you should see a price listed for each plan.
- Clicking “Get Started” should take you to a create account page. After completing the form, you should be redirected to http://localhost:3000/sign-up?plan=.
There's a minimal smoke test written in Playwright to ensure that the application still starts once the Stripe integration has been redacted. Run it with the following commands:
npm install
export PLAYWRIGHT_BROWSERS_PATH=0
npx playwright install --with-deps chromium
npx playwright test
Note: Playwright installs browsers into a shared system directory by default. The environment variable exported above tells it to install browsers directly into this project folder, which is helpful on corporate devices which only allow binaries to be run from particular directories. If you don't have that constraint, then the variable can be omitted.