Skip to Content

Next.js Integration

⚡ 12 min read

Next.js App Router with redirect-based Transcodes auth — native <script defer> in <head>, client providers, Route Handlers for JWT verification.

Transcodes Console only configures your project. Your app loads the CDN SDK and owns sign-in UX.

Canonical walkthrough: Signin · API: Redirect API

Client-side only. The SDK needs the browser (IndexedDB, WebAuthn). Mark every file that touches transcodes with 'use client'. Never call SDK APIs from Server Components or middleware.


Before you start

RequirementWhere
Project IDConsole → Authentication Kit → Installation Guide
CDN scriptInstallation Guide snippet
transcodes.d.tsConsole → Project Setup
SDK Redirect OriginsStep 1 — Domains when callback returns to your site
MembersConsole → RBAC → Users

Load the SDK (CDN)

Use a native <script defer> in <head> — not next/script for webworker.js:

app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <head> <script src={`https://cdn.transcodes.link/${process.env.NEXT_PUBLIC_TRANSCODES_PROJECT_ID}/webworker.js`} defer /> </head> <body>{children}</body> </html> ); }
.env.local
NEXT_PUBLIC_TRANSCODES_PROJECT_ID=proj_abc123xyz

Place transcodes.d.ts under e.g. types/ and include in tsconfig.jsonStep 2.

Wrap the tree with a client bootstrap component (next section).


Client bootstrap

AuthBootstrap — callback + layout wrapper

app/providers/AuthBootstrap.tsx
'use client'; import { useEffect, type ReactNode } from 'react'; export function AuthBootstrap({ children }: { children: ReactNode }) { useEffect(() => { void transcodes.handleSignInCallback().then((result) => { if (result?.success) { // JWT stored — AUTH_STATE_CHANGED fires } }); }, []); return <>{children}</>; }
app/layout.tsx
import { AuthBootstrap } from './providers/AuthBootstrap'; // inside <body>, after <Script … /> <AuthBootstrap>{children}</AuthBootstrap>

Sign-in button

app/components/SignInButton.tsx
'use client'; export function SignInButton() { return ( <button type="button" onClick={() => transcodes.redirectToSignIn()}> Sign in </button> ); }

Auth state

'use client'; useEffect(() => { const off = transcodes.on('AUTH_STATE_CHANGED', ({ isAuthenticated, member }) => { // update React state }); return () => off(); }, []);

Step 3: Redirect · Step 4: Events


Protected pages

There is no Transcodes JWT in Next.js middleware today — gate on the client after the SDK restores the session:

app/dashboard/page.tsx
'use client'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; export default function DashboardPage() { const router = useRouter(); const [ready, setReady] = useState(false); useEffect(() => { void transcodes.token.isAuthenticated().then((authed) => { if (!authed) router.replace('/'); else setReady(true); }); }, [router]); if (!ready) return null; return <div>Dashboard</div>; }

Use a loading shell until isAuthenticated() resolves to avoid hydration mismatch.


Route Handlers (member JWT)

Forward the SDK access token and verify with ES256 + Console JWK:

app/api/me/route.ts
import { NextRequest, NextResponse } from 'next/server'; export async function GET(request: NextRequest) { const token = request.headers.get('authorization')?.replace(/^Bearer /, ''); if (!token) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } // jwtVerify — see Signin Step 5 return NextResponse.json({ ok: true }); }

Step 5: Verify JWT


Step-up and Console

'use client'; const res = await transcodes.redirectToStepUp({ resource: 'billing', action: 'delete', }); const gate = res.payload[0]; const ok = res.success && (gate?.decision === 'allow' || (gate?.decision === 'stepup' && gate?.status === 'verified')); transcodes.redirectToConsole();

Requires signed-in member. Step-up Auth · Console


SSR checklist

  • SDK APIs only inside 'use client' or after useEffect mount.
  • Do not read transcodes during Server Component render.
  • Optional: dynamic(() => import('./SignInButton'), { ssr: false }) for immediate click handlers.

Common mistakes

MistakeFix
Missing AuthBootstrap / callback handlerCall handleSignInCallback() once on load
isAuthenticated() without awaitAlways async
Unregistered callback originSDK Redirect Origins in Console
Step-up with no sessionSign in first

Other frameworks

Last updated on