SkyeGate

If their wallet meets the condition, they see the content. If it doesn't, they don't.

SkyeGate Pro for Vercel

Drop a wallet gate into any Next.js app. Bring your own wallet stack — wagmi, RainbowKit, ConnectKit, Privy, whatever you already use. @skyemeta/skyegate handles the gating layer. Four condition types, 32 blockchains, server-side JWT validation, same SKYE license key as the WordPress plugin.

npm install @skyemeta/skyegate

Powered by The Insumer Model™ wallet verification engine.

Five Minutes to a Wallet Gate

Three steps. No configuration. No magic.

1. Install

npm install @skyemeta/skyegate

Peer dep: react ^18 (only if you import the React entry). Runtime dep: jose. Zero wallet libs — you use your own.

2. Set your license key

# .env.local
NEXT_PUBLIC_SKYE_LICENSE_KEY=SKYE-XXXX-XXXX-XXXX

Your SKYE license key is safe to expose. The proxy auto-binds it to your production domain on first use; other apexes are rejected.

3. Drop in <GatedContent />

Wrap whatever you want gated. The component handles the verify call, status transitions, and conditional rendering. Server-side validation goes in a route handler.

app/page.tsx
'use client';
import { useAccount } from 'wagmi';
import { GatedContent } from '@skyemeta/skyegate/react';

export default function Page() {
  const { address } = useAccount();
  return (
    <GatedContent
      address={address}
      conditions={[{ type: 'farcaster_id' }]}
      licenseKey={process.env.NEXT_PUBLIC_SKYE_LICENSE_KEY!}
      loading={<p>Verifying…</p>}
      fallback={<p>Connect a Farcaster-linked wallet.</p>}
      onPass={async (jwt) => {
        const res = await fetch('/api/gated', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ jwt }),
        });
        // render res.json().secret …
      }}
    >
      <p>Welcome, Farcaster user.</p>
    </GatedContent>
  );
}
app/api/gated/route.ts
import { validateContentToken } from '@skyemeta/skyegate';

export const runtime = 'nodejs';

export async function POST(req: Request) {
  const { jwt } = await req.json();
  const result = await validateContentToken(jwt, {
    expectedConditions: [{ type: 'farcaster_id' }],
  });
  if (!result.pass) {
    return Response.json(
      { error: result.error },
      { status: 403 },
    );
  }
  return Response.json({
    secret: 'Real gated content here.',
  });
}

Clone the full starter app →

Four Condition Types

Same vocabulary as the WordPress plugin. Stack up to 10 per gate; pass=true requires all of them to be met.

Token balance

ERC-20, SPL, native ETH/SOL/MATIC, XRPL trust line tokens. 32 chains.

{
  type: 'token_balance',
  contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  chainId: 1,
  threshold: 100,
  decimals: 6,         // USDC
}

NFT ownership

ERC-721, ERC-1155, Solana SPL NFTs. Match by collection contract.

{
  type: 'nft_ownership',
  contractAddress: '0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85',
  chainId: 1,          // ENS .eth
}

EAS attestation

Ethereum Attestation Service templates — Coinbase Verified, Gitcoin Passport, more.

{
  type: 'eas_attestation',
  template: 'coinbase_verified_account',
}

Farcaster identity

Wallet linked to a Farcaster account (FID present). New in Pro 1.4.0.

{
  type: 'farcaster_id',
}

Match the same conditions in validateContentToken's expectedConditions on the server side — that's how a JWT earned for one route can't unlock another.

API at a Glance

verifyConditions(params)

Promise<{ pass, jwt, raw, error? }>

Low-level imperative call. The React hook + component use this internally; reach for it in non-React contexts (server actions, API routes, Node scripts).

Required params: address, conditions[], licenseKey. Optional: walletType ('evm' | 'solana'), endpoint, domain.

validateContentToken(jwt, options?)

Promise<{ valid, pass, payload?, error? }>

Server-side JWT validation. Verifies the ECDSA P-256 signature against InsumerAPI's JWKS, checks issuer + expiry via jose, and (if you pass expectedConditions) confirms the signed conditions match what the route requires.

Trust the math, not a company — including us. Every result is independently verifiable by any third party using the public JWKS.

useSkyeGate(options)

{ status, pass, jwt, error, refetch }

React hook. Same options as verifyConditions, plus enabled to gate the call. status cycles through 'idle' → 'verifying' → 'pass' | 'fail' | 'error'.

<GatedContent />

JSX.Element

Declarative wrapper. Renders children on pass, fallback otherwise, loading while verifying. Optional onPass(jwt) callback fires once when the gate first passes — use it to fetch gated content from your server.

Full API reference on GitHub →

How It Works

your Next.js app
  ↓ verifyConditions(address, conditions, licenseKey)
  ↓
skyemeta.com/api/verify    ← SkyeMeta proxy validates SKYE key + domain
  ↓
api.insumermodel.com       ← InsumerAPI returns a signed boolean
  ↓                       (no balances exposed)
JWT signed with ECDSA P-256
  ↓ POSTed to your server
  ↓
validateContentToken(jwt)  ← jose + JWKS, signature + issuer + expiry +
  ↓                       condition match
gated content delivered

The wallet's actual balances never reach your server or your customers — only the signed yes-or-no on whether the condition was met. Trust the math, not a company — including us.

One License, One Site — With Sensible Defaults

Auto-bind on first production use

Your license has no domain at first. The first call from a real apex (e.g. myapp.com) auto-binds the license to that apex. Subsequent calls from myapp.com and any subdomain (staging.myapp.com, preview.myapp.com, app.myapp.com) are accepted.

Calls from a different apex are rejected with License bound to myapp.com.

Dev / preview hosts skip the bind

localhost, 127.0.0.1, *.vercel.app, and *.local verify normally but never bind the license. Vercel preview deploys, local dev, and .local hostnames don't burn your production bind.

Treat your license key as you would any per-domain credential. To move a key to a different production apex, contact support.

WordPress Plugin vs Vercel SDK

WordPress plugin Vercel SDK (this page)
DistributionDirect .zip from skyemeta.comnpm install @skyemeta/skyegate
StackPHP + bundled JSTypeScript / React
Wallet connectBundled, multi-walletBring your own (wagmi, RainbowKit, ConnectKit, Privy)
License keySame SKYE keySame SKYE key
ConditionsAll 4 types, up to 10 stackedAll 4 types, up to 10 stacked
Chains3232
SourceClosed (proprietary plugin)Open (MIT, GitHub)

One Pro license. Pick the channel that matches your stack — or use both, on the same key, no extra cost.

Get a Key

SkyeGate Pro is $49/mo or $350/yr per domain — same key works on the WordPress plugin and this SDK.

$350/yr — Save 40% or subscribe monthly

Comparison, FAQ, and the WordPress option at skyemeta.com/skyegate.

Same Verification Engine. Different Use Cases.

Ready to gate some content?

Bring your own wallet stack. We bring the gating layer.