Billing

Plans & Products

Managing subscription plans.

Nuda Kit stores billing plans in the database and links them to Stripe products. This allows you to display plans in your app and create checkout sessions dynamically.

Overview

The plans system provides:

Database Plans

Plans stored locally for fast queries.

Stripe Integration

Each plan links to a Stripe Price ID.

Multiple Modes

Support for subscriptions and one-time payments.

Active/Inactive

Toggle plans without deleting them.

Plan Model

Plans are stored in the plans table:

ColumnTypeDescription
idIntegerPrimary key
nameStringDisplay name (e.g., "Pro")
keyStringUnique identifier (e.g., "pro")
stripe_price_idStringStripe Price ID (price_xxx)
modeEnumsubscription or payment
is_activeBooleanWhether plan is available
created_atTimestampCreation date
updated_atTimestampLast update

Plan Modes

ModeDescriptionUse Case
subscriptionRecurring billingMonthly/yearly plans
paymentOne-time paymentLifetime deals

Setting Up Plans

Step 1: Create Products in Stripe

  1. Go to Stripe Dashboard → Products
  2. Click Add product
  3. Enter product details:
    • Name: "Pro Plan"
    • Description: Optional
  4. Add a price:
    • Recurring or One-time
    • Amount and currency
  5. Copy the Price ID (starts with price_)

Step 2: Add Plans to Database

Run the plan seeder or create plans manually:

node ace db:seed --files=database/seeders/plan_seeder.ts

The seeder creates example plans — update the stripePriceId values with your actual Stripe Price IDs.

Step 3: Update Plan Seeder

Edit database/seeders/plan_seeder.ts with your plans:

FieldExampleDescription
name"Pro"Display name
key"pro"Unique slug for API
stripePriceId"price_1234..."From Stripe Dashboard
mode"subscription"Payment type
isActivetrueAvailable for purchase

API Endpoint

MethodEndpointAuthDescription
GET/plansNoList all active plans

Response:

{
  "data": {
    "plans": [
      {
        "id": 1,
        "name": "Pro",
        "key": "pro",
        "stripePriceId": "price_xxx",
        "mode": "subscription",
        "isActive": true
      }
    ]
  }
}
The /plans endpoint is public (no authentication required) so it can be used on landing pages.

What's Included

Backend

  • Plan Model — Full model with modes and active flag
  • GetAllPlansController — Returns active plans
  • Plan Seeder — Example plans ready to customize
  • Database migration with indexes

Frontend

  • Plan Cards — Display plans with pricing
  • Billing Page — Plan selection UI
  • Landing Page Pricing — Public pricing section
  • usePlanQuery — TanStack Query composable

Example Plans

Nuda Kit includes two example plans:

PlanKeyModeDescription
ProproSubscriptionStandard paid plan
UltimateultimateSubscriptionPremium plan

Customize these or add more plans as needed.


Adding a New Plan

  1. Create product in Stripe and copy the Price ID
  2. Add to seeder or insert directly:
# Using AdonisJS REPL
node ace repl

# In REPL:
> const Plan = (await import('#models/plan')).default
> await Plan.create({
    name: 'Enterprise',
    key: 'enterprise',
    stripePriceId: 'price_xxx',
    mode: 'subscription',
    isActive: true
  })
  1. Update frontend pricing display if needed

Deactivating a Plan

To hide a plan without deleting it:

# Using AdonisJS REPL
node ace repl

> const Plan = (await import('#models/plan')).default
> const plan = await Plan.findByOrFail('key', 'old-plan')
> plan.isActive = false
> await plan.save()

Deactivated plans:

  • Won't appear in /plans response
  • Won't be available for new checkouts
  • Existing subscriptions are unaffected

Pricing Display

The frontend fetches plans and displays pricing:

ComponentLocationDescription
Pricing SectionLanding pagePublic pricing cards
Plan CardsBilling settingsUpgrade options
PlanItemComponentsReusable plan display

Pricing, features, and styling are customizable in the frontend components.


Best Practices

PracticeDescription
Use keysReference plans by key, not ID
Keep Stripe in syncUpdate database when changing Stripe
Soft deactivateSet isActive: false instead of deleting
Test mode firstCreate plans in Stripe test mode

Resources