Configuration
SDK Options
interface SDKOptions {
// Required
applicationId: string; // Your registered app ID
apiKey: string; // Organization API key (gwsk_...)
jwksUri?: string; // JWKS endpoint URL (optional if environment is set)
// Environment (auto-resolves endpoints)
environment?: 'production' | 'demo' | 'dev';
// Endpoints (auto-resolved when environment is set)
apiEndpoint?: string; // SDK API endpoint
// Optional hooks
hooks?: {
onSessionStart?: (context: SessionStartContext) => Promise<void>;
onSessionEnd?: (context: SessionEndContext) => Promise<void>;
onSessionWarning?: (context: SessionWarningContext) => Promise<void>;
onSessionExtend?: (context: SessionExtendContext) => Promise<void>;
};
// Session controls configuration
sessionControls?: SessionControlsConfig;
// Other optional settings
marketplaceUrl?: string; // Redirect URL after session end
warningThresholdMinutes?: number; // Warning threshold (default: 5)
debug?: boolean; // Enable debug logging
pauseWhenHidden?: boolean; // Auto-pause when tab hidden
validateJWTBackend?: boolean; // Use backend validation
validationEndpoint?: string; // Backend validation URL
heartbeat?: {
enabled: boolean;
intervalSeconds: number;
endpoint: string;
};
}
Environment Configuration
Development
const config = {
applicationId: 'test-app',
apiKey: 'gwsk_YOUR_API_KEY_HERE',
jwksUri: 'http://localhost:3000/.well-known/jwks.json',
marketplaceUrl: 'http://localhost:8080',
debug: true,
};
Production
const config = {
applicationId: process.env.MARKETPLACE_APP_ID,
apiKey: process.env.MARKETPLACE_API_KEY,
jwksUri: 'https://api.generalwisdom.com/.well-known/jwks.json',
marketplaceUrl: 'https://platform.generalwisdom.com',
debug: false,
};
Framework Integration Patterns
Vanilla JavaScript
import MarketplaceSDK from '@mission_sciences/provider-sdk';
const sdk = new MarketplaceSDK({
applicationId: 'my-vanilla-app',
apiKey: 'gwsk_YOUR_API_KEY_HERE',
jwksUri: 'https://api.generalwisdom.com/.well-known/jwks.json',
hooks: {
onSessionStart: async (context) => {
localStorage.setItem('marketplace_user', JSON.stringify({
userId: context.userId,
email: context.email,
sessionId: context.sessionId,
expiresAt: context.expiresAt,
}));
document.getElementById('login-section').style.display = 'none';
document.getElementById('app-section').style.display = 'block';
document.getElementById('user-email').textContent = context.email;
},
onSessionEnd: async (context) => {
localStorage.removeItem('marketplace_user');
document.getElementById('login-section').style.display = 'block';
document.getElementById('app-section').style.display = 'none';
},
},
});
sdk.initialize().then(() => {
console.log('Marketplace SDK initialized');
});
window.marketplaceSDK = sdk;
Vue
import { ref, onMounted, onUnmounted } from 'vue';
import MarketplaceSDK from '@mission_sciences/provider-sdk';
import type { SessionStartContext, SessionEndContext } from '@mission_sciences/provider-sdk';
export function useMarketplaceSession() {
const sdk = ref<MarketplaceSDK | null>(null);
const session = ref({
isActive: false,
userId: '',
email: '',
expiresAt: 0,
});
onMounted(async () => {
const marketplaceSDK = new MarketplaceSDK({
applicationId: 'my-vue-app',
apiKey: 'gwsk_YOUR_API_KEY_HERE',
jwksUri: 'https://api.generalwisdom.com/.well-known/jwks.json',
hooks: {
onSessionStart: async (context: SessionStartContext) => {
session.value = {
isActive: true,
userId: context.userId,
email: context.email || '',
expiresAt: context.expiresAt,
};
await authenticateUser(context);
},
onSessionEnd: async (context: SessionEndContext) => {
session.value = {
isActive: false,
userId: '',
email: '',
expiresAt: 0,
};
await clearAuth();
},
},
});
await marketplaceSDK.initialize();
sdk.value = marketplaceSDK;
});
onUnmounted(() => {
sdk.value?.destroy();
});
return { sdk, session };
}
Chrome Extensions
Background Script:
import MarketplaceSDK from '@mission_sciences/provider-sdk';
const sdk = new MarketplaceSDK({
applicationId: 'my-chrome-extension',
apiKey: 'gwsk_YOUR_API_KEY_HERE',
jwksUri: 'https://api.generalwisdom.com/.well-known/jwks.json',
hooks: {
onSessionStart: async (context) => {
await chrome.storage.local.set({
marketplace_session: {
userId: context.userId,
email: context.email,
expiresAt: context.expiresAt,
jwt: context.jwt,
},
});
chrome.runtime.sendMessage({
type: 'MARKETPLACE_SESSION_START',
session: context,
});
},
onSessionEnd: async (context) => {
await chrome.storage.local.remove('marketplace_session');
chrome.runtime.sendMessage({
type: 'MARKETPLACE_SESSION_END',
reason: context.reason,
});
},
},
});
sdk.initialize();
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'GET_SESSION') {
chrome.storage.local.get('marketplace_session', (result) => {
sendResponse(result.marketplace_session || null);
});
return true;
}
});
Content Script:
chrome.runtime.sendMessage(
{ type: 'GET_SESSION' },
(session) => {
if (session) {
console.log('Active marketplace session:', session);
injectSessionHeader(session);
}
}
);
chrome.runtime.onMessage.addListener((request) => {
if (request.type === 'MARKETPLACE_SESSION_START') {
console.log('Session started:', request.session);
}
if (request.type === 'MARKETPLACE_SESSION_END') {
console.log('Session ended:', request.reason);
}
});
Authentication Integration
Backend Token Exchange Pattern
The recommended approach for production apps is to exchange the marketplace JWT for your own application token:
onSessionStart: async (context: SessionStartContext) => {
try {
const response = await fetch('https://your-api.com/auth/marketplace', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${context.jwt}`,
},
body: JSON.stringify({
userId: context.userId,
email: context.email,
sessionId: context.sessionId,
}),
});
if (!response.ok) {
throw new Error(`Auth failed: ${response.status}`);
}
const { token, refreshToken, expiresIn } = await response.json();
localStorage.setItem('auth_token', token);
localStorage.setItem('refresh_token', refreshToken);
localStorage.setItem('token_expires', String(Date.now() + (expiresIn * 1000)));
console.log('[Auth] User authenticated via marketplace');
} catch (error) {
console.error('[Auth] Failed:', error);
throw error; // Prevents session from starting
}
},
Firebase Integration
import { signInWithCustomToken } from 'firebase/auth';
import { auth } from './firebase';
onSessionStart: async (context: SessionStartContext) => {
const response = await fetch('https://your-api.com/auth/firebase-token', {
method: 'POST',
headers: {
'Authorization': `Bearer ${context.jwt}`,
},
});
const { customToken } = await response.json();
await signInWithCustomToken(auth, customToken);
},
Auth0 Integration
onSessionStart: async (context: SessionStartContext) => {
const response = await fetch('https://your-domain.auth0.com/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: context.jwt,
client_id: 'your-auth0-client-id',
client_secret: 'your-auth0-client-secret',
scope: 'openid profile email',
}),
});
const { access_token, id_token } = await response.json();
localStorage.setItem('auth0_access_token', access_token);
localStorage.setItem('auth0_id_token', id_token);
},
Keycloak Integration
onSessionStart: async (context: SessionStartContext) => {
const response = await fetch('https://your-api.com/auth/keycloak-exchange', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${context.jwt}`,
},
body: JSON.stringify({
userId: context.userId,
email: context.email,
}),
});
const { accessToken, refreshToken, idToken } = await response.json();
localStorage.setItem('keycloak_access_token', accessToken);
localStorage.setItem('keycloak_refresh_token', refreshToken);
localStorage.setItem('keycloak_id_token', idToken);
},
Okta Integration
onSessionStart: async (context: SessionStartContext) => {
const response = await fetch('https://your-api.com/auth/okta-exchange', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${context.jwt}`,
},
body: JSON.stringify({
userId: context.userId,
email: context.email,
}),
});
const { accessToken, refreshToken, idToken } = await response.json();
localStorage.setItem('okta_access_token', accessToken);
localStorage.setItem('okta_refresh_token', refreshToken);
localStorage.setItem('okta_id_token', idToken);
},
Performance Optimization
Bundle Size
- SDK is approximately 36 KB gzipped as of 0.3.0 (main ES 5.9 KB + lazy MarketplaceSDK chunk 35 KB)
- Tree-shake unused features — React hooks, Privy modals, and ExtensionModal ship in separate entry points
- Use code splitting — the MarketplaceSDK chunk lazy-loads on first
initialize()
Network
- Cache JWKS response (SDK does this automatically)
- Use CDN for static assets
- Enable HTTP/2
Rendering
- Lazy load session header component
- Debounce timer updates (SDK uses 1s intervals)
- Use
requestAnimationFramefor animations