βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β π shadcn/directory/clerk/clerk-docs/guides/development/sdk-development/fullstack β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β
A fullstack SDK combines the frontend-only SDK and backend-only SDK into one. A fullstack SDK is necessary for frameworks that support multiple rendering strategies (SSR, SSG, etc.), middleware, data fetching, and more. Examples of such frameworks would be Next.js or Rails.
Client{{ target: '_blank' }}, Session{{ target: '_blank' }}, User{{ target: '_blank' }}, and Organization{{ target: '_blank' }} properties through the frameworkβs choice of state managementrequireAuth helper)See the respective frontend-only SDK and backend-only SDK implementation instructions.
In addition to these instructions, you'll need to go through the following steps to support all required features.
<Steps> ### Add handshake support[!NOTE] If you're looking for a real-world example, have a look at
@clerk/nextjs.
Inside your Clerk middleware, add checks for the headers on the requestState. Apply these headers to the Response and handle any existing location headers (e.g. redirects).
import { clerkClient as defaultClerkClient } from './client.ts'
const clerkMiddleware = (options) => {
return async (context, next) => {
const clerkClient = options.clerkClient || defaultClerkClient
const requestState = await clerkClient.authenticateRequest(context.req, {
authorizedParties: ['https://example.com'],
})
if (requestState.headers) {
// This adds observability headers to the res
requestState.headers.forEach((value, key) => context.res.headers.append(key, value))
const locationHeader = requestState.headers.get('location')
if (locationHeader) {
return context.redirect(locationHeader, 307)
} else if (requestState.status === 'handshake') {
throw new Error('Clerk: unexpected handshake without redirect')
}
}
context.set('clerkAuth', requestState.toAuth())
context.set('clerk', clerkClient)
await next()
}
}
</Steps>β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