Use the JavaScript Server SDK and JavaScript Client SDK together to create a server-side rendered experience.

{% callout type="example" heading="" %}
For a complete example, go to the [experiment-node-server demo app](https://github.com/amplitude/experiment-node-server/tree/main/packages/ssr-demo) on GitHub.
{% /callout %}

## Installation

Install both the JavaScript Server SDK and JavaScript Client SDK.

{% code-group %}
```bash npm
npm install --save @amplitude/experiment-js-client @amplitude/experiment-node-server
```

```bash yarn
yarn add @amplitude/skylab-js-client @amplitude/skylab-js-server
```
{% /code-group %}

## Initialize the Server SDK

On server startup, initialize the Server SDK. To distinguish it from the Client SDK `Experiment` object, this example aliases the Server SDK `Experiment` object as `ExperimentServer`.

```js
let ExperimentServer;
if (typeof window === 'undefined') {
  console.debug('Initializing Server Experiment');
  ExperimentServer = require('@amplitude/experiment-node-server').Experiment.initialize(
    'server-IAxMYws9vVQESrrK88aTcToyqMxiiJoR',
    { debug: true },
  );
}

export { ExperimentServer };
```

## Fetch variants on request

On each request, fetch variants using the server-side SDK. The result is a plain JavaScript object that maps feature keys to variant values. Store the result where your rendering code can access it in both server-side and client-side contexts.

```js
const allFlags = await experimentServer.fetchV2({
  id: 'userId',
});

// store the result where the rendering code can access it
global.appProps = { flags: allFlags };
```

## Initialize the Client SDK on render

At the start of your server-side render, initialize the Client SDK with the fetched variants. Instantiate an `ExperimentClient` that the render scope can access (for example, through a React ContextProvider). In the server-side context, create a new `ExperimentClient` every time. In the client-side context, create a new `ExperimentClient` only if one doesn't already exist.

```js
import { ExperimentClient } from '@amplitude/experiment-js-client';

let experimentClient;

const render = (appProps) => {
const isServerSide = typeof window === 'undefined';
  if (isServerSide) {
    console.debug('Initializing Client Experiment');
    // on the server, create a new ExperimentClient every time
    experimentClient = new ExperimentClient(
      'client-IAxMYws9vVQESrrK88aTcToyqMxiiJoR',
      {
        initialVariants: appProps['features'],
      },
    );
  } else if (!experiment) {
    // in the client, only create the ExperimentClient once
    experimentClient = Experiment.initialize(
      'client-IAxMYws9vVQESrrK88aTcToyqMxiiJoR',
      {
        initialVariants: appProps['features'],
      },
    );
  }
}

// use a provider or store the ExperimentClient so the render scope can access it
```

## Get variants on render

After you initialize the Client SDK, fetch the flag status in any component.

```js
// experimentClient should be the same ExperimentClient instance from the previous step
experimentClient.variant('flag-key');
```
