Next.js
Next.js route handler example for signing Jupid Embed tokens.
Use a server-only route handler to sign the token. The exact authentication method depends on the partner app; the route must only run for an authenticated partner user.
Install a JWT signer
bun add joseRoute handler
import { SignJWT } from "jose"
import { NextResponse } from "next/server"
const secret = new TextEncoder().encode(process.env.JUPID_EMBED_SECRET)
export async function GET() {
const user = await getCurrentUser()
const now = Math.floor(Date.now() / 1000)
const token = await new SignJWT({
email: user.email,
name: user.name,
payload: {
company_name: user.companyName,
},
})
.setProtectedHeader({ alg: "HS256", typ: "JWT" })
.setIssuer(process.env.JUPID_EMBED_PARTNER_ID)
.setAudience("jupid-embed")
.setSubject(user.id)
.setIssuedAt(now)
.setExpirationTime(now + 300)
.setJti(crypto.randomUUID())
.sign(secret)
return NextResponse.json({ token })
}getCurrentUser represents the partner app's own authenticated user
lookup. Keep this route on the server and never sign tokens from a Client
Component.
Client component
"use client"
import { useEffect, useRef } from "react"
export function JupidEmbed() {
const containerRef = useRef<HTMLDivElement>(null)
useEffect(() => {
async function mount() {
const response = await fetch("/api/jupid/embed-token")
const data = await response.json()
const container = containerRef.current!
window.JupidEmbed.mount({
partnerId: "your-partner-id",
token: data.token,
container,
initialPath: "/",
appUrl: "https://jupid-staging-app.example.com",
})
}
mount()
}, [])
return <div ref={containerRef} className="min-h-[720px]" />
}Add the SDK script to the page or layout that renders the component:
import Script from "next/script"
export function JupidEmbedPage() {
return (
<>
<Script
src="https://jupid-staging-app.example.com/embed.js"
strategy="afterInteractive"
/>
<JupidEmbed />
</>
)
}If your TypeScript setup needs the browser global, declare it in the partner app:
declare global {
interface Window {
JupidEmbed: {
mount(options: {
partnerId: string
token: string
container: HTMLElement
initialPath?: string
appUrl?: string
}): {
destroy(): void
}
}
}
}