@flowglad/nextjs
v0.18.0
Published
A Next.js integration package for Flowglad, providing utilities for both client and server-side functionality.
Downloads
5,319
Readme
@flowglad/nextjs
A Next.js integration package for Flowglad, providing utilities for both client and server-side functionality.
Installation
npm install @flowglad/nextjs
# or
yarn add @flowglad/nextjs
# or
bun add @flowglad/nextjsRequirements
- React 18 or 19
- Next.js 14, 15, or 16
Usage
Client-side Components
Import client-side components and utilities directly from the package:
import { Component } from '@flowglad/nextjs';Server-side Code
For server-side code, use the dedicated server import path:
import { serverFunction } from '@flowglad/nextjs/server';This separation ensures proper code splitting and prevents server-only code from being included in client bundles.
Features
- App Router Support
- Pages Router Support
- Type-safe route handlers
- Server-side utilities
- Client-side components
- React Context for billing and subscription management
API Reference
React Context
The package provides a React context for managing billing and subscription state. Here's how to use it:
// In your app's root layout or page
import { FlowgladProvider } from '@flowglad/nextjs';
export default function RootLayout({ children }) {
return (
<FlowgladProvider
baseURL="https://your-app.com" // Base URL of your app (optional, defaults to relative /api/flowglad)
>
{children}
</FlowgladProvider>
);
}
// In your components
import { useBilling, usePricing } from '@flowglad/nextjs';
function BillingComponent() {
const pricingModel = usePricing();
const {
customer,
subscriptions,
paymentMethods,
createCheckoutSession,
cancelSubscription,
loaded,
errors
} = useBilling();
if (!loaded || !pricingModel) {
return <div>Loading...</div>;
}
if (errors) {
return <div>Error: {errors[0].message}</div>;
}
return (
<div>
<h2>Current Subscriptions</h2>
{subscriptions?.map(sub => (
<div key={sub.id}>
{sub.name} - {sub.status}
<button onClick={() => cancelSubscription({ subscriptionId: sub.id })}>
Cancel
</button>
</div>
))}
<button
disabled={!pricingModel.products[0]?.defaultPrice}
onClick={() =>
createCheckoutSession({
successUrl: 'https://your-app.com/success',
cancelUrl: 'https://your-app.com/cancel',
priceSlug: pricingModel.products[0]?.defaultPrice?.slug,
})
}
>
Subscribe
</button>
</div>
);
}Route Handlers
App Router
import { nextRouteHandler } from '@flowglad/nextjs/server';
import { flowglad } from '@/lib/flowglad';
import { verifyToken } from '@/lib/auth';
// Create the route handler with customer ID extraction
export const { GET, POST } = nextRouteHandler({
getCustomerExternalId: async (req) => {
const token = req.headers.get('authorization')?.split(' ')[1];
if (!token) throw new Error('Unauthorized');
const decoded = await verifyToken(token);
return decoded.userId;
},
flowglad,
});Pages Router
import { pagesRouteHandler } from '@flowglad/nextjs/server';
import { flowglad } from '@/lib/flowglad';
import { verifyToken } from '@/lib/auth';
// Create the route handler with customer ID extraction
export default pagesRouteHandler({
getCustomerExternalId: async (req) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) throw new Error('Unauthorized');
const decoded = await verifyToken(token);
return decoded.userId;
},
flowglad,
});The route handlers will automatically:
- Parse the request path from the URL
- Handle query parameters (normalized for Pages Router)
- Process request bodies for non-GET requests
License
This project is licensed under the MIT License - see the LICENSE file for details.
