Clerk Billing and Stripe subscription management setup. Use when implementing subscriptions, configuring pricing plans, setting up billing, adding payment flows, managing entitlements, or when user mentions Clerk Billing, Stripe integration, subscription management, pricing tables, payment processing, or monetization.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
examples/feature-gate-pattern.tsxexamples/organization-billing.tsxexamples/saas-billing-flow.tsxexamples/usage-based-billing.tsxscripts/configure-plans.shscripts/setup-billing.shscripts/setup-webhooks.shtemplates/checkout-flow.tsxtemplates/pricing-page.tsxtemplates/subscription-management.tsxtemplates/webhook-handlers/payment-succeeded.tstemplates/webhook-handlers/subscription-created.tsThis skill provides complete Clerk Billing integration with Stripe for subscription management, pricing plans, and payment processing. Clerk Billing eliminates the need for custom webhooks and payment UI by connecting directly to Stripe while handling user interface, entitlement logic, and session-aware billing flows.
Initialize Clerk Billing in your Clerk Dashboard:
# Run automated setup script
bash ./skills/billing-integration/scripts/setup-billing.sh
What This Does:
Manual Setup Steps:
Create subscription plans and features:
# Run plan configuration script
bash ./skills/billing-integration/scripts/configure-plans.sh
Configuration Process:
Plan Types:
Add the pricing display component:
Using Template:
# Copy pricing page template
cp ./skills/billing-integration/templates/pricing-page.tsx app/pricing/page.tsx
Basic Implementation:
import { PricingTable } from '@clerk/nextjs'
export default function PricingPage() {
return (
<div className="container mx-auto py-12">
<h1 className="text-4xl font-bold text-center mb-8">
Choose Your Plan
</h1>
<PricingTable />
</div>
)
}
What PricingTable Provides:
Create a complete checkout experience:
# Copy checkout flow template
cp ./skills/billing-integration/templates/checkout-flow.tsx components/checkout-flow.tsx
Checkout Features:
Customization Options:
<PricingTable
appearance={{
theme: 'dark',
variables: {
colorPrimary: '#3b82f6',
borderRadius: '0.5rem',
}
}}
onSuccess={(subscription) => {
// Custom success handler
router.push('/dashboard')
}}
/>
Protect features based on subscription status:
Frontend Protection:
import { useAuth } from '@clerk/nextjs'
export default function FeatureComponent() {
const { has } = useAuth()
const canUseFeature = has?.({ feature: 'ai_assistant' })
if (!canUseFeature) {
return <UpgradePrompt feature="AI Assistant" />
}
return <AIAssistantInterface />
}
Backend Protection (API Routes):
import { auth } from '@clerk/nextjs/server'
export async function POST(request: Request) {
const { has } = await auth()
if (!has({ feature: 'ai_assistant' })) {
return Response.json(
{ error: 'Subscription required' },
{ status: 403 }
)
}
// Process request
}
Organization-Level Access:
const { has } = useAuth()
const orgHasFeature = has?.({
permission: 'org:billing:manage',
feature: 'team_workspace'
})
Enable users to manage subscriptions:
Built-in Management:
import { UserButton } from '@clerk/nextjs'
export default function Navigation() {
return (
<UserButton afterSignOutUrl="/" />
)
}
What Users Can Access:
Custom Management Interface:
# Copy subscription management template
cp ./skills/billing-integration/templates/subscription-management.tsx components/subscription-management.tsx
While Clerk handles most webhook logic automatically, you may need custom webhooks for:
# Setup webhook handlers
bash ./skills/billing-integration/scripts/setup-webhooks.sh
Common Webhook Events:
subscription.created - New subscriptionsubscription.updated - Plan changesubscription.deleted - Cancellationinvoice.payment_succeeded - Successful paymentinvoice.payment_failed - Failed paymentHandler Templates:
# Copy webhook handler templates
cp ./skills/billing-integration/templates/webhook-handlers/subscription-created.ts app/api/webhooks/subscription-created/route.ts
cp ./skills/billing-integration/templates/webhook-handlers/payment-succeeded.ts app/api/webhooks/payment-succeeded/route.ts
Sandbox Mode:
Test Cards (Stripe):
Success: 4242 4242 4242 4242
Decline: 4000 0000 0000 0002
3D Secure: 4000 0027 6000 3184
Testing Checklist:
# 1. Enable billing in Dashboard
bash ./skills/billing-integration/scripts/setup-billing.sh
# 2. Configure pricing plans
bash ./skills/billing-integration/scripts/configure-plans.sh
# 3. Implement pricing page
cp ./skills/billing-integration/templates/pricing-page.tsx app/pricing/page.tsx
# 4. Add subscription management
cp ./skills/billing-integration/templates/subscription-management.tsx components/subscription-management.tsx
# 5. Copy complete example
cp ./skills/billing-integration/examples/saas-billing-flow.tsx app/subscribe/page.tsx
Result: Full billing system with pricing display, checkout, and subscription management
Setup:
Implementation:
// Feature-gated component
import { useAuth } from '@clerk/nextjs'
import { PricingTable } from '@clerk/nextjs'
export default function PremiumFeature() {
const { has } = useAuth()
if (!has({ feature: 'premium_analytics' })) {
return (
<div className="border rounded-lg p-6">
<h3>Premium Analytics</h3>
<p>Upgrade to Pro to unlock advanced analytics</p>
<PricingTable />
</div>
)
}
return <AdvancedAnalyticsDashboard />
}
Setup:
Implementation:
import { useOrganization } from '@clerk/nextjs'
export default function OrgBilling() {
const { organization } = useOrganization()
return (
<div>
<h2>Billing for {organization?.name}</h2>
<PricingTable mode="organization" />
</div>
)
}
Setup:
Implementation:
// Track API usage
import { clerkClient } from '@clerk/nextjs/server'
export async function POST(request: Request) {
const { userId } = await auth()
// Check current usage
const user = await clerkClient.users.getUser(userId)
const currentUsage = user.publicMetadata.apiUsage || 0
// Check limit
const { has } = await auth()
const limit = has({ feature: 'api_calls_1000' }) ? 1000 : 100
if (currentUsage >= limit) {
return Response.json({ error: 'Usage limit reached' }, { status: 429 })
}
// Increment usage
await clerkClient.users.updateUserMetadata(userId, {
publicMetadata: {
apiUsage: currentUsage + 1
}
})
// Process request
}
Clerk Setup:
@clerk/nextjs version 5.0+Stripe Requirements:
Environment Variables:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
Dependencies:
{
"@clerk/nextjs": "^5.0.0",
"next": "^14.0.0",
"react": "^18.0.0"
}
Project Structure:
app/
├── pricing/
│ └── page.tsx # Pricing page with PricingTable
├── subscribe/
│ └── page.tsx # Checkout flow
├── api/
│ └── webhooks/ # Optional custom webhooks
components/
├── subscription-management.tsx
└── upgrade-prompt.tsx
Never Hardcode Credentials:
# ❌ WRONG
STRIPE_SECRET_KEY=sk_live_actual_key_here
# ✅ CORRECT
STRIPE_SECRET_KEY=your_stripe_secret_key_here
Always Use Environment Variables:
// ✅ Read from environment
const stripeKey = process.env.STRIPE_SECRET_KEY
if (!stripeKey) {
throw new Error('STRIPE_SECRET_KEY not configured')
}
Protect API Routes:
auth()Webhook Security:
import { headers } from 'next/headers'
import { stripe } from '@/lib/stripe'
export async function POST(request: Request) {
const body = await request.text()
const signature = headers().get('stripe-signature')
try {
const event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET
)
// Process event
} catch (err) {
return Response.json({ error: 'Invalid signature' }, { status: 400 })
}
}
Clerk Billing Settings (Dashboard):
Stripe Configuration (Synced):
Plan Design:
User Experience:
Access Control:
Pricing Strategy:
Monetization Approach:
Organizations:
User Management:
publicMetadata for client-accessible dataprivateMetadata for sensitive billing dataSession Awareness:
Common Issues:
PricingTable not displaying:
Payment failing:
Access control not working:
Webhooks not firing:
Debugging:
// Log subscription status
const { has, debug } = useAuth()
console.log('Auth debug:', debug)
console.log('Has feature:', has({ feature: 'ai_assistant' }))
Plugin: clerk Version: 1.0.0 Category: Billing & Monetization Skill Type: Integration & Setup