Add ConfigCat to Next.js App
Tags: nextjs
Published: 2023-06-17 21:38:07

I recently started helping my friend [@jordan-t-romero](https://medium.com/@jordan-t-romero) with a NextJS and NodeJS project she is working on. This weekend we incorporated [ConfigCat](https://configcat.com/) so that we can add feature flags to control what content is displayed in the different environments (local, staging, production, etc.)

Once we created an account and were logged in, we headed over to the [React SDK Reference](https://configcat.com/docs/sdk-reference/react/) guide since [Next.js](https://nextjs.org/) is a framework for [React](https://react.dev/).

## Install Package
Since we use yarn instead of npm, we ran `yard add configcat-react` to add ConfigCat to our dependencies.

## Import & Initialize a `ConfigCatProvider` with your SDK Key.
We wrapped our root component (`_app.tsx` in the Pages folder) with `ConfigCatProvider` to access ConfigCat features in child components.

```typescript
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import Layout from '../components/Layout/_layout'
import '../components/theme/styles.css'
import { ConfigCatProvider } from 'configcat-react'

export default function App({ Component, pageProps }: AppProps) {

  return (
    <ConfigCatProvider sdkKey="...your actual key">
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </ConfigCatProvider>
  )
}
```
When you sign up with ConfigCat, if you go to the documentation, the sample code to paste in to add the provider will include your specific `sdkKey`.

## Try it out
The first place we wanted to try it was in our NavBar. We eventually want to have a Login and Sign Up buttons, but they aren’t hooked up and we aren’t ready for real users on Production, so this was the ideal use case. In the ConfigCat app, we created a new feature to flag called `signUpandLoginVisible` and used the toggle to set it to on for testing purposes.

![Screen shot of the modal pop-up of the ConfigCat site when you make a new feature flag. It has fields for a human readable name, a field for programs to use, an optional hint field to describe the feature, and toggles to initially set Test & Production environments on or off.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e76yzwcp5lr200hckb7z.png)

In `components/Layout/Navbar.tsx` we import `useFeatureFlag` and set a const for `signUpandLoginVisible`. The first arg for `useFeatureFlag/2` is the name of the feature that is set in ConfigCat. The second arg is the default value to be used. Since the page loads slightly faster than the SDK Key can be read, it will use the default until it is connected with ConfigCat. Once we want to have these features shown, we will probably change the default to true. However it is so fast that we couldn’t tell the difference with our human eyes.

```typescript
import NavComponent from './NavComponent'
import { useFeatureFlag } from 'configcat-react'

const Navbar = () => {
  const { value: signUpAndLoginVisible } = useFeatureFlag(
    'signUpAndLoginVisible',
    false,
  )

  return (
    <div>
      <NavComponent navText="Home" />
      <NavComponent navText="About" />
      <NavComponent navText="Contact" />
      {signUpAndLoginVisible ? <NavComponent navText="Sign Up" /> : null}
      {signUpAndLoginVisible ? <NavComponent navText="Login" /> : null}
    </div>
  )
}

export default Navbar
```

![A horizontal nav with buttons for Home, About, Contact, Sign Up, and Login.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53nhzhy406182gfnucs4.png)

And just like that we have a Sign Up and Login button! Then we can go in to ConfigCat, swith the toggle to off, wait a few seconds (usually about 60 seconds or more for us) for the change to take effect, and no more Sign Up or Login buttons!

![ConfigCat signUpAndLoginVisible toggled off.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6bjc5zipiy4d8yihgslv.png)

![A horizontal nav with buttons for Home, About, and Contact.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v47vq2udtl0qaqa734rb.png)

## Use an Environmental Variable
The final piece we wanted to implement was moving the SDK Key out of the app logic and into an Environment Variable. This is for a couple of reasons. You want to [protect private keys](https://www.telerik.com/blogs/beginners-guide-environment-variables) like this and make sure they aren’t visible on places like [GitHub](https://github.com/) where your code lives. Even if it is a private repository, extra protection is always better. The second is that we are using [Vercel](https://vercel.com) for our deployments and it gives us the ability to use different variables for our various environments.

We already have a `.gitignore` file in our home directory that includes our `.env` file: 
```gitignore
# local env files
.env*.local
.env
```
so in our `.env` file we can add where `abc123` is your actual SDK Key:
```
NEXT_PUBLIC_CONFIGCAT_SDK_KEY=abc123
```
Next.js comes with [built in support for environmental variables](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#loading-environment-variables). Because the variables in the `.env` file are by default only available server side (Node.js in our case), we need to add the `NEXT_PUBLIC_` prefix to the variable name. This makes the environment variable accessible in the browser by allowing Next.js to read the value at build time and it is delivered to the client as part of the js bundle. We access the variable by calling `process.env.[variable]` within the code base. Our `_app.tsx` now looks like this:

```typescript
...
import { ConfigCatProvider } from 'configcat-react'

export default function App({ Component, pageProps }: AppProps) {
  const CONFIGCAT_KEY = process.env.NEXT_PUBLIC_CONFIGCAT_SDK_KEY

  return (
    <ConfigCatProvider sdkKey={CONFIGCAT_KEY}>
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </ConfigCatProvider>
  )
}
```
However, we now get have a typescript error: 
```
Type 'string | undefined' is not assignable to type 'string'.
  Type 'undefined' is not assignable to type 'string'.ts(2322)
ConfigCatProvider.d.ts(7, 5): The expected type comes from property 'sdkKey' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<ConfigCatProvider> & Readonly<PropsWithChildren<ConfigCatProviderProps>>'
(property) sdkKey: string
```

Because the SDK Key now comes from our `.env` file, when the app first boots up, the value is undefined until it becomes loaded. The loading process happens very fast so it shouldn’t have much of an effect on users, but we can add in a loading state until the value is available.

```typescript
export default function App({ Component, pageProps }: AppProps) {
  const CONFIGCAT_KEY = process.env.NEXT_PUBLIC_CONFIGCAT_SDK_KEY

  if (!CONFIGCAT_KEY) {
    return <div>Loading...</div>
  }

  return (
    <ConfigCatProvider sdkKey={CONFIGCAT_KEY}>
        <Layout>
          <Component {...pageProps} />
        </Layout>
    </ConfigCatProvider>
  )
}
```

And now we are all set with ConfigCat with a proper environment variable and are ready to fully use our feature flags.

Happy Coding!