@nextsparkjs/ai-workflow 0.1.0-beta.127 → 0.1.0-beta.128

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ Interactive guide to configure subscription plans, features, and billing in Next
7
7
  ## Required Skills
8
8
 
9
9
  Before executing, these skills provide deeper context:
10
- - `.claude/skills/billing-subscriptions/SKILL.md` - Stripe integration and billing patterns
10
+ - `.claude/skills/billing-subscriptions/SKILL.md` - Multi-provider billing and Gateway Factory patterns
11
11
  - `.claude/skills/permissions-system/SKILL.md` - Three-layer permission model
12
12
 
13
13
  ---
@@ -22,7 +22,7 @@ Before executing, these skills provide deeper context:
22
22
 
23
23
  ## Behavior
24
24
 
25
- Guides the user through configuring subscription plans with features, usage limits, and Stripe integration.
25
+ Guides the user through configuring subscription plans with features, usage limits, and payment provider integration.
26
26
 
27
27
  ---
28
28
 
@@ -43,8 +43,8 @@ Step 3: Define Usage Limits (Quotas)
43
43
  Step 4: Configure Plans
44
44
  └── Create free, pro, enterprise plans
45
45
 
46
- Step 5: Set Up Stripe
47
- └── Create products and prices
46
+ Step 5: Set Up Payment Provider
47
+ └── Create products and prices (Stripe or Polar)
48
48
 
49
49
  Step 6: Test the Checkout Flow
50
50
  └── Verify the complete flow
@@ -327,8 +327,7 @@ export const billingConfig: BillingConfig = {
327
327
  api_calls: 1000,
328
328
  email_sends: 100,
329
329
  },
330
- stripePriceIdMonthly: null,
331
- stripePriceIdYearly: null,
330
+ // No price IDs for free plan
332
331
  },
333
332
 
334
333
  // PRO PLAN
@@ -357,8 +356,10 @@ export const billingConfig: BillingConfig = {
357
356
  api_calls: 100000,
358
357
  email_sends: 5000,
359
358
  },
360
- stripePriceIdMonthly: 'price_xxx_monthly', // From Stripe
361
- stripePriceIdYearly: 'price_xxx_yearly',
359
+ providerPriceIds: {
360
+ monthly: 'price_xxx_monthly', // From your payment provider
361
+ yearly: 'price_xxx_yearly',
362
+ },
362
363
  },
363
364
 
364
365
  // ENTERPRISE PLAN
