Pricing Plan Management
Pricing plans are the core of the payment system. They define the products users can purchase, prices, payment methods, and benefits. NEXTY.DEV provides a complete management interface and API to manage pricing plans.
Pricing Plan Data Structure
Basic Fields
{
id: string; // UUID, auto-generated
environment: 'test' | 'live'; // Environment: test or production
cardTitle: string; // Card title
cardDescription?: string; // Card description
provider: 'stripe' | 'creem' | 'none'; // Payment provider
isActive: boolean; // Whether activated
isHighlighted: boolean; // Whether highlighted
displayOrder: number; // Display order
}Payment Configuration Fields
Stripe Configuration
{
stripePriceId?: string; // Stripe Price ID
stripeProductId?: string; // Stripe Product ID
stripeCouponId?: string; // Stripe Coupon ID
enableManualInputCoupon: boolean; // Enable manual coupon input entry
}Creem Configuration
{
creemProductId?: string; // Creem Product ID
creemDiscountCode?: string; // Creem discount code
}Payment Type and Interval
{
paymentType: 'one_time' | 'onetime' | 'recurring' | null; // Stripe and Creem have different definitions, boilerplate preserves provider's original definition
recurringInterval: 'month' | 'year' | 'every-month' | 'every-year' | null; // Stripe and Creem have different definitions, boilerplate preserves provider's original definition
}Price Information
{
price?: string; // Actual price (numeric string)
currency?: string; // Currency code (e.g., USD, CNY)
displayPrice?: string; // Display price (e.g., "$10")
originalPrice?: string; // Original price (used to show discount)
priceSuffix?: string; // Price suffix (e.g., "month", "year")
}Multi-language Support (langJsonb)
langJsonb is a JSONB field used to store multi-language content:
{
"en": {
"cardTitle": "Pro Plan",
"cardDescription": "Best for professionals",
"displayPrice": "$29",
"priceSuffix": "month",
"buttonText": "Get Started",
"features": [
{ "description": "Feature 1", "included": true },
{ "description": "Feature 2", "included": true }
]
},
"zh": {
"cardTitle": "专业版",
"cardDescription": "适合专业人士",
"displayPrice": "¥199",
"priceSuffix": "月",
"buttonText": "立即开始",
"features": [
{ "description": "功能 1", "included": true },
{ "description": "功能 2", "included": true }
]
}
}Benefits Configuration (benefitsJsonb)
benefitsJsonb is used to define the benefits granted to users by the plan, especially credits:
{
"oneTimeCredits": 100, // One-time credits (one-time payment)
"monthlyCredits": 50, // Monthly credits (subscription)
"totalMonths": 12 // Total months (annual subscription)
}Features List (features)
The features list is an array used to display the features included in the plan:
[
{
"description": "Unlimited projects",
"included": true,
"bold": false
},
{
"description": "Priority support",
"included": true,
"bold": true
},
{
"description": "Advanced analytics",
"included": false,
"bold": false
}
]Creating a Pricing Plan
Create via Dashboard
- Visit
/dashboard/prices(admin privileges required) - Click the "Create Plan" button
- Fill in plan information:
- Basic Information: Title, description, environment
- Payment Provider: Choose Stripe, Creem, or None
- Payment Configuration: Fill in corresponding configuration based on the selected provider
- Price Information: Price, currency, display price, etc.
- Multi-language Content: Fill in multi-language content in the
langJsonbfield - Benefits Configuration: Configure benefits such as credits in
benefitsJsonb - Features List: Add features included in the plan
Create via API
Use the createPricingPlanAction function:
import { createPricingPlanAction } from '@/actions/prices/admin';
const result = await createPricingPlanAction({
planData: {
environment: 'live',
cardTitle: 'Pro Plan',
provider: 'stripe',
stripePriceId: 'price_xxx',
paymentType: 'recurring',
recurringInterval: 'month',
price: '29.00',
currency: 'USD',
displayPrice: '$29',
priceSuffix: 'month',
isActive: true,
isHighlighted: false,
displayOrder: 1,
langJsonb: {
en: {
cardTitle: 'Pro Plan',
cardDescription: 'Best for professionals',
displayPrice: '$29',
priceSuffix: 'month',
buttonText: 'Get Started',
features: [
{ description: 'Feature 1', included: true }
]
}
},
benefitsJsonb: {
monthlyCredits: 100
},
features: [
{ description: 'Unlimited projects', included: true }
]
},
locale: 'en'
});Updating a Pricing Plan
Update via Dashboard
- Visit
/dashboard/prices - Click on the plan you want to update
- Modify plan information
- Save changes
Update via API
Use the updatePricingPlanAction function:
import { updatePricingPlanAction } from '@/actions/prices/admin';
const result = await updatePricingPlanAction({
id: 'plan-id',
planData: {
displayPrice: '$39', // Only update fields that need modification
isHighlighted: true
},
locale: 'en'
});Deleting a Pricing Plan
Delete via Dashboard
- Visit
/dashboard/prices - Click on the plan you want to delete
- Click the delete button
- Confirm deletion
Delete via API
Use the deletePricingPlanAction function:
import { deletePricingPlanAction } from '@/actions/prices/admin';
const result = await deletePricingPlanAction({
id: 'plan-id',
locale: 'en'
});Querying Pricing Plans
Admin Query for All Plans
import { getAdminPricingPlans } from '@/actions/prices/admin';
const result = await getAdminPricingPlans();
if (result.success) {
const plans = result.data; // All plans (including inactive ones)
}Public Query for Active Plans
import { getPublicPricingPlans } from '@/actions/prices/public';
const result = await getPublicPricingPlans();
if (result.success) {
const plans = result.data; // Returns only active plans
}The system automatically filters based on the current environment (NODE_ENV):
- Production environment: Returns plans with
environment = 'live' - Other environments: Returns plans with
environment = 'test'
Query a Single Plan by ID
import { getPricingPlanById } from '@/actions/prices/admin';
const result = await getPricingPlanById('plan-id');
if (result.success) {
const plan = result.data;
}Displaying Pricing Plans
Using the Pricing Component (Categorized by Type)
The Pricing.tsx component categorizes and displays plans based on payment type:
import Pricing from '@/components/home/Pricing';
export default function PricingPage() {
return <Pricing />;
}The component automatically:
- Categorizes plans into monthly subscriptions, annual subscriptions, and one-time payments
- Uses the Tabs component to switch between different plan types
- Displays corresponding multi-language content based on the current locale
Using the PricingAll Component (Display All Plans)
The PricingAll.tsx component displays all active plans at once:
import PricingAll from '@/components/home/PricingAll';
export default function PricingPage() {
return <PricingAll />;
}Custom Styling
You can also modify the styling of the PricingCardDisplay component to meet your needs.
Multi-language Content Management
Language Codes
The system uses standard language codes (e.g., en, zh, ja) to identify different languages.
Multi-language Fields
The following fields support multi-language:
cardTitlecardDescriptiondisplayPriceoriginalPricepriceSuffixbuttonTexthighlightTextfeatures
Multi-language Fallback Mechanism
If content for the current locale doesn't exist, the system automatically falls back to the default language (usually en):
const localizedPlan =
plan.langJsonb?.[currentLocale] ||
plan.langJsonb?.[DEFAULT_LOCALE] ||
{};Benefits Configuration Best Practices
One-time Payment Benefits
{
"oneTimeCredits": 100
}After purchasing a one-time plan, users immediately receive 100 credits.
Monthly Subscription Benefits
{
"monthlyCredits": 50
}After subscribing to a monthly plan:
- Immediately receive 50 credits
- Reset to 50 credits upon each monthly renewal
Annual Subscription Benefits
{
"monthlyCredits": 50,
"totalMonths": 12
}After subscribing to an annual plan:
- Immediately receive 50 credits
- Receive 50 credits each subsequent month
- Total distribution over 12 months
Payment Provider Configuration
Stripe Configuration Steps
- Create a Product in Stripe Dashboard
- Create a Price (choose one-time or subscription)
- Copy the Price ID
- Fill in
stripePriceIdin the pricing plan
Creem Configuration Steps
- Create a Product in Creem Dashboard
- Copy the Product ID
- Fill in
creemProductIdin the pricing plan
Coupon Configuration
Stripe Coupons
- Create a Coupon in Stripe Dashboard
- Select the created Coupon in the pricing plan, no need to manually fill it in
- For Stripe pricing, if a default Coupon is set, manual coupon modification is not allowed. You can enable manual coupon input entry through the
enableManualInputCouponfield
Creem Discount Codes
- Create a Discount Code in Creem Dashboard
- Fill it into the
creemDiscountCodefield
Frequently Asked Questions
Q: How do I create a free plan?
A: Set provider = 'none'. This way, the plan will be displayed but won't trigger the payment process. You can use the buttonLink field to set a custom link to guide users to the feature usage page.
Q: How do I hide a plan?
A: Set isActive = false. The plan will not be returned in the public API and will not be displayed on the pricing page.
Q: How do I adjust the display order of plans?
A: Modify the displayOrder field. The smaller the number, the higher it appears in the display order.