Skip to main content
Product pages tie together four moving parts: your database schema, a listing page, per-product detail pages, and a checkout flow. This guide walks through a simple one-click purchase setup, plus the advanced patterns you’ll layer on once the basics work.
Before you start: make sure your database is set up and Stripe is configured.

Three Paths

In your project’s AI chat, describe what you want:
The AI will scaffold the schema, pages, and checkout endpoint. Review the result and ask for refinements (pricing layout, image sizes, cart vs one-click, etc.).

The Products Table

Key decisions:
  • price_cents (integer) avoids floating-point rounding issues with money
  • slug (unique text) is your URL path segment
  • stripe_price_id links the DB row to the Stripe Price object
  • active lets you hide products without deleting them

Create Products in Stripe

For each product you want to sell:
1

Create the Product in Stripe

Stripe Dashboard > Products > Add Product. Name, description, image.
2

Add a Price

Stripe lets you have multiple prices per product. For a one-time purchase, pick One-time and enter the amount.
3

Copy the Price ID

Starts with price_. Save it to your DB row’s stripe_price_id.

The Listing Page: /shop

Fetch all active products and render them as a grid:

The Detail Page: /shop/[slug]

The Checkout Endpoint

Create api/checkout.ts:
The Buy Now button POSTs to this endpoint and redirects the browser to session.url (Stripe’s hosted checkout page).

Order Confirmation Page: /order-success

Reads session_id from the URL, fetches the session from Stripe, and displays a thank-you message:

The Stripe Webhook

The webhook is where the real work happens — recording orders, decrementing inventory, sending confirmation emails. Stripe calls your endpoint when the payment completes:
1

Create the webhook endpoint

api/stripe-webhook.ts. Verify the signing secret, then handle checkout.session.completed.
2

Create an orders row

Record amount, customer email, line items, Stripe session ID.
3

Decrement inventory

Pair this with your low-stock alert workflow.
4

Send a confirmation email

Use your email provider to send the order details. See Send Emails.

Advanced Patterns

Layer these in once the basic single-item checkout works:
  • Shopping cart — multi-item checkout with a cart state stored in localStorage or a carts table
  • Subscriptions — use Stripe’s subscription mode for recurring plans
  • Variants — size/color options with per-variant SKU and stock
  • Discount codes — Stripe Coupons applied at checkout
  • Abandoned cart recovery — see abandoned cart workflow
  • Out-of-stock handling — see low-stock alerts
Start simple — single-product, one-click checkout. Add cart, subscriptions, variants, and discounts only when specific customer requests or data show you need them. Most early e-commerce sites over-build and under-sell.

Verify It Worked

1

Use a test Stripe key

Confirm your project is using a sk_test_... key, not the live one.
2

Complete a test checkout

Click Buy Now on a product. On the Stripe checkout page, use test card 4242 4242 4242 4242 with any future expiry and any 3-digit CVC.
3

Confirm order recorded

Check your orders table — the new row should exist. Stock should have decremented. Confirmation email should be in your inbox.
4

Switch to live mode and buy your own product

Before going fully live, set your test Stripe keys to live keys, and actually buy a real product from your own site. Refund yourself. This catches anything test mode skipped.

Troubleshooting

You’re mixing test and live Stripe keys. Test-mode price IDs don’t work with live-mode keys and vice versa. Keep them consistent — either everything test or everything live.
Usually a missing or incorrect STRIPE_PUBLISHABLE_KEY env var on the client side, or a mismatch between the publishable key and the secret key’s mode. Check the browser console for Stripe errors.
In the Stripe Dashboard, go to Developers > Webhooks. Confirm the endpoint URL matches your deployed site. Confirm the signing secret in your env vars matches the one shown in Stripe. Click the webhook’s “Send test event” button to trigger a test delivery and check the response.
The webhook handler is erroring before it reaches the UPDATE. Check the Stripe webhook attempts log — you’ll see the failed responses with error messages. Then check your server logs via View Logs.
Either your email service isn’t configured or the webhook fails after the order insert but before the email send. Use a try/catch around the email call so a mail failure doesn’t break the rest of the order processing.

What’s Next?

Low-Stock Alerts

Get notified before you run out of inventory

Abandoned Cart Recovery

Win back customers who didn’t complete checkout