GROWTH PATTERN

Adding Freemium Gating to Next.js + Lemon Squeezy + Supabase Apps

Free tier users in Next.js + Lemon Squeezy + Supabase apps often hit limits without any automated upgrade prompts or feature blocking.

Next.js + Lemon Squeezy + Supabase

Last updated:

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

Without usage tracking in Supabase, free users can consume unlimited resources without hitting conversion triggers. Lemon Squeezy processes payments but doesn't monitor feature usage, requiring separate tracking implementation.

Standard Next.js + Lemon Squeezy + Supabase Flow vs Optimized Skene Flow

Standard Flow
1

User subscribes via Lemon Squeezy

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 + Lemon Squeezy + Supabase tracks usage in Supabase and integrates with Lemon Squeezy 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 + Lemon Squeezy + 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