GROWTH PATTERN

Adding Freemium Gating to Next.js + Paddle + Supabase Apps

While Next.js + Paddle + Supabase integrates Paddle for billing, there's no automated system to enforce usage limits or prompt upgrades.

Next.js + Paddle + Supabase

Last updated:

What's Missing in Standard Next.js + Paddle + Supabase Architecture

Paddle handles subscriptions, but usage tracking is separate. You'd need to manually track feature usage in Supabase and correlate it with Paddle subscription status. No automatic usage-to-billing connection.

Standard Next.js + Paddle + Supabase Flow vs Optimized Skene Flow

Standard Flow
1

User subscribes via Paddle

2

Subscription status stored in Supabase

3

Features accessible but no usage limits enforced

Skene Flow
1

Track usage in Supabase 'subscriptions' and 'usage' tables

2

Detect when free tier user hits limit (e.g., 100 API calls)

3

Block feature access and trigger upgrade prompt email

4

Track conversion from free to paid

Visual comparison of the flows:

Loading diagram...

How Skene Fixes This

The Skene infrastructure for Next.js + Paddle + Supabase tracks usage in Supabase and integrates with Paddle to enforce subscription limits. It automatically gates features and sends upgrade prompts when free tier limits are reached.

Implementation Comparison

Using Skene Infrastructure

Install via Prompt

cursor.mdc
@task: Initialize Skene.
@action: Analyze my local code, validating subscription via `npx skene login`, and generate `skene.config.ts` to implement the Freemium Gating pattern for Next.js + Paddle + Supabase.

Copy Skene Prompt for Cursor

Generated skene.config.ts

skene.config.ts
// skene.config.ts - The Automated Way
import { defineLoop } from '@skene/sdk';

export default defineLoop({
  type: 'freemium',
  opinion: 'Enforce usage limits for free tier users and trigger upgrade prompts',
  steps: [
    {
      trigger: {
        type: 'api',
        endpoint: '/api/features/*',
        method: 'POST'
      },
      condition: {
        type: 'usage',
        limit: {
          free: 100,
          paid: Infinity
        },
        period: '30d'
      },
      action: {
        type: 'block',
        message: 'You've reached your free tier limit. Upgrade to continue.',
        upgradePrompt: {
          type: 'email',
          provider: 'resend',
          template: 'upgrade_prompt'
        }
      }
    }
  ],
  recovery: {
    retries: 0 // No retries for blocking actions
  }
});

Frequently asked questions