Skip to main content

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

app/layout.tsx
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

app/page.tsx
'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:
pages/_app.tsx
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