stripe-stack

<quick_start> Add payments to a Next.js + Supabase project:

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "stripe-stack" with this command: npx skills add scientiacapital/skills/scientiacapital-skills-stripe-stack

<quick_start> Add payments to a Next.js + Supabase project:

  • Install Stripe: npm install stripe @stripe/stripe-js

  • Add env vars (see quick_reference below)

  • Create idempotency table (see schema below)

  • Choose workflow: setup-new-project.md or add-webhook-handler.md

// Lazy-loaded Stripe client import Stripe from 'stripe'; let _stripe: Stripe | null = null; export function getStripe(): Stripe { if (!_stripe) { _stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2025-12-15.clover' }); } return _stripe; }

</quick_start>

<success_criteria> Integration is successful when:

  • Webhook handler uses database-backed idempotency (not in-memory)

  • All keys in environment variables (never hardcoded)

  • Test mode fully working before any live mode deployment

  • Signature verification on all webhook endpoints

  • Event logging before processing (insert-before-process pattern)

  • Go-live checklist completed before production deployment </success_criteria>

<essential_principles>

Core Principles

Idempotency is Non-Negotiable

  • ALL webhook handlers MUST use database-backed idempotency

  • Never use in-memory Sets (lost on serverless cold starts)

  • Insert event record BEFORE processing, not after

Test/Live Mode Separation

  • Use environment variables for ALL keys (never hardcode)

  • Test keys: sk_test_ , pk_test_ , whsec_test_

  • Live keys: sk_live_ , pk_live_ , whsec_live_

  • Products/prices must be recreated in live mode

Shared Stripe Account

  • All NetZero Suite projects share ONE Stripe account

  • Same webhook secret can be used across projects

  • Each project has its own webhook endpoint URL

Lazy Client Initialization

  • Never initialize Stripe at module level (build errors)

  • Use factory function pattern for server-side client

  • Check for API key before creating instance

</essential_principles>

What Are You Building?

Before proceeding, identify your use case:

Use Case Workflow Description

New project setup-new-project.md

Fresh Stripe integration from scratch

Add webhooks add-webhook-handler.md

Add webhook handler to existing project

Subscriptions implement-subscriptions.md

Recurring billing with plans

Credit system add-credit-system.md

Pay-as-you-go credits

Go live go-live-checklist.md

Test → Production migration

Workflow Routing

If setting up Stripe in a new project: → Read workflows/setup-new-project.md

→ Then read reference/environment-vars.md

→ Use templates/stripe-client.ts and templates/env-example.txt

If adding webhook handling: → Read workflows/add-webhook-handler.md

→ Then read reference/webhook-patterns.md

→ Use templates/webhook-handler-nextjs.ts and templates/idempotency-migration.sql

If implementing subscription billing: → Read workflows/implement-subscriptions.md

→ Then read reference/pricing-models.md

→ Use templates/plans-config.ts

If adding credit/usage-based system: → Read workflows/add-credit-system.md

→ Then read reference/pricing-models.md

If migrating test → production: → Read workflows/go-live-checklist.md

<quick_reference>

Quick Reference

Environment Variables (Standard)

Server-side (never expose to client)

STRIPE_SECRET_KEY=sk_test_... STRIPE_WEBHOOK_SECRET=whsec_...

Client-side (safe to expose)

NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...

Optional: Price IDs (for test→live switching)

STRIPE_PRICE_STARTER_MONTHLY=price_... STRIPE_PRICE_PRO_MONTHLY=price_...

Common Webhook Events

Event When It Fires Action

checkout.session.completed

Customer completes checkout Create subscription record

customer.subscription.created

New subscription starts Initialize user limits

customer.subscription.updated

Plan change, renewal Update plan/limits

customer.subscription.deleted

Cancellation Downgrade to free

invoice.paid

Monthly renewal success Reset usage counters

invoice.payment_failed

Payment failed Mark as past_due

Stripe Client Pattern

let _stripe: Stripe | null = null;

export function getStripe(): Stripe { if (!_stripe) { const key = process.env.STRIPE_SECRET_KEY; if (!key) throw new Error('STRIPE_SECRET_KEY not configured'); _stripe = new Stripe(key, { apiVersion: '2025-12-15.clover', typescript: true }); } return _stripe; }

Idempotency Table Schema

CREATE TABLE stripe_webhook_events ( id TEXT PRIMARY KEY, -- Use Stripe event ID directly type TEXT NOT NULL, -- Event type data JSONB NOT NULL, -- Full event payload processed_at TIMESTAMPTZ DEFAULT NOW() );

Webhook Handler Structure

export async function POST(request: NextRequest) { const body = await request.text(); const signature = request.headers.get('stripe-signature');

// 1. Verify signature const event = stripe.webhooks.constructEvent(body, signature, webhookSecret);

// 2. Check idempotency (BEFORE processing) const { data: existing } = await supabase .from('stripe_webhook_events') .select('id') .eq('id', event.id) .single();

if (existing) return NextResponse.json({ duplicate: true });

// 3. Log event (INSERT before processing) await supabase.from('stripe_webhook_events').insert({ id: event.id, type: event.type, data: event, });

// 4. Process event switch (event.type) { case 'checkout.session.completed': await handleCheckout(event.data.object); break; // ... other handlers }

return NextResponse.json({ received: true }); }

</quick_reference>

<integration_notes>

Integration Notes

Works With

  • Supabase: Use service role client for webhook handlers (bypasses RLS)

  • Prisma: Alternative to Supabase for idempotency table

  • Vercel: Add runtime/maxDuration config for webhook routes

  • Next.js App Router: Use request.text() for raw body

Related Skills

  • supabase-sql-skill

  • For database migrations

  • create-hooks-skill

  • For post-deployment notifications

GitHub Repository

Private templates and examples available at: github.com/ScientiaCapital/stripe-stack

</integration_notes>

<reference_index>

Reference Files

File Purpose

reference/webhook-patterns.md

Idempotency, event handling, error recovery

reference/pricing-models.md

Plans vs Credits vs Usage-based billing

reference/environment-vars.md

Standard env var conventions

reference/common-errors.md

Troubleshooting guide

Template Files

File Purpose

templates/webhook-handler-nextjs.ts

Complete webhook route (copy-paste)

templates/stripe-client.ts

Lazy-loaded client factory

templates/plans-config.ts

Subscription plan definitions

templates/idempotency-migration.sql

Supabase migration

templates/webhook-handler.test.ts

Test template

templates/env-example.txt

Standard .env template

Workflow Files

File Purpose

workflows/setup-new-project.md

Fresh Stripe integration

workflows/add-webhook-handler.md

Add webhook to existing project

workflows/implement-subscriptions.md

Subscription billing

workflows/add-credit-system.md

Pay-as-you-go credits

workflows/go-live-checklist.md

Test → Production migration

</reference_index>

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

business-model-canvas

No summary provided by upstream source.

Repository SourceNeeds Review
General

trading-signals

No summary provided by upstream source.

Repository SourceNeeds Review
General

content-marketing

No summary provided by upstream source.

Repository SourceNeeds Review
General

crm-integration

No summary provided by upstream source.

Repository SourceNeeds Review