Quick Start
Install and configure the Stripe fragment
Overview
The Fragno Stripe fragment makes it easy to manage Stripe subscriptions in your application. This guide will walk you through installation and basic setup to get your first subscription working.
Prerequisites
Before you begin, make sure you have:
- Stripe API Key
- Stripe Webhook Secret
- A Stripe Product & Price: Create at least one product with a price in your Stripe Dashboard
Installation
Install the Stripe fragment and Fragno db package:
npm install @fragno-dev/stripe @fragno-dev/dbServer Setup
1. Create the Fragment Instance
Create a file to instantiate your Stripe fragment (e.g., lib/stripe.ts or server/stripe.ts):
import { createStripeFragment } from "@fragno-dev/stripe";
/* These imports are illustrative and application specific */
import { databaseAdapter } from "@/db/fragno";
import { getSession } from "@/lib/auth";
export const stripeFragment = createStripeFragment(
{
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
// Resolves the authenticated entity from the request
resolveEntityFromRequest: async (context) => {
// Get session using your authentication system
const session = await getSession(context.headers);
if (!session) {
return null; // The fragment responds with 401 UNAUTHENTICATED
}
return {
// Your application's identifier for the entity which owns the subscription
referenceId: session.user.id,
// Set on the Stripe customer the fragment creates for this entity
customerEmail: session.user.email,
customerMetadata: {},
};
},
// Runs after a subscription changed, e.g. to grant or revoke access
onSubscriptionChanged: async ({ subscription }) => {
console.log(subscription.referenceId, subscription.status);
},
},
{ databaseAdapter },
);The fragment creates a Stripe customer for an entity on its first checkout and remembers the link itself, so your application does not need to store Stripe IDs. See Subscriptions for all callbacks.
What is referenceId? This is your application's identifier for the entity that owns the
subscription (typically a user ID or organization ID). The fragment uses this to link Stripe data
back to your application's data model.
2. Mount the Fragment Routes
The fragment provides HTTP routes that need to be mounted in your application. How you do this depends on your framework. See Frameworks supported frameworks.
import { stripeFragment } from "@/lib/stripe";
export const { GET, POST, PUT, PATCH, DELETE } = stripeFragment.handlersFor("next-js");3. Run Database Migrations
The fragment adds customer and subscription tables to your database. Generate the schema for
these tables using the fragno-cli. For setting up Fragno DB schemas, see the
Fragno DB Quickstart.
# Generate schema file
npx fragno-cli db generate lib/stripe.ts --format drizzle -o db/stripe.schema.ts4. Run a Hook Processor
The webhook route only records each Stripe event; durable hooks process it afterwards and retry when Stripe or your callbacks fail. Run a hook processor so they run:
import { createDurableHooksProcessor } from "@fragno-dev/db/dispatchers/node";
createDurableHooksProcessor([stripeFragment], { pollIntervalMs: 2000 }).startPolling();Creating a subscription
Create a client instance to use the fragment in your frontend:
import { createStripeFragmentClient } from "@fragno-dev/stripe/react";
export const stripeClient = createStripeFragmentClient();This client exposes several mutators for managing subscriptions:
upgradeSubscription: create or update a subscriptioncancelSubscription: cancel a subscriptionuseBillingPortal: redirect to Stripe's billing portal for managing payment methods and billing details
import { stripeClient } from "@/lib/stripe-client";
export function SubscribeButton() {
const { mutate, loading, error } = stripeClient.upgradeSubscription();
const handleSubscribe = async () => {
const { url } = await mutate({
body: {
priceId: "price_1234567890", // The Stripe price ID being subscribed to
successUrl: `${window.location.origin}/success`,
cancelUrl: window.location.href,
},
});
window.location.href = url; // Redirect to Stripe Checkout
};
return (
<button onClick={handleSubscribe} disabled={loading}>
{loading ? "Loading..." : "Subscribe"}
</button>
);
}