Overview
⚡ 12 min readIntegrate passkey login and step-up MFA: create a project in the Console, load the SDK (HTML / CDN or npm), then open modals and verify JWTs on your backend.
Client-side only. The Transcodes SDK runs in the browser only. Do not
import or call it from SSR or React Server Components. In Next.js, add
'use client' to any file that uses the SDK.
Console: organization and project
Sign in to Transcodes
Open the Transcodes Console . Creating an account creates an organization (your workspace).
Create a project
- Click Create New Project
- Enter a project name (required, up to 100 characters) and optional description (up to 200 characters)
Copy your Project ID
After creation, copy the Project ID (e.g. proj_abc123xyz). Use it in the CDN script URL, in init({ projectId }), and in VITE_TRANSCODES_PROJECT_ID / NEXT_PUBLIC_TRANSCODES_PROJECT_ID.
Organization = company/workspace (billing, members). Project = one app or site. Always use the Project ID in SDK code—not an organization ID.
Two ways to integrate
You can load Transcodes in either of these ways:
| Method | What you do | Typical use |
|---|---|---|
| 1. HTML / CDN | Add webworker.js to index.html (for PWA, also add manifest + sw.js) | PWA, copy-paste Dashboard snippets, no npm required |
| 2. npm SDK | After npm install @bigstrider/transcodes-sdk, call await init({ projectId }) once, then use APIs via named exports | Bundler apps (Vite, Next.js, Vue, etc.) |
Both paths expose the same features; how you call them differs: CDN uses transcodes.openAuthLoginModal(), npm uses import { openAuthLoginModal } from '@bigstrider/transcodes-sdk'.
PWA (Web App Kit) today: Installable PWA (manifest, home screen, service worker) only works when webworker.js is loaded via HTML (or the equivalent early document load, e.g. Next.js beforeInteractive). The npm SDK path alone cannot replace that for PWA—use the HTML + CDN flow and Web App Installation Guide.
HTML / CDN (default — also required for PWA)
Authentication Toolkit Cluster only — passkey login and step-up MFA:
<script
type="module"
src="https://cdn.transcodes.link/YOUR_PROJECT_ID/webworker.js"
></script>Web App Toolkit Cluster (PWA) — manifest + webworker + sw.js:
<link rel="manifest" href="https://cdn.transcodes.link/YOUR_PROJECT_ID/manifest.json" />
<script
type="module"
src="https://cdn.transcodes.link/YOUR_PROJECT_ID/webworker.js"
></script>Add sw.js (Service Worker) — download from Transcodes Dashboard (Web App Cluster → Installation Guide) and place in public/ so it is served at /sw.js. Required for PWA installability
npm SDK: init({ projectId }) (alternative — no script tag)
After installing the package, call init once at the top of your client entry point with an options object:
npm install @bigstrider/transcodes-sdkimport { init } from '@bigstrider/transcodes-sdk';
await init({ projectId: 'YOUR_PROJECT_ID' });
// Optional fields on the same object:
// await init({ projectId: 'YOUR_PROJECT_ID', customUserId: 'uid_xxx', debug: true });Then call every API via named exports — no global window.transcodes:
import {
openAuthLoginModal,
openAuthIdpModal,
isAuthenticated,
getCurrentMember,
getAccessToken,
hasToken,
signOut,
getMember,
on, off,
trackUserAction,
isPwaInstalled,
} from '@bigstrider/transcodes-sdk';Naming: getCurrentMember is the npm counterpart of transcodes.token.getCurrentMember() (signed-in Member from the session/JWT). getMember matches transcodes.member.get() for lookups (e.g. by email). Older SDK versions may still export getCurrentUser / getUser as aliases—prefer the Member names in new code.
GitHub: transcodings/transcodes-sdk
Quick Start Guides
Choose Your Framework
Framework Comparison
| Framework | Build Tool | TypeScript | SSR | Load SDK | State Management |
|---|---|---|---|---|---|
| React | Vite | Yes | No | HTML or npm + init | Context API |
| Next.js | Next.js | Yes | Yes | next/script or npm | Context API |
| Vue.js | Vite | Yes | No | HTML or npm + init | Composables / Pinia |
| Vanilla JS | Vite | No | No | HTML or npm + init | Class / Module |
Universal Setup
Pick HTML script and/or npm + init as in Two ways to integrate, then follow the steps below.
1. Load the SDK
Option A — Script in HTML (required for PWA)
Authentication Toolkit Cluster only (Vite):
<script
type="module"
src="https://cdn.transcodes.link/%VITE_TRANSCODES_PROJECT_ID%/webworker.js"
></script>Web App Toolkit Cluster (PWA) — add manifest, script, and Service Worker:
<link rel="manifest" href="https://cdn.transcodes.link/%VITE_TRANSCODES_PROJECT_ID%/manifest.json" />
<script
type="module"
src="https://cdn.transcodes.link/%VITE_TRANSCODES_PROJECT_ID%/webworker.js"
></script>Service Worker (sw.js) — required for PWA installability (home screen icon, standalone window). The browser registers it to enable “Add to Home Screen”
- Download
sw.jsfrom Transcodes Dashboard → Web App Cluster → Installation Guide - Place it so it is served at
https://yourdomain.com/sw.js:- Vite (React, Vue, Vanilla): put in
public/sw.js - Next.js: put in
public/sw.js
- Vite (React, Vue, Vanilla): put in
Next.js — use next/script with strategy="beforeInteractive". Use the same URLs as above (cdn.transcodes.link). For PWA, add the manifest in <head> and place sw.js in public/
Option B — npm — no script tag; call await init({ projectId }) from the client entry, then use named exports (see framework guides). PWA install flow cannot be npm-only today.
2. Set Environment Variables
Vite (React, Vue, Vanilla):
VITE_TRANSCODES_PROJECT_ID=proj_abc123xyzNext.js:
NEXT_PUBLIC_TRANSCODES_PROJECT_ID=proj_abc123xyz3. Open Login Modal
CDN (window.transcodes):
const result = await transcodes.openAuthLoginModal({
projectId: 'proj_abc123xyz',
});
if (result.success) {
const { token, member } = result.payload[0];
console.log('Logged in as:', member?.email);
}npm (named exports):
import { openAuthLoginModal } from '@bigstrider/transcodes-sdk';
const result = await openAuthLoginModal({ webhookNotification: false });
if (result.success) {
const { token, member } = result.payload[0];
console.log('Logged in as:', member?.email);
}4. Check Authentication Status
isAuthenticated() is an async method. Always use await
CDN:
const isAuth = await transcodes.token.isAuthenticated();npm:
import { isAuthenticated } from '@bigstrider/transcodes-sdk';
const isAuth = await isAuthenticated();5. Subscribe to Auth Events
CDN:
const unsubscribe = transcodes.on('AUTH_STATE_CHANGED', (payload) => {
console.log('Auth state:', payload.isAuthenticated);
});
unsubscribe();npm:
import { on } from '@bigstrider/transcodes-sdk';
const unsubscribe = on('AUTH_STATE_CHANGED', (payload) => {
console.log('Auth state:', payload.isAuthenticated);
});
unsubscribe();6. Sign Out
CDN: await transcodes.token.signOut();
npm:
import { signOut } from '@bigstrider/transcodes-sdk';
await signOut({ webhookNotification: false });SDK API Overview
CDN (window.transcodes)
// Token
transcodes.token.getCurrentMember(): Promise<Member | null>
transcodes.token.getAccessToken(): Promise<string | null>
transcodes.token.hasToken(): boolean
transcodes.token.isAuthenticated(): Promise<boolean> // async!
transcodes.token.signOut(options?: { webhookNotification?: boolean }): Promise<void>
// Member
transcodes.member.get(params): Promise<ApiResponse<Member[]>>
// Modals
transcodes.openAuthLoginModal(params): Promise<ApiResponse<AuthResult[]>>
transcodes.openAuthConsoleModal(params?): Promise<ApiResponse<null>>
transcodes.openAuthAdminModal(params): Promise<ApiResponse<null>>
transcodes.openAuthIdpModal(params): Promise<ApiResponse<IdpAuthResponse[]>>
// Events
transcodes.on(event, callback): () => void
transcodes.off(event, callback): void
// Audit
transcodes.trackUserAction(event, options?): Promise<void>npm SDK (@bigstrider/transcodes-sdk) — named exports
import {
init, // await init({ projectId, customUserId?, debug? })
openAuthLoginModal, // await openAuthLoginModal({ webhookNotification })
openAuthConsoleModal, // await openAuthConsoleModal()
openAuthAdminModal, // await openAuthAdminModal({ allowedRoles })
openAuthIdpModal, // await openAuthIdpModal({ resource, action })
isAuthenticated, // await isAuthenticated() → boolean
getCurrentMember, // await getCurrentMember() → Member | null
getAccessToken, // await getAccessToken() → string | null
hasToken, // hasToken() → boolean (sync)
signOut, // await signOut({ webhookNotification })
getMember, // await getMember({ email }) → ApiResponse<Member[]>
on, off, // on('AUTH_STATE_CHANGED', cb) → unsubscribe fn
trackUserAction, // await trackUserAction({ tag, severity, status }, opts)
isPwaInstalled, // isPwaInstalled() → boolean (sync)
} from '@bigstrider/transcodes-sdk';Available Events
| Event | Description |
|---|---|
AUTH_STATE_CHANGED | Authentication state changed (login/logout) |
TOKEN_REFRESHED | Access token was automatically refreshed |
TOKEN_EXPIRED | Token expired and cannot be refreshed |
ERROR | SDK error occurred |
TypeScript support
- npm: types ship with
@bigstrider/transcodes-sdk - CDN: download definitions from the Authentication Kit → Installation Guide in the Console, or:
curl -o transcodes.d.ts https://cdn.transcodes.link/types/transcodes.d.tsThen point tsconfig.json at your types/ folder (see below).
{
"compilerOptions": {
"typeRoots": ["./node_modules/@types", "./types"]
},
"include": ["src", "types"]
}See each framework guide for full TypeScript setup
Common Patterns
Protected Route Pattern
All frameworks implement a similar protected route pattern:
- Check
isAuthenticated()(async) - If not authenticated, show login modal
- If login cancelled, redirect to home
- If authenticated, render protected content
React/Next.js: <ProtectedRoute> component with useEffect
Vue: <AuthGuard> component with watch
Vanilla JS: init() function with async/await
Auth State Management
| Framework | Pattern | File |
|---|---|---|
| React | Context + use() hook | AuthContext.tsx |
| Next.js | Context + 'use client' | AuthProvider.tsx |
| Vue | Composable / Pinia | useAuth.ts / auth.ts |
| Vanilla JS | Class / Module | auth.js |
Common Mistakes
// WRONG: isAuthenticated() is async
if (transcodes.token.isAuthenticated()) { ... } // CDN
if (isAuthenticated()) { ... } // npm
// CORRECT
if (await transcodes.token.isAuthenticated()) { ... } // CDN
if (await isAuthenticated()) { ... } // npm// WRONG
await transcodes.token.logout();
// CORRECT
await transcodes.token.signOut(); // CDN
await signOut({ webhookNotification: false }); // npmTroubleshooting
SDK Not Loading
// Check if SDK is loaded
if (typeof transcodes === 'undefined') {
console.error('Transcodes SDK not loaded');
}CORS Errors
Ensure your domain is added to the allowed list in the Transcodes Dashboard :
localhost:5173(Vite dev server)localhost:3000(Next.js dev server)yourdomain.com(production)
CSP (Content Security Policy)
At minimum, allow the CDN domain for the SDK script. The exact connect-src and frame-src API domains are available in your Transcodes Console → Authentication Cluster → Installation Guide.
<meta
http-equiv="Content-Security-Policy"
content="
script-src 'self' https://cdn.transcodes.link;
connect-src 'self' {TRANSCODES_API_DOMAINS};
frame-src 'self' {TRANSCODES_API_DOMAINS};
"
/>Replace {TRANSCODES_API_DOMAINS} with the domains listed in your Console.
Production checklist
- Allow your domain in the Transcodes Console (Authentication Kit → Configuration)
- HTTPS in production — WebAuthn needs a secure context
- CSP — include
cdn.transcodes.linkand the Transcodes API domains as in CSP above
The SDK only runs on domains you authorize for the project.
Next steps
- Passkey-first Login - Step-by-step passkey setup
- Step-up MFA - Add MFA for sensitive actions
- React Integration - Vite React SPA guide
- Next.js Integration - Next.js 15 App Router guide
- Vue Integration - Vite Vue 3 guide
- Vanilla JS Integration - Pure JavaScript guide
- API Reference - Full API documentation