Documentation Index

Fetch the complete documentation index at: https://docs.xgen.ai/llms.txt

Use this file to discover all available pages before exploring further.

Server Side Integration

Prev Next

Unfortunately, there is no "one size fits all" solution because each framework handle SSR differently (and even in a single framework there is more than one way of doing things).

But in general, the idea is to use a cookie based flow:

  1. Create a new XGenClient instance for each server-side request

  2. "Load/Feed" your xg.authStore with data from the request cookie

  3. Perform your application server-side actions

  4. Before returning the response to the client, update the cookie with the latest xg.authStore state

All BaseAuthStore instances have 2 helper methods that should make working with cookies a little bit easier:

// update the store with the parsed data from the cookie string
xg.authStore.loadFromCookie('xgen_token=...;xgen_user=...;xgen_session=...');

// exports the store data as cookie, with option to extend the default SameSite, Secure, HttpOnly, Path and Expires attributes
xg.authStore.exportToCookie({ httpOnly: false }); // Output: 'xgen_token=...;xgen_user=...;xgen_session=...'


Below you can find an example of how to integrate with Express:

Express

One way to integrate with Express could be to create the XGen client in a [middleware](https://expressjs.com/en/guide/using-middleware.html) and pass it to the other routes using the res.locals.

Note: Your server will need to handle CORS

  • set the allowed origin and credentials: true on your server

  • Make sure to include credentials: include when making the fetch call

  • When calling xg.authStore.exportToCookie() make sure you pass the option to switch sameSite: false

    • xg.authStore.exportToCookie({secure: true, sameSite: false, httpOnly: true, path: '/'})

// src/index.ts
import express from 'express';
import XGenClient, { type ClientParams } from '@xgenai/sdk-core';

// locals typescript
declare global {
	namespace Express {
		interface Locals {
			xg: XGenClient;
		}
	}
}

const clientParams: ClientParams = {
	key: 'client-key',
	secret: 'client-secret',
	clientId: 'client-id',
	trackerId: 'tracker-id',
};

export const app = express();

const port = 3000;

// Middleware - creates a new client and loads the cookie info (user, session, token data)
app.use((req, res, next) => {
	const xg = new XGenClient(clientParams);
	if (xg) {
		res.locals.xg = xg;
	}

	xg.authStore.loadFromCookie(req.headers.cookie || '');

	next();
});

// Routes
app.get('/', (_, res) => {
	res.send('Healthy!');
});

app.get('/products', async (_, res) => {
	try {
		const recommendations = await res.locals.xg.recommend.getResultsById({
			elementId: '<element_id>',
		});

		res.setHeader('Set-Cookie', res.locals.xg.authStore.exportToCookie());

		res.send(recommendations);
	} catch (err) {
		console.error(err);
		res.send(err);
	}

});

// Server
app.listen(port, () => {
	console.logExample app listening on port ${port});
});


Below you can find an example of how to integrate with SvelteKit SSR:

SvelteKit

One way to integrate with SvelteKit SSR could be to create the XGen client in a hook handle and pass it to the other server-side actions using the event.locals.

// src/hooks.server.js
import XGenClient from '@xgenai/sdk-core';

/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
  event.locals.xg = new XGenClient({/*params*/});

  // load the store data from the request cookie string
  event.locals.xg.authStore.loadFromCookie(event.request.headers.get('cookie') || '');

  const response = await resolve(event);

  // send back the default 'xgen_token', 'xgen_user', 'xgen_session' cookies to the client with the latest store state
  response.headers.append('set-cookie', event.locals.xg.authStore.exportToCookie());

  return response;
}

And then, in some of your server-side actions, you could directly access the previously created event.locals.xg instance:

// src/routes/recommendations/+server.js

/**

* Creates a `POST /recommendations` server-side endpoint

*

* @type {import('./$types').RequestHandler}

*/

export async function POST({ request, locals }) {
  const { email, password } = await request.json();
  const results = await xg.recommend.getResultsById({elementId: '<element_id>'})
  return new Response(results);
}

For proper locals.xg type detection, you can also add XGenClient in your your global types definition:

// src/app.d.ts

import XGenClient from '@xgenai/sdk-core';

declare global {
  declare namespace App {
    interface Locals {
      xg: XGenClient
    }
  }
}