Installation
npm install @encorekit/web-sdk
Why Next.js is Different
Next.js uses Server Components by default in the App Router, which cannot run client-side code like SDK initialization. You need to create a Client Component wrapper that initializes the SDK and wraps your app.
Complete Setup Example
Step 1: Create the EncoreProvider Component
components/EncoreProvider.tsx
'use client';
import { useEffect } from 'react';
import Encore from '@encorekit/web-sdk';
interface EncoreProviderProps {
apiKey: string;
environment?: 'production' | 'development';
logLevel?: 'none' | 'debug';
children: React.ReactNode;
}
export function EncoreProvider({
apiKey,
environment = 'production',
logLevel = 'none',
children
}: EncoreProviderProps) {
useEffect(() => {
// Generate or retrieve userId from localStorage
const storageKey = 'encore_user_id';
let userId = localStorage.getItem(storageKey);
if (!userId) {
userId = 'user_' + Math.random().toString(36).substring(2, 15);
localStorage.setItem(storageKey, userId);
}
Encore.configure({
apiKey,
userId,
environment,
logLevel,
});
}, [apiKey, environment, logLevel]);
return <>{children}</>;
}
Step 2: Use in Root Layout
import type { Metadata } from 'next';
import { EncoreProvider } from '@/components/EncoreProvider';
import './globals.css';
export const metadata: Metadata = {
title: 'My App',
description: 'My app with Encore SDK',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<EncoreProvider
apiKey={process.env.NEXT_PUBLIC_ENCORE_API_KEY!}
environment={process.env.NODE_ENV === 'production' ? 'production' : 'development'}
logLevel={process.env.NODE_ENV === 'development' ? 'debug' : 'none'}
>
{children}
</EncoreProvider>
</body>
</html>
);
}
Step 3: Use Encore in Page Components
'use client';
import { useState } from 'react';
import Encore from '@encorekit/web-sdk';
export default function PricingPage() {
const [loading, setLoading] = useState(false);
const handleUnlock = async () => {
setLoading(true);
try {
const result = await Encore.presentOffer();
if (result.granted) {
console.log('Offer granted:', result.entitlement);
// Handle user completed Encore offer
} else {
console.log('Offer declined:', result.reason);
}
} finally {
setLoading(false);
}
};
return (
<div>
<h1>Premium Feature</h1>
<button onClick={handleUnlock} disabled={loading}>
{loading ? 'Loading...' : 'Unlock with Offer'}
</button>
</div>
);
}
Environment Variables
Create a .env.local file:
NEXT_PUBLIC_ENCORE_API_KEY=your-api-key-here
Next.js requires the NEXT_PUBLIC_ prefix for environment variables that need to be accessible in client components.
Server-Side API Route for Validation
app/api/offer-granted/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { userId, entitlement } = await request.json();
try {
// Validate with Encore backend
const response = await fetch('https://svc.joinyaw.com/api/v1/entitlements/validate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ENCORE_SECRET_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ userId, entitlement })
});
const data = await response.json();
if (data.isActive) {
// Grant access in your database
// await grantPremiumAccess(userId);
return NextResponse.json({ success: true });
}
return NextResponse.json({ success: false }, { status: 403 });
} catch (error) {
console.error('Validation error:', error);
return NextResponse.json({ error: 'Validation failed' }, { status: 500 });
}
}
Store ENCORE_SECRET_KEY in .env.local (without the NEXT_PUBLIC_ prefix) so it’s only available on the server.
Next.js Patterns
Pages Router (Legacy)
If you’re using the Pages Router instead of App Router:
import type { AppProps } from 'next/app';
import { useEffect } from 'react';
import Encore from '@encorekit/web-sdk';
export default function App({ Component, pageProps }: AppProps) {
useEffect(() => {
const storageKey = 'encore_user_id';
let userId = localStorage.getItem(storageKey);
if (!userId) {
userId = 'user_' + Math.random().toString(36).substring(2, 15);
localStorage.setItem(storageKey, userId);
}
Encore.configure({
apiKey: process.env.NEXT_PUBLIC_ENCORE_API_KEY!,
userId,
environment: 'production',
});
}, []);
return <Component {...pageProps} />;
}
Working Example
Complete working example: See the Next.js demo app for a full implementation with pricing page and offer presentation.
Next Steps