One of the most powerful paradigms introduced in recent web development is moving authorization logic to the server edge. In this tutorial, we will demonstrate how to secure a Next.js 15 App Router route using the VREN SDK, ensuring that only users with an active on-chain subscription can access your premium content.
The Architecture
Traditional Web3 applications gate content on the client side. The user connects their wallet, the React component reads the blockchain state, and if the user holds the token, the UI unlocks. The flaw here is obvious: a malicious user can simply inspect the network requests, bypass the client-side boolean, and access the raw data.
With Next.js 15 Server Components, we verify the blockchain state on the server before the HTML is ever generated.
Implementation
First, install the VREN SDK and your preferred wallet connection library (e.g., wagmi). When the user connects their wallet on the client, you must set a secure HTTP-only cookie containing their wallet address.
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { Vren } from '@vren/sdk';
const vren = new Vren({
appId: process.env.VREN_APP_ID!,
network: "polygon"
});
export async function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/dashboard')) {
const wallet = request.cookies.get('user_wallet')?.value;
if (!wallet) {
return NextResponse.redirect(new URL('/login', request.url));
}
// Verify on-chain subscription state
const result = await vren.gate('pro', wallet as `0x${string}`);
if (!result.access) {
return NextResponse.redirect(new URL('/pricing', request.url));
}
}
return NextResponse.next();
}Because `vren.gate()` executes at the middleware layer using viem under the hood, the check happens in milliseconds. The unauthorized user is redirected to the `/pricing` page before the `/dashboard` route even begins to render.
Optimizing RPC Calls
If your application experiences high traffic, executing an RPC call on every single page navigation will quickly exhaust your Alchemy or Infura rate limits. To solve this, we recommend caching the result of the `vren.gate()` check in Redis (e.g., via Upstash) with a Time-To-Live (TTL) of 5 minutes.
The VREN webhook system can then be used to actively invalidate this Redis cache the moment a user cancels or their subscription expires on-chain, creating a perfectly synchronized, highly performant gating system.
