First party fragmentStripeFormsWorkflowsUploadsAuth

Stripe Billing

Subscriptions, checkout, webhooks, and billing portal flows in one fragment.

Install

npm install @fragno-dev/stripe @fragno-dev/db

Billing flow

A Stripe event moves through your app in minutes.

  1. 1

    Checkout session

    Stripe creates a session and redirects the customer.

  2. 2

    Webhook event

    The fragment syncs subscription state into your database.

  3. 3

    In-app hooks

    Use typed hooks to trigger upgrades, cancellations, or portals.

Checkout + billing portal

Create subscriptions, upgrades, and cancellations directly from your frontend.

Automatic webhook sync

Keep subscription state up to date with Stripe events and sync helpers.

Database-backed state

The fragment stores subscription data in your own database.

Setup blueprint

The high-signal steps, with code you can paste.

1. Install

Install the fragment and the Fragno DB package.

npm install @fragno-dev/stripe @fragno-dev/db

2. Create the fragment server

Configure Stripe secrets and map customers to your users.

import { createStripeFragment } from "@fragno-dev/stripe";import { getSession } from "@/lib/auth";import { updateEntity } from "@/db/repo";export const stripeFragment = createStripeFragment({  stripeSecretKey: process.env.STRIPE_SECRET_KEY!,  webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,  onStripeCustomerCreated: async (stripeCustomerId, referenceId) => {    await updateEntity(referenceId, { stripeCustomerId });  },  resolveEntityFromRequest: async (context) => {    const session = getSession(context.headers);    return {      referenceId: session.user.id,      customerEmail: session.user.email,      stripeCustomerId: session.user.stripeCustomerId || undefined,      stripeMetadata: {},    };  },});

3. Mount routes + generate schema

Expose the Stripe handlers and generate schema migrations.

import { stripeFragment } from "@/lib/stripe";export const handlers = stripeFragment.handlersFor("react-router");export const action = handlers.action;export const loader = handlers.loader;// Generate schema// npx fragno-cli db generate lib/stripe.ts --format drizzle -o db/stripe.schema.ts

4. Create a client

Generate typed hooks for billing flows.

import { createStripeFragmentClient } from "@fragno-dev/stripe/react";export const stripeClient = createStripeFragmentClient();

Use it

Hook into upgrade/cancel flows directly in your UI.

import { stripeClient } from "@/lib/stripe-client";export function SubscribeButton() {  const { mutate, loading } = stripeClient.upgradeSubscription();  const handleSubscribe = async () => {    const { url, redirect } = await mutate({      body: {        priceId: "price_123",        successUrl: `${window.location.origin}/success`,        cancelUrl: window.location.href,      },    });    if (redirect) {      window.location.href = url;    }  };  return (    <button onClick={handleSubscribe} disabled={loading}>      {loading ? "Loading..." : "Subscribe"}    </button>  );}

Query subscriptions

Access subscription data on the server for dashboards or admin flows.

import { stripeFragment } from "@/lib/stripe";const subscriptions = await stripeFragment.services.getSubscriptionsByReferenceId(user.id);const subscription = await stripeFragment.services.getSubscriptionById(subscriptionId);const byCustomer = await stripeFragment.services.getSubscriptionsByStripeCustomerId(customerId);

We fix split brain

Keep Stripe and your database in sync

Split brain happens when Stripe is the source of truth but your app depends on a local copy of subscription state. The fragment ships the webhook handlers, schema, and client hooks together so you stay synchronized without re-implementing the hard parts.

BackendStripe Fragment Server/api/stripe/upgrade/api/stripe/webhook
FrontendStripe Fragment ClientupgradeSubscription()cancelSubscription()
Stripe API
subscriptionsDBWebhookEventsAPIDeveloperStripe FragmentStripe

Events flow from Stripe → fragment handlers → your database. Your UI reads from a single, consistent source instead of juggling webhook races.