Menu

Pricing Groups Feature Guide

Feature Overview

Pricing groups is a flexible pricing management feature provided by the NEXTY.DEV boilerplate, allowing you to organize and display pricing plans according to custom groups. This provides great flexibility for displaying pricing information on frontend pages—whether you need to display pricing information in different ways across multiple pages and components, you can easily achieve it.

Core Advantages

  • Flexible Grouping: Custom group identifiers (slug), organize pricing plans as needed
  • High Frontend Freedom: Filter and display by group, adapt to various page layouts

Data Structure

Groups Table (pricing_plan_groups)

Groups use slug as the primary key, simplifying queries and associations:

lib/db/schema.ts
export const pricingPlanGroups = pgTable('pricing_plan_groups', {
  slug: varchar('slug', { length: 100 }).primaryKey(),
  createdAt: timestamp('created_at', { withTimezone: true })
    .defaultNow()
    .notNull(),
})

Group Field in Pricing Plans Table

Each pricing plan is associated with a group through the groupSlug field:

lib/db/schema.ts
// pricingPlans table
groupSlug: varchar('group_slug', { length: 100 })
  .references(() => pricingPlanGroups.slug, { onDelete: 'restrict' })
  .default('default')
  .notNull(),

Note: Groups use foreign key constraints. You must remove all pricing plans under a group before deleting the group.

Admin Dashboard Operations

1. Group Management Entry

On the pricing management page (/dashboard/prices) in the admin dashboard, click the "Manage Groups" button to open the group management dialog.

2. Create Group

In the group management dialog:

  1. Enter the group identifier (slug) in the input field
  2. Slug can only contain lowercase letters, numbers, and hyphens (e.g., annual, monthly, enterprise-plans)
  3. Click the "+" button or press Enter to create the group
pricing-groups-create

3. Delete Group

In the group management dialog:

  • Each group displays the number of pricing plans under it on the right
  • Only groups with no associated pricing plans can be deleted
  • The default group is a system-reserved group and cannot be deleted

4. Group List Display

In the table on the pricing plans list page (/dashboard/prices), the Group column displays the group each pricing plan belongs to, making it easy to quickly view and filter.

Assign Groups to Pricing Plans

Select Group When Creating Pricing Plan

In the create pricing plan form, the Group field allows you to:

  1. Select an existing group from the dropdown list
  2. Directly enter a new group identifier and create it quickly

Modify Group When Editing Pricing Plan

When editing a pricing plan, you can change its group at any time, and the system will take effect immediately.

pricing-groups-edit

Frontend Display Components

NEXTY.DEV provides three out-of-the-box pricing display components to meet different scenario needs:

Display pricing cards grouped by groupSlug, with Tab switching support.

This is the most flexible display method, suitable for most SaaS product pricing pages.

import { PricingByGroup } from "@/components/pricing";
 
export default function PricingPage() {
  return <PricingByGroup />;
}

Default Behavior:

  • Filters plans with groupSlug of annual, monthly, onetime
  • Displays in Tab switching format
  • Prioritizes displaying the annual (annual) tab
  • Automatically hides tabs with no plans

Custom Group Display:

If you use custom groups (such as basic, pro, enterprise), simply modify the frontend component logic to filter pricing plans by group:

// Example: Filter by custom groups
const basicPlans = allPlans.filter((plan) => plan.groupSlug === "basic");
const proPlans = allPlans.filter((plan) => plan.groupSlug === "pro");
const enterprisePlans = allPlans.filter((plan) => plan.groupSlug === "enterprise");

2. PricingAll

Display all active pricing cards at once, without grouping.

Suitable for scenarios with fewer pricing plans or when you need to display all options side by side.

import { PricingAll } from "@/components/pricing";
 
export default function SimplePricingPage() {
  return <PricingAll />;
}

Features:

  • Displays all pricing plans with isActive = true
  • Automatically adjusts grid columns based on the number of plans
  • No Tab switching, suitable for simple pricing displays

3. PricingByPaymentType

Automatically group and display by payment type (monthly/annual/one-time).

Similar Tab switching experience to PricingByGroup, but the grouping logic is based on paymentType and recurringInterval fields, rather than groupSlug.

import { PricingByPaymentType } from "@/components/pricing";
 
export default function PaymentTypePricingPage() {
  return <PricingByPaymentType />;
}

Automatic Classification Logic:

  • Monthly: paymentType is recurring and recurringInterval is month/every-month
  • Annual: paymentType is recurring and recurringInterval is year/every-year
  • One-time: paymentType is one_time/onetime

Component Comparison

ComponentGrouping BasisDisplay MethodRecommended Scenario
PricingByGroupgroupSlug fieldTab switchingCustom groups, flexible display control
PricingAllNo groupingDisplay allFewer plans, simple pages
PricingByPaymentTypePayment type fieldsTab switchingDisplay by payment cycle
  • Components: components/pricing/PricingByGroup.tsx, PricingAll.tsx, PricingByPaymentType.tsx
  • Server Actions: actions/prices/groups.ts, actions/prices/public.ts
  • Database Schema: lib/db/schema.ts
  • Type Definitions: types/pricing.ts
  • State Management: stores/pricingGroupStore.ts
  • Admin Pages: app/[locale]/(protected)/dashboard/(admin)/prices/