Skip to main content

Next.js

Integrate the General Wisdom Provider SDK in a Next.js 14 App Router project. The SDK requires browser APIs, so it must run inside a 'use client' component boundary.

Prerequisites

  • Node.js 20+
  • A Next.js 14+ project with the App Router (or create one below)
  • Your Application ID and API Key from the Provider Dashboard

Quick Setup

npx create-next-app@latest my-gw-app --typescript --app
cd my-gw-app
npm install @mission_sciences/provider-sdk
npm run dev

Complete Example

Client Component

The SDK interacts with the DOM and browser APIs, so it must live in a Client Component:

src/app/SessionClient.tsx
'use client';

import { useEffect } from 'react';
import { MarketplaceSDK } from '@mission_sciences/provider-sdk';

const APP_ID = 'YOUR_APP_ID';
const API_KEY = 'YOUR_API_KEY';

export default function SessionClient() {
useEffect(() => {
const sdk = new MarketplaceSDK({
applicationId: APP_ID,
apiKey: API_KEY,
environment: 'production', // 'demo' | 'production'
autoStart: true,
themeMode: 'auto', // 'light' | 'dark' | 'auto'
warningThresholdSeconds: 300, // warn user 5 min before expiry
enableHeartbeat: false, // keep-alive ping
heartbeatIntervalSeconds: 30,
debug: false,
});

sdk.initialize().catch(console.error);

return () => {
sdk.destroy();
};
}, []);

return (
<div>
{/* Your application content */}
</div>
);
}

Server Page

The page itself remains a Server Component. It renders the Client Component that manages the SDK:

src/app/page.tsx
import SessionClient from './SessionClient';

export default function Page() {
return <SessionClient />;
}
Replace placeholders

Swap YOUR_APP_ID and YOUR_API_KEY with the credentials from your Provider Dashboard.

Pattern Breakdown

Why a separate Client Component?

Next.js App Router defaults to Server Components. The SDK requires:

  • window and DOM access (browser-only APIs)
  • useEffect for lifecycle management
  • Client-side JavaScript execution

By isolating the SDK in a dedicated 'use client' component, the rest of your page can benefit from server rendering, streaming, and reduced JavaScript bundle on first load.

Architecture Diagram

┌─────────────────────────────────────────┐
│ page.tsx (Server Component) │
│ - Fetches data, renders layout │
│ - Zero client JS for static portions │
│ │
│ ┌───────────────────────────────────┐ │
│ │ SessionClient.tsx ('use client') │ │
│ │ - MarketplaceSDK lifecycle │ │
│ │ - useEffect mount/unmount │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘

Why not initialize in a layout?

You can place the SDK in layout.tsx to persist across page navigations. However, this keeps the session alive even on pages that do not need it. Prefer placing the SDK in the specific route that requires an active session.

Configuration Options

OptionTypeDefaultDescription
applicationIdstringYour registered application ID
apiKeystringYour API key
environment'demo' | 'production''production'Target environment
autoStartbooleantrueStart session automatically on init
themeMode'light' | 'dark' | 'auto''auto'UI theme preference
warningThresholdSecondsnumber300Seconds before expiry to show warning
enableHeartbeatbooleanfalseEnable keep-alive pings
heartbeatIntervalSecondsnumber30Interval between heartbeat pings
debugbooleanfalseEnable verbose console logging

Common Gotchas

Missing 'use client' directive

Without the directive at the top of the file, Next.js treats the component as a Server Component. Any use of useEffect, useState, or browser globals will fail at build time with:

Error: useState/useEffect only works in Client Components. Add the "use client" directive.

SSR hydration mismatches

The SDK renders UI elements into the DOM after mount. If your component returns different markup on the server vs. the client, you will see hydration warnings. Keep the initial render minimal and let the SDK inject its UI post-mount.

Environment variables

In Next.js, client-accessible env vars must be prefixed with NEXT_PUBLIC_:

.env.local
NEXT_PUBLIC_GW_APP_ID=app_abc123
NEXT_PUBLIC_GW_API_KEY=key_xyz789
const APP_ID = process.env.NEXT_PUBLIC_GW_APP_ID!;
const API_KEY = process.env.NEXT_PUBLIC_GW_API_KEY!;
caution

Environment variables without the NEXT_PUBLIC_ prefix are server-only and will be undefined in Client Components.

Dynamic imports for code splitting

If you want to defer loading the SDK until the component actually mounts (reducing initial bundle size):

src/app/page.tsx
import dynamic from 'next/dynamic';

const SessionClient = dynamic(() => import('./SessionClient'), {
ssr: false,
});

export default function Page() {
return <SessionClient />;
}

Setting ssr: false skips server rendering entirely for this component, which avoids any SSR-related issues with browser APIs.

Next Steps