Environment variables
The app reads its configuration from a.env file in the project root. Create this file before starting the development server.
.env
Your Stripe secret API key. Used server-side in
customer.ts and payment.ts to instantiate the Stripe client via new Stripe(STRIPE_SECRET_KEY). In test mode, this value starts with sk_test_. In live mode, it starts with sk_live_.The webhook signing secret used in
webhook.ts to verify that incoming webhook requests originate from Stripe. Generated when you create a webhook endpoint in the Stripe Dashboard or by the Stripe CLI during local development. Starts with whsec_.Getting Stripe API keys
Log in to the Stripe Dashboard
Go to dashboard.stripe.com and sign in to your account.
Switch to test mode
Toggle the Test mode switch in the top-right corner of the Dashboard. All keys and resources created in test mode are isolated from live-mode data.
Open the API keys page
Navigate to Developers → API keys. You will see two keys:
- Publishable key — starts with
pk_test_. Used client-side insubscribe.tsxto initialize Stripe.js. - Secret key — starts with
sk_test_. Used server-side only. Click Reveal test key to view it.
Webhook configuration
Stripe sends webhook events to your server when subscription-related actions occur (for example, when a checkout session completes or a payment fails). The app verifies each event using the webhook signing secret.Local development with the Stripe CLI
Production webhook setup
Create a webhook endpoint in the Dashboard
Go to Developers → Webhooks → Add endpoint in the Stripe Dashboard.Set the endpoint URL to your production domain:
Select events to listen for
At a minimum, subscribe to the following events (these are the events the app handles):
invoice.paidinvoice.payment_failedcustomer.subscription.deleted
Session configuration
The app uses a cookie-based session to store authentication state. The session is configured insessions.ts using React Router’s createCookieSessionStorage:
sessions.ts
| Option | Value | Description |
|---|---|---|
name | __session | The name of the cookie sent in the browser. |
httpOnly | true | Prevents JavaScript from reading the cookie, reducing XSS exposure. |
maxAge | 60 | Session expires after 60 seconds of inactivity. Extend this for longer sessions. |
path | / | The cookie is sent for all routes under the root path. |
sameSite | lax | Protects against most CSRF attacks while allowing top-level navigations. |
secrets | ["s3cret1"] | Used to sign the cookie. Rotate this value in production. |
secure | true | The cookie is only sent over HTTPS. |
The
secure: true flag means the cookie will not be sent over plain HTTP. If you are running locally without HTTPS, you may need to set secure: false in your development environment. Never disable secure in production.Stripe publishable key
The Stripe publishable key is used client-side insubscribe.tsx to initialize Stripe.js for the payment element. Unlike the secret key, the publishable key can safely appear in browser-side code.
subscribe.tsx
pk_test_ in test mode and pk_live_ in live mode.