Using stripekit
stripekit is a CLI that (1) reconciles a declarative stripe.config.ts into the user's own Stripe account and (2) scaffolds correct billing code into a Next.js App Router app. It's plain Stripe underneath — no hosted service, no runtime dependency.
Install-free: every command runs via npx stripekit@latest <command>. Always check npm for the latest version.
Prerequisites
- Node.js 20+.
- A Stripe test secret key (
sk_test_…) available asSTRIPE_SECRET_KEYin the environment or.env.local. Never enter real keys on the user's behalf — ask them to add it.
Full setup in a Next.js app
npx stripekit@latest init— detects the framework + auth library, writesstripe.config.ts, and scaffoldslib/stripe/*(client, sync, customer helpers, storage adapter) andapp/api/stripe/*(webhook, checkout, portal). Flags:--adapter kv|drizzle,--auth clerk|authjs|better-auth|none,--yes.- Edit
stripe.config.tsto define products, prices, and features. npx stripekit plan— preview what will change on the Stripe account (read-only).npx stripekit push— create/update products, prices, webhook endpoint, and portal; writesSTRIPE_WEBHOOK_SECRETandSTRIPE_PORTAL_CONFIGURATION_IDback to.env.local.npx stripekit dev— forward Stripe webhooks to localhost during development (wrapsstripe listen).npx stripekit check— verify keys, config, drift, and webhook/portal wiring.
Any stack (catalog only)
Running init in a non-Next.js project sets up only stripe.config.ts. Use plan / push / pull to manage the catalog from any stack.
Config shape
import { defineConfig } from 'stripekit'
export default defineConfig({
products: {
pro: {
name: 'Pro',
prices: {
monthly: { amount: 2000, currency: 'usd', interval: 'month' }, // amount in cents
yearly: { amount: 19200, currency: 'usd', interval: 'year' },
},
features: { seats: 5, projects: 'unlimited' },
},
},
portal: { cancellations: true, planSwitching: true },
webhooks: { path: '/api/stripe/webhook' },
})Reference prices in app code by their stable lookup key — product_price, e.g. pro_monthly — never a Stripe price ID. Amounts can change without touching app code.
Machine-readable output (for agents/CI)
Every command accepts --json.
plan --json/push --json→{ mode, summary: { create, update, replace, destroy, total }, actions: [{ kind, effect, description }], applied, appliedCount?, envUpdated? }.check --json→{ ok, items: [{ label, status, detail }] }.pull --json→{ productCount, priceCount, warnings, source }.
Use --yes to skip prompts. To apply to a live account you must pass both --live and --yes; do this only with explicit user confirmation.
Safety invariants
pushonly reads/mutates objects stripekit created (tagged via metadata). Anything the user made by hand in the Stripe dashboard is never touched.- Prices are immutable in Stripe: an amount/interval change creates a new price, moves the lookup key onto it, and archives the old one. Existing subscriptions are never disrupted.
- Removed items are archived, never deleted. Reconciliation is idempotent (apply then re-plan → zero changes).
More
Docs: https://stripe.rafael.ltd/ · Machine index: https://stripe.rafael.ltd/llms.txt · Source: https://github.com/rafaelcg/stripekit