@@ -386,7 +387,7 @@ export const billingConfig: BillingConfig = {
386
387
  📋 Plan Types:
387
388
 
388
389
  • 'free' - No payment required
389
- • 'paid' - Requires Stripe subscription
390
+ • 'paid' - Requires payment subscription
390
391
  • 'enterprise' - Custom pricing (contact sales)
391
392
 
392
393
  📋 Visibility:
@@ -398,37 +399,47 @@ export const billingConfig: BillingConfig = {
398
399
 
399
400
  What would you like to do?
400
401
 
401
- [1] Continue to Step 5 (Stripe Setup)
402
+ [1] Continue to Step 5 (Payment Provider Setup)
402
403
  [2] How do I add more plan tiers?
403
404
  [3] Show me the pricing page component
404
405
  ```
405
406
 
406
407
  ---
407
408
 
408
- ## Step 5: Set Up Stripe
409
+ ## Step 5: Set Up Payment Provider
409
410
 
410
411
  ```
411
412
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
412
- STEP 5 OF 6: Set Up Stripe
413
+ STEP 5 OF 6: Set Up Payment Provider
413
414
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
414
415
 
415
- 1️⃣ Create Stripe Products and Prices:
416
-
417
- In Stripe Dashboard (dashboard.stripe.com):
416
+ 1️⃣ Create Products and Prices in your provider:
418
417
 
418
+ For Stripe (dashboard.stripe.com):
419
419
  • Products → Add Product → "Pro Plan"
420
420
  • Add Price → $29/month → Copy price_xxx_monthly
421
421
  • Add Price → $290/year → Copy price_xxx_yearly
422
422
 
423
+ For Polar (polar.sh):
424
+ • Products → Create Product → Set pricing
425
+ • Copy the Product Price ID
426
+
423
427
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
424
428
 
425
429
  2️⃣ Configure Environment Variables:
426
430
 
427
431
  ```env
428
432
  # .env.local
433
+
434
+ # For Stripe:
429
435
  STRIPE_SECRET_KEY=sk_test_xxx
430
436
  STRIPE_PUBLISHABLE_KEY=pk_test_xxx
431
437
  STRIPE_WEBHOOK_SECRET=whsec_xxx
438
+
439
+ # For Polar:
440
+ POLAR_ACCESS_TOKEN=pat_xxx
441
+ POLAR_WEBHOOK_SECRET=whsec_xxx
442
+ POLAR_SERVER=sandbox
432
443
  ```
433
444
 
434
445
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -440,8 +451,10 @@ STRIPE_WEBHOOK_SECRET=whsec_xxx
440
451
  {
441
452
  slug: 'pro',
442
453
  // ...
443
- stripePriceIdMonthly: 'price_1xxx', // From Stripe
444
- stripePriceIdYearly: 'price_1yyy',
454
+ providerPriceIds: {
455
+ monthly: 'price_1xxx', // From your provider
456
+ yearly: 'price_1yyy',
457
+ },
445
458
  }
446
459
  ```
447
460
 
@@ -449,23 +462,17 @@ STRIPE_WEBHOOK_SECRET=whsec_xxx
449
462
 
450
463
  4️⃣ Set Up Webhook:
451
464
 
452
- In Stripe Dashboard → Webhooks → Add endpoint:
453
-
465
+ For Stripe: Dashboard → Webhooks → Add endpoint
454
466
  URL: https://your-domain.com/api/v1/billing/webhooks/stripe
455
467
 
456
- Events to listen for:
457
- checkout.session.completed
458
- • invoice.paid
459
- • invoice.payment_failed
460
- • customer.subscription.updated
461
- • customer.subscription.deleted
468
+ For Polar: Organization Settings → Webhooks → Add endpoint
469
+ URL: https://your-domain.com/api/v1/billing/webhooks/polar
462
470
 
463
471
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
464
472
 
465
- 5️⃣ Test with Stripe CLI (development):
473
+ 5️⃣ Test locally (Stripe example):
466
474
 
467
475
  ```bash
468
- # Install Stripe CLI
469
476
  stripe listen --forward-to localhost:3000/api/v1/billing/webhooks/stripe
470
477
  ```
471
478
 
@@ -474,7 +481,7 @@ stripe listen --forward-to localhost:3000/api/v1/billing/webhooks/stripe
474
481
  What would you like to do?
475
482
 
476
483
  [1] Continue to Step 6 (Test Checkout)
477
- [2] I have questions about Stripe setup
484
+ [2] I have questions about provider setup
478
485
  [3] Help me set up webhook forwarding
479
486
  ```
480
487
 
@@ -536,7 +543,7 @@ node core/scripts/build/registry.mjs
536
543
 
537
544
  • Go to /pricing (or /dashboard/settings/billing)
538
545
  • Click "Upgrade to Pro"
539
- • Use Stripe test card: 4242 4242 4242 4242
546
+ • Use test card (Stripe): 4242 4242 4242 4242
540
547
  • Complete checkout
541
548
  • Verify webhook updates subscription
542
549
  • Check features are now available
@@ -557,7 +564,7 @@ You've configured:
557
564
  • Feature flags for plan gating
558
565
  • Usage limits and quotas
559
566
  • Subscription plans with pricing
560
- • Stripe integration
567
+ Payment provider integration (Stripe or Polar)
561
568
 
562
569
  📚 Related tutorials:
563
570
  • /how-to:set-user-roles-and-permissions - RBAC configuration
@@ -20,7 +20,7 @@ BILLING ARCHITECTURE:
20
20
 
21
21
  Configuration Layer:
22
22
  contents/themes/{theme}/config/billing.config.ts
23
- ├── provider: 'stripe' | 'polar' | 'paddle' | 'lemonsqueezy'
23
+ ├── provider: 'stripe' | 'polar' # (paddle, lemonsqueezy, mercadopago: type defined, not yet implemented)
24
24
  ├── currency: 'usd' | 'eur' | ...
25
25
  ├── defaultPlan: 'free'
26
26
  ├── features: { featureSlug: FeatureDefinition }
@@ -37,7 +37,7 @@ core/lib/billing/
37
37
  │ ├── types.ts # Provider-agnostic result types
38
38
  │ ├── interface.ts # BillingGateway interface (contract)
39
39
  │ ├── factory.ts # getBillingGateway() factory
40
- └── stripe.ts # StripeGateway implements BillingGateway
40
+ ├── stripe.ts # StripeGateway implements BillingGateway
41
41
  │ └── polar.ts # PolarGateway implements BillingGateway
42
42
  ├── queries.ts # Database queries
43
43
  ├── enforcement.ts # Limit/feature enforcement
@@ -97,6 +97,11 @@ export interface BillingGateway {
97
97
 
98
98
  // Webhooks (Stripe passes string signature, Polar passes headers Record)
99
99
  verifyWebhookSignature(payload: string | Buffer, signatureOrHeaders: string | Record<string, string>): WebhookEventResult
100
+
101
+ // Dashboard & Metadata
102
+ getProviderName(): string
103
+ getSubscriptionDashboardUrl(externalSubscriptionId: string | null | undefined): string | null
104
+ getResourceHintDomains(): { preconnect: string[]; dnsPrefetch: string[] }
100
105
  }
101
106
  ```
102
107
 
@@ -144,29 +149,33 @@ const session = await getBillingGateway().createCheckoutSession(params)
144
149
  const portal = await getBillingGateway().createPortalSession(params)
145
150
  await getBillingGateway().cancelSubscriptionAtPeriodEnd(subId)
146
151
 
152
+ // Provider metadata
153
+ const name = getBillingGateway().getProviderName() // "Stripe" or "Polar"
154
+ const url = getBillingGateway().getSubscriptionDashboardUrl(id) // Dashboard URL or null
155
+
156
+ // Resource hints (used in layout.tsx automatically)
157
+ import { getBillingResourceHints } from '@nextsparkjs/core/lib/billing/gateways/factory'
158
+ const { preconnect, dnsPrefetch } = getBillingResourceHints()
159
+
147
160
  // WRONG: Import from specific provider
148
161
  import { createCheckoutSession } from '.../gateways/stripe' // DEPRECATED
149
162
  ```
150
163
 
151
164
  ### Plan Price IDs
152
165
 
153
- Plans support both provider-specific and generic price IDs:
166
+ Plans use `providerPriceIds` for price configuration (works with any provider):
154
167
 
155
168
  ```typescript
156
169
  // PlanDefinition in config-types.ts
157
170
  {
158
171
  slug: 'pro',
159
- // Generic (checked first) - works with any provider
160
172
  providerPriceIds: {
161
173
  monthly: 'price_xxx_monthly',
162
174
  yearly: 'price_xxx_yearly',
163
175
  },
164
- // Stripe-specific (fallback for backward compat)
165
- stripePriceIdMonthly: 'price_pro_monthly',
166
- stripePriceIdYearly: 'price_pro_yearly',
167
176
  }
168
177
 
169
- // PlanService.getPriceId() checks providerPriceIds first, falls back to stripe-specific
178
+ // PlanService.getPriceId() reads from providerPriceIds
170
179
  const priceId = PlanService.getPriceId('pro', 'monthly')
171
180
  ```
172
181
 
@@ -237,13 +246,16 @@ export class StripeGateway implements BillingGateway {
237
246
  // app/api/v1/billing/webhooks/stripe/route.ts
238
247
  // NOTE: Webhook routes stay provider-specific by design.
239
248
  // They need raw provider types for proper type narrowing.
240
- import { getStripeInstance } from '@nextsparkjs/core/lib/billing/gateways/stripe'
241
- import type Stripe from 'stripe'
249
+ import Stripe from 'stripe'
250
+
251
+ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
242
252
 
243
253
  export async function POST(request: NextRequest) {
244
254
  const payload = await request.text()
245
255
  const signature = request.headers.get('stripe-signature')!
246
- const event = getStripeInstance().webhooks.constructEvent(payload, signature, secret)
256
+ const event = stripe.webhooks.constructEvent(
257
+ payload, signature, process.env.STRIPE_WEBHOOK_SECRET!
258
+ )
247
259
 
248
260
  switch (event.type) {
249
261
  case 'checkout.session.completed':
@@ -659,15 +671,11 @@ export const billingConfig: BillingConfig = {
659
671
  features: ['basic_analytics', 'advanced_analytics', 'api_access'],
660
672
  limits: { team_members: 15, tasks: 1000, api_calls: 100000 },
661
673
 
662
- // Generic price IDs (preferred - works with any provider)
674
+ // Price IDs from your payment provider dashboard
663
675
  providerPriceIds: {
664
676
  monthly: 'price_pro_monthly',
665
677
  yearly: 'price_pro_yearly',
666
678
  },
667
-
668
- // OR Stripe-specific (backward compat)
669
- stripePriceIdMonthly: 'price_pro_monthly',
670
- stripePriceIdYearly: 'price_pro_yearly',
671
679
  },
672
680
  {
673
681
  slug: 'enterprise',
@@ -784,8 +792,8 @@ CREATE TABLE plans (
784
792
  "trialDays" INTEGER DEFAULT 0,
785
793
  features JSONB DEFAULT '[]',
786
794
  limits JSONB DEFAULT '{}',
787
- "stripePriceIdMonthly" TEXT,
788
- "stripePriceIdYearly" TEXT,
795
+ -- Price IDs stored in providerPriceIds (via billing.config.ts)
796
+ -- Legacy: stripePriceIdMonthly/Yearly columns may exist in older migrations but are unused
789
797
  "createdAt" TIMESTAMPTZ DEFAULT NOW(),
790
798
  "updatedAt" TIMESTAMPTZ DEFAULT NOW()
791
799
  );
@@ -829,7 +837,7 @@ POLAR_SERVER=sandbox # 'sandbox' or 'production'
829
837
 
830
838
  ```typescript
831
839
  // NEVER: Import from specific provider in consumers
832
- import { createCheckoutSession } from '.../gateways/stripe' // DEPRECATED
840
+ import { createCheckoutSession } from '.../gateways/stripe' // REMOVED
833
841
 
834
842
  // CORRECT: Use factory
835
843
  import { getBillingGateway } from '.../gateways/factory'
@@ -841,7 +849,7 @@ const session: Stripe.Checkout.Session = ...
841
849
  // CORRECT: Use provider-agnostic types
842
850
  const session: CheckoutSessionResult = ...
843
851
 
844
- // NEVER: Use getStripePriceId (deprecated)
852
+ // NEVER: Use getStripePriceId (removed)
845
853
  PlanService.getStripePriceId('pro', 'monthly')
846
854
 
847
855
  // CORRECT: Use generic getPriceId
@@ -885,7 +893,7 @@ if (current >= limit) return false
885
893
  ### General (all providers)
886
894
 
887
895
  - [ ] Provider selected in `billing.config.ts`
888
- - [ ] Plans defined with price IDs (providerPriceIds or stripe-specific)
896
+ - [ ] Plans defined with price IDs (providerPriceIds)
889
897
  - [ ] Features and limits defined
890
898
  - [ ] Action mappings configured
891
899
  - [ ] Team-based subscription created on team creation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/ai-workflow",
3
- "version": "0.1.0-beta.127",
3
+ "version": "0.1.0-beta.128",
4
4
  "description": "AI workflow templates for NextSpark - Claude Code agents, commands, skills, and multi-editor support",
5
5
  "license": "MIT",
6
6
  "author": "NextSpark <hello@nextspark.dev>",