code/tamagui.dev/doc/stripe-setup.md
This document explains how to properly test Stripe subscriptions in the local development environment for Tamagui, including webhook configuration, database caveats, and reset operations.
stripe listenGo to your Stripe Dashboard and toggle "Test mode" in the top-right corner.
.envFrom the Developers > API keys section in the dashboard, copy the following:
pk_test_...sk_test_...Update your .env as follows:
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxx
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
The Tamagui site handles Stripe subscriptions in the following way:
create-subscription+api.tsupgrade-subscription+api.tsThese endpoints initiate the Stripe checkout session.
webhook+api.tsThis endpoint receives Stripe events and persists subscription data into Supabase.
Stripe events like checkout.session.completed, customer.subscription.created, and invoice.paid are handled here.
To capture webhook events locally while running your dev server, use the following command:
stripe listen --load-from-webhooks-api --forward-to http://localhost:8081/api/stripe/webhook
This forwards all webhook events configured in your Stripe dashboard to your local server.
๐ Ref: Stripe Webhook Docs
Since you're using Stripe in test mode and Supabase in production mode, a mismatch can occur:
customers table in Supabase uses a foreign key to auth.user.idUse the primary key (auth.user.id) to find and delete the corresponding record from the customers table manually or via Supabase UI/SQL.
Use the provided script to remove active subscriptions for a user:
cd code/tamagui.dev
node ./scripts/cancel-subscription.mjs <USER_ID>
This script will:
subscriptions table in Supabase with status: canceled๐ Script file:
code/tamagui.dev/scripts/cancel-subscription.mjs
A user is considered to be on the "Pro" plan if they have an active or trialing subscription named "Tamagui Pro".
This status is determined by checking the subscriptions table in Supabase.
๐ Logic from:
code/tamagui.dev/features/user/subscription/eligibility.ts
const hasProductAccess = (subscriptions, productName) =>
subscriptions?.some(
(sub) =>
(sub.status === 'active' || sub.status === 'trialing') &&
sub.subscription_items?.some((item) => item.price?.product?.name === productName)
)
This logic is used to check access to specific features like Pro, Chat, or Support tiers.
.env with Stripe test keyscustomers tablestripe listen in parallel with the dev serverCauses:
payment_method.idSolutions:
sk_test_... or sk_live_... keypaymentMethods.list to view available methods