Documentation

Feature Gating

Go beyond simple paywalls by combining middleware redirects, plan-aware helpers, and usage tracking. Everything lives alongside the Stripe config so you can resell the boilerplate with clear upgrade paths.

Choose Your Strategy

  1. Route-level gating: Middleware checks subscription status and reroutes users away from premium dashboards.
  2. Component-level gating: UI reads the current plan and hides unavailable features.
  3. Usage quotas: UsageRecord entries track metrics such as API calls and storage.

Middleware

In src/middleware.ts, set ENABLE_SUBSCRIPTION_ENFORCEMENT="true" in your.env to block access to /dashboard/analytics, /dashboard/projects, and/dashboard/team unless token.stripeSubscriptionId exists. Customize thePREMIUM_ROUTES array to cover new pages.

Helper Functions

  • getUserPlan(stripeSubscriptionId, stripePriceId): resolves the plan key (FREE/STARTER/GROWTH/SCALE).
  • isPlanFeatureEnabled(plan, feature): boolean switch for toggling UI.
  • hasFeatureAccess(plan, feature, usage): enforce per-plan limits (pass current usage count).
import { getUserPlan, isPlanFeatureEnabled } from "@/lib/stripe";

const plan = getUserPlan(user.stripeSubscriptionId, user.stripePriceId);

if (!isPlanFeatureEnabled(plan, "analytics")) {
  redirect("/dashboard/billing?upgrade=true");
}

Usage Tracking

When you need metered usage, store counts in the UsageRecord model. Each record tracks a feature, the limit, and the current period. Update counts via cron job, queue, or directly inside API routes.

UI Patterns

  • Show plan comparison cards (see src/components/pricing-comparison.tsx).
  • Use toast notifications or inline alerts prompting users to upgrade when they hit limits.
  • Add query params (e.g., ?upgrade=true) so the billing page highlights the relevant plan.