Plans Config
Your pricing tiers — free, premium, and beyond.
File: config/plans.config.ts
This file defines the plans shown on the /pricing page and in the submission flow. Each paid plan must have a matching Stripe Price ID — you create prices in Stripe, then paste the ID into an env var.

The default setup
Two plans: Standard (free, $0) and Premium ($15 one-time).
export const plansConfig: PlansConfig = {
currency: 'USD',
plans: [
{
id: 'standard',
name: 'Standard',
price: 0,
type: 'free',
description: 'Free listing with basic features',
priceId: null,
cta: 'Get Started Free',
features: {
homepage_duration: 30,
guaranteed_backlinks: 0,
premium_badge: false,
skip_queue: false,
social_promotion: false,
priority_support: false,
},
},
{
id: 'premium',
name: 'Premium',
price: 15,
type: 'one-time',
description: 'Premium listing with priority placement',
priceId: process.env.STRIPE_PRICE_ID_PREMIUM || null,
cta: 'Go Premium',
highlighted: true,
features: {
homepage_duration: 7,
guaranteed_backlinks: 3,
premium_badge: true,
skip_queue: true,
social_promotion: true,
priority_support: true,
detailed_analytics: true,
founder_outreach: true,
},
},
],
};Fields
| Field | Type | What it does |
|---|---|---|
id | string | Internal ID. Used by API + getPlan('id'). |
name | string | Display name on the pricing card. |
price | number | Price in your currency (dollars, not cents). |
type | 'free' | 'one-time' | 'recurring' | Billing mode. |
description | string | One-line description under the plan name. |
priceId | string | null | The Stripe Price ID — from STRIPE_PRICE_ID_* env. |
cta | string | Button label. |
highlighted | boolean? | Adds the "most popular" highlight. |
features | object | Arbitrary keys describing what the plan includes. Used for the feature-comparison table. |
Pricing page preview

Adding a new plan
1. Create a Price in Stripe
- Stripe Dashboard → Products → Add product
- Name it ("Pro", "Lifetime", whatever)
- Set the price and type (one-time or recurring)
- Save → copy the Price ID (starts with
price_)
See Payments for the full Stripe workflow.
2. Add the env var
Append to .env.local:
STRIPE_PRICE_ID_PRO=price_1ABCdef...3. Add the plan object
plans: [
// ...existing plans,
{
id: 'pro',
name: 'Pro',
price: 29,
type: 'one-time',
description: 'Everything in Premium plus...',
priceId: process.env.STRIPE_PRICE_ID_PRO || null,
cta: 'Get Pro',
features: {
homepage_duration: 14,
guaranteed_backlinks: 10,
premium_badge: true,
skip_queue: true,
social_promotion: true,
priority_support: true,
dedicated_account_manager: true,
},
},
],4. Restart the dev server
Env var changes don't hot-reload. Stop (Ctrl+C) and run pnpm dev again.
Or, design the pricing with AI
Update config/plans.config.ts for my directory about {your niche}.
Business model:
- Free tier: {what free users get / limits}
- Paid tier(s): {e.g. "$15 one-time Premium with priority placement and guaranteed backlinks"}
- Currency: {USD|EUR|RUB|...}
For each plan, pick sensible values in the features object (homepage_duration, guaranteed_backlinks, premium_badge, skip_queue, social_promotion, priority_support, etc.) that match the pitch.
For paid plans, reference process.env.STRIPE_PRICE_ID_\{PLAN_ID\} on priceId — don't hardcode IDs. List the env vars I need to add afterwards.
Preserve the PlansConfig type. Don't touch helper functions.
Helper functions
The config also exports:
import { getPlan, getFreePlan, getPaidPlans } from '@/config/plans.config';
getPlan('premium'); // → the Premium plan object, or undefined
getFreePlan(); // → first plan with price 0
getPaidPlans(); // → all plans with price > 0Going free-only
If you don't want to collect money at all:
- Remove the
premiumplan (keep onlystandard) - In
config/payments.config.ts, setprovider: 'none'
The /pricing page will show only the free plan, and the Stripe integration becomes inert.