Skip to content

iamadhitya1/react-premium-gate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-premium-gate

npm MIT License GitHub Zero Dependencies React

Drop-in React components and hooks for Razorpay subscription paywalls. Built for Indian SaaS apps.

Three exports. Zero runtime dependencies. Works with any React app.

react-premium-gate demo

When to use this

Use react-premium-gate when:

  • You're building a React app that monetizes via Razorpay subscriptions (monthly/yearly plans)
  • You need to gate features or UI behind a Pro plan without writing the plumbing from scratch
  • You're deploying on Vercel and want ready-made serverless API routes for payment flows
  • You need server-side subscription verification, not just client-side localStorage checks

Not the right fit if you're using Stripe, Paddle, or Lemon Squeezy — this library is Razorpay-specific by design.


Why not build it yourself?

A complete Razorpay subscription flow in React requires five moving parts: create the subscription server-side, open the Razorpay SDK, verify the HMAC-SHA256 payment signature, persist subscription state, and re-verify against Razorpay's API on each session load.

react-premium-gate ships all five — as a hook, two components, and three copy-paste Vercel API templates. Add the package, paste the templates, configure env vars, and your paywall is live in under an hour.


What's included

Export Type What it does
<PremiumGate> Component Blocks UI behind a paywall with a customizable CTA
<PricingModal> Component Bottom-sheet pricing modal with plan toggle
usePro Hook Manages Pro status via localStorage + server verification

Plus Vercel API templates in /templates/api/ for Razorpay subscription creation and HMAC payment verification.


Install

npm install react-premium-gate

Usage

usePro

import { usePro } from 'react-premium-gate'

function App() {
  const { isPro, loading, activatePro } = usePro({
    storageKey: 'my_app_sub',           // localStorage key
    verifyEndpoint: '/api/verify-subscription', // optional server check
  })

  if (loading) return null
  return isPro ? <ProContent /> : <FreeContent />
}

<PremiumGate>

import { PremiumGate } from 'react-premium-gate'

<PremiumGate
  onUpgrade={() => setShowModal(true)}
  title="Pro Feature"
  description="Unlock this with a Pro subscription."
  buttonText="Upgrade to Pro — ₹399/mo"
  icon="👑"
  accentColor="#F0B429"
/>

Props

Prop Type Default
onUpgrade function required
title string 'Pro Feature'
description string 'Upgrade to Pro to unlock this feature.'
buttonText string 'Upgrade to Pro'
icon string '👑'
accentColor string '#F0B429'
style object {}

<PricingModal>

import { PricingModal } from 'react-premium-gate'

const PLANS = [
  { id: 'monthly', label: 'Monthly', price: '₹399',   period: '/mo' },
  { id: 'yearly',  label: 'Yearly',  price: '₹2,999', period: '/yr', badge: 'Save 37%' },
]

<PricingModal
  isOpen={showModal}
  onClose={() => setShowModal(false)}
  plans={PLANS}
  onSelectPlan={(planId) => handlePayment(planId)}
  accentColor="#F0B429"
  loading={paymentLoading}
/>

Props

Prop Type Default
isOpen boolean required
onClose function required
plans array []
onSelectPlan function required
title string 'Upgrade to Pro'
subtitle string 'Less than a coffee. Way more value.'
icon string '👑'
accentColor string '#F0B429'
fineText string 'Secure payment · Cancel anytime'
loading boolean false

Razorpay API Templates

Copy the files from /templates/api/ into your Vercel project's api/ folder.

templates/api/
├── create-subscription.js   # Creates Razorpay subscription server-side
├── verify-payment.js        # Verifies HMAC-SHA256 payment signature
└── verify-subscription.js   # Checks if subscription is still active

Required Vercel env vars:

RAZORPAY_KEY_ID=rzp_live_xxx
RAZORPAY_KEY_SECRET=your_secret
RAZORPAY_PLAN_MONTHLY=plan_xxx
RAZORPAY_PLAN_YEARLY=plan_xxx

Full Example

import { useState } from 'react'
import { usePro, PremiumGate, PricingModal } from 'react-premium-gate'

const PLANS = [
  { id: 'monthly', price: '₹399',   period: '/mo' },
  { id: 'yearly',  price: '₹2,999', period: '/yr', badge: 'Save 37%' },
]

export default function App() {
  const { isPro, activatePro } = usePro({
    storageKey: 'my_app_sub',
    verifyEndpoint: '/api/verify-subscription',
  })
  const [showModal, setShowModal] = useState(false)
  const [loading, setLoading] = useState(false)

  const handlePayment = async (planId) => {
    setLoading(true)
    const res = await fetch(`/api/create-subscription?plan=${planId}`)
    const { subscriptionId } = await res.json()

    const rzp = new window.Razorpay({
      key: process.env.VITE_RAZORPAY_KEY_ID,
      subscription_id: subscriptionId,
      handler: async (response) => {
        const verify = await fetch('/api/verify-payment', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(response),
        })
        const { valid, subscriptionId: subId } = await verify.json()
        if (valid) { activatePro(subId); setShowModal(false) }
        setLoading(false)
      },
    })
    rzp.open()
  }

  return (
    <>
      {!isPro && (
        <PremiumGate
          onUpgrade={() => setShowModal(true)}
          title="Analytics — Pro only"
          description="Unlock detailed charts and AI insights."
          buttonText="Upgrade to Pro"
        />
      )}

      <PricingModal
        isOpen={showModal}
        onClose={() => setShowModal(false)}
        plans={PLANS}
        onSelectPlan={handlePayment}
        loading={loading}
      />
    </>
  )
}

Author

M. Adhitya — Builder, Rewrite Labs · Newsletter

License

MIT © 2025 M. Adhitya

Built at Rewrite Labs · Used in production across the Rewrite Labs app suite.

About

No description or website provided.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors