Skip to content

Server-Side Rendering ​

How to use Sesamy with server-rendered pages. Even with SSR, you can use Sesamy's client-side components -- the server provides auth state, and sesamy-js handles the rest.

Overview ​

With SSR, your server renders the page before sending it to the browser. This creates two opportunities:

  1. Pre-populate auth state so sesamy-js knows the reader is logged in without an extra network call
  2. Check entitlements server-side for use cases like personalised content or SEO

The recommended approach combines Capsule encryption (content stays encrypted in the HTML, decrypted client-side) with server-injected auth state.

Injecting the id-token ​

When you use HttpOnly cookie auth with a reverse proxy, the server has access to the auth cookie on each request. You can decode the access token, extract the id-token claims, and inject them into the page so sesamy-js picks them up immediately.

Using the server-state element ​

Add a <script id="sesamy-server-state"> element with the id-token JWT:

html
<script type="application/json" id="sesamy-server-state">
  {"idToken": "eyJhbGciOiJSUzI1NiIs..."}
</script>

sesamy-js reads this element during initialisation. If the token is valid and not expired, the reader is treated as authenticated without calling /auth/userinfo.

Using the config property ​

If you initialise sesamy-js programmatically, pass the id-token via the config:

typescript
import { init } from '@sesamy/sesamy-js';

await init({
  clientId: 'your-vendor-id',
  auth: {
    useHttpCookies: true,
    idToken: serverProvidedIdToken,
  },
  capsule: { enabled: true },
});

How to get the id-token on the server ​

The exact approach depends on your framework. The general pattern:

  1. Read the at (access token) cookie from the incoming request
  2. Decrypt it using the Token Handler encryption secret (or call the /auth/userinfo endpoint with the cookie forwarded)
  3. Extract the id-token claims (sub, name, email, exp, etc.)
  4. Inject the JWT string into the page HTML

Simpler approach: forward the cookie

If you do not want to decrypt the token yourself, your server can call GET /sesamy-api/auth/userinfo with the cookies forwarded. Use the response to mint a signed JWT with an exp claim and inject that as idToken — sesamy-js only accepts a JWT and will ignore raw JSON payloads.

Capsule with SSR ​

With Capsule, the encrypted content and the resourceJWT are already embedded in the HTML at publish time. The server does not need to fetch or prepare any content-related data.

The flow is:

  1. Server renders the page with the DCA manifest (encrypted content) and optionally the server-state element (id-token)
  2. Browser loads sesamy-js
  3. sesamy-js reads the id-token from the server-state element -- reader is authenticated immediately
  4. sesamy-js detects the DCA manifest, calls the unlock endpoint, decrypts the content, and injects it

The server never needs to handle content decryption.

Server-side entitlement checks ​

For cases where you need to know the reader's access level on the server (e.g. to render different layouts or for analytics), you can check entitlements via the Sesamy SDK:

typescript
import { client } from '@sesamy/sdk';

export async function getServerSideProps({ req }) {
  // Forward the session cookie to the Sesamy API
  const sesamyClient = client({
    baseUrl: 'https://api2.sesamy.com',
    headers: { cookie: req.headers.cookie },
  });

  const entitlements = await sesamyClient.entitlements.list();
  const hasAccess = entitlements.some(e => e.sku === 'premium');

  return { props: { hasAccess } };
}

Do not skip client-side protection

Even if you check entitlements server-side, always use Capsule or another lock mode to protect the actual content. Server-side checks are useful for layout decisions, but the content itself should be encrypted or withheld to prevent it from leaking in cached HTML.

Next.js example ​

See the dedicated Next.js + Vercel guide for a complete example including Vercel Edge rewrites, server-side entitlement checks, and client-side Sesamy components.

When you cannot render per-user HTML ​

If your HTML is shared across readers (edge cache, static hosting, CDN-cached pages), you cannot inject a per-user sesamy-server-state element. In that case, use the Bootstrap Loader instead -- a tiny inline script that pre-fetches authentication state in parallel with the main bundle and sets a CSS class on <html> before first paint, so member-only blocks do not flash.

Next Steps ​

Released under the MIT License.