FeaturevisorFeaturevisor

Framework guides

Next.js

Set up Featurevisor SDK in a Next.js application for evaluating feature flags targeting static site generation (SSG) and server-side rendering (SSR) strategies.

Rendering strategies

This guide is focused on static site generation (SSG) and server-side rendering (SSR) using Pages Router of Next.js.

If you are looking for a client-side rendering (CSR) strategy, please refer to the React.js guide which comes with its own separate package for convenience.

Creating a new Next.js app

Let's create a new Next.js app using the create-next-app CLI tool:

$ npx create-next-app@latest

Installing SDK

Install the Featurevisor SDK using npm:

$ npm install --save @featurevisor/sdk

It is recommended to be familiar with the SDK API before reading this guide further. You can find full API documentation here.

Setting up Featurevisor SDK

We would like to be able to set up the Featurevisor SDK instance once and reuse the same instance everywhere.

To achieve this, we will create new module featurevisor.js in the root of the project:

// src/featurevisor.js
import { createInstance } from "@featurevisor/sdk";

const DATAFILE_URL = "https://cdn.yoursite.com/datafile.json";

let instance;

export async function getInstance() {
  if (instance) {
    return instance;
  }

  const f = createInstance({
    datafileUrl: DATAFILE_URL,
  });

  instance = await f.onReady();

  return instance;
}

For further SDK usage documentation, please refer to the JavaScript SDK guide.

Now that we have the SDK instance in place, we can use it anywhere in our application.

Static site generation (SSG)

If you are pre-rendering your pages at build time, you can use the getStaticProps function to gain access to the Featurevisor SDK instance and pass your evaluations to the page component.

// src/pages/index.js
import { getInstance } from "../featurevisor";

export async function getStaticProps() {
  const featureKey = "my_feature";
  const context = { userId: "123" };

  // get access to the Featurevisor SDK instance
  const f = await getInstance();

  // evaluate your feature flag, variation, or their variables
  const isEnabled = f.isEnabled(featureKey, context);

  // pass your evaluation as regular props
  return {
    props: {
      isEnabled: isEnabled,
    },
  };
}

export default function Home(props) {
  return (
    <div>
      <h1>My page</h1>

      <p>Feature is {props.isEnabled ? "enabled" : "disabled"}!</p>
    </div>
  );
}

Server-side rendering (SSR)

If you are rendering your pages on each request, you can use the getServerSideProps in a very similar way:

// src/pages/index.js
import { getInstance } from "../featurevisor";

export async function getServerSideProps() {
  const featureKey = "my_feature";
  const context = { userId: "123" };

  // get access to the Featurevisor SDK instance
  const f = await getInstance();

  // evaluate your feature flag, variation, or their variables
  const isEnabled = f.isEnabled(featureKey, context);

  // pass your evaluation as regular props
  return {
    props: {
      isEnabled: isEnabled,
    },
  };
}

export default function Home(props) {
  return (
    <div>
      <h1>My page</h1>

      <p>Feature is {props.isEnabled ? "enabled" : "disabled"}!</p>
    </div>
  );
}

Bucketing guidelines

If you are using Featurevisor for gradual rollouts or A/B testing, you should make sure that the bucketing is consistent across all rendering strategies.

Usually bucketing is done by passing the User's ID when the user is already known, or a randomly generated UUID for the device if the user is not known yet.

Since the getStaticProps and getServerSideProps functions are executed on the server, you should make sure that the User's ID is passed to the server as well. If that's not an option, you are recommended to use a single value consistently.

See documentation about bucketBy property in feature definitions for further explanation here.

App Router

If you are using App Router, you can do something like this:

// src/app/approuter/page.tsx
import { getInstance } from "../../featurevisor";

export default async function Home() {
  const featureKey = "my_feature";
  const context = { userId: "123", country: "nl" };

  const f = await getInstance();

  const isEnabled = f.isEnabled(featureKey, context);

  return (
    <div>
      <h1>My page</h1>

      <p>Feature is {props.isEnabled ? "enabled" : "disabled"}!</p>
    </div>
  );
}

Working repository

You can find a fully functional example of this integration on GitHub: https://github.com/featurevisor/featurevisor-example-nextjs.

Previous
React Native