A native session bridge into your page’s server middleware. The bridge writes the session into the WebView’s cookie store (and optionally injects a request header) so Next.js, TanStack, or any framework’s middleware sees an authenticated user on the very first request, no Clerk web SDK on the page required. On by default with sensible scoping, most apps never need to tune it.Documentation Index
Fetch the complete documentation index at: https://setup.despia.com/llms.txt
Use this file to discover all available pages before exploring further.
Parameters
| Param | Default | Notes |
|---|---|---|
enabled | true | false purges every SSR cookie |
header | none | Header name to inject on main-frame navigations. Authorization gets a Bearer prefix, any other name gets the raw JWT |
domains | app host + localhost + 127.0.0.1 | Comma-separated override of the cookie/host scope |
Cookies
Three cookies, scoped per configured domain, refreshed every 50 seconds.| Cookie | Value | Used by |
|---|---|---|
__session | Session JWT | Clerk’s clerkMiddleware() |
__client_uat | Unix-seconds signed in, 0 signed out | Clerk’s middleware signed-in/out signal |
clerk_token | Session JWT | Manual @clerk/backend verification or client-side reads |
HttpOnly (so client code on localhost can read clerk_token), Secure on real hosts, and not Secure on localhost / 127.0.0.1 so they work over http://localhost:port.
Header transport
Withheader=, the bridge intercepts main-frame GETs to configured domains and attaches the header.
Authorization gets a Bearer prefix. Any other header (X-Clerk-JWT, X-Auth) gets the raw JWT.
Next.js
clerkMiddleware() reads __session and __client_uat from request cookies, so the standard middleware just works.
<ClerkProvider>, no useAuth() hook, no web SDK. The native bridge writes the cookies and the middleware does the rest.
Manual verification
For any other backend, read the JWT and verify it with@clerk/backend.
sub. Never accept a client-reported userId.
Handshake invariant
Clerk’s middleware treats “a live__client_uat next to a missing/expired __session” as a redirect to Clerk’s FAPI for a handshake, which a native WebView with no Clerk web SDK cannot satisfy. The bridge guarantees the cookie pair is only ever in one of two states middleware accepts without a handshake:
- Signed-in: fresh JWT in
__sessionplus__client_uat > 0 - Signed-out: no
__sessionplus__client_uat = 0
Cold launch
The first page load of a cold launch is anonymous, Clerk is not configured until your page’s JS has run and calledclerk://configure. That first load lands in the safe signed-out state, never a handshake. Every navigation after configure is authenticated.
If you need authenticated SSR on the very first byte, configure earlier in your boot or render a brief loading shell that calls configure and then navigates to the real route once window.clerkJWT is populated.
Offline
A failed refresh leaves the existing cookies in place. Once they hit their 55-second TTL the browser presents the signed-out state to middleware rather than the handshake combination. The user effectively becomes signed-out for new server-rendered requests until the device comes back online.Resources
NPM Package
despia-native