GROWTH PATTERN

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

Next.js + Stripe + Supabase manages subscriptions well, but free users can access all features without hitting conversion triggers because usage isn't tracked.

Next.js + Stripe + Supabase

Last updated:

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

While Stripe processes payments reliably, webhooks fire for payment events (invoice.paid, customer.subscription.deleted) but don't track user activity in your app. There's no connection between Stripe subscription data and usage tracking.

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

Standard Flow
1

User subscribes via Stripe

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., 5 team members invited)

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

This Skene Prompt installs usage tracking that correlates Supabase feature usage with Stripe subscription tiers. When free users hit limits (like 100 API calls), it automatically blocks features and sends upgrade prompts.

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 + Stripe + 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