# Gatsby quickstart

## 1. Install `hypertune`

Once you have a Gatsby application ready, install Hypertune's JavaScript SDK:

{% tabs %}
{% tab title="npm" %}

```bash
npm install hypertune
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add hypertune
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm add hypertune
```

{% endtab %}
{% endtabs %}

## 2. Set environment variables

Define the following environment variables in your `.env.development` and `.env.production` files:

{% code title=".env.production" %}

```bash
GATSBY_HYPERTUNE_TOKEN=token
HYPERTUNE_FRAMEWORK=gatsby
HYPERTUNE_OUTPUT_DIRECTORY_PATH=src/generated
```

{% endcode %}

Replace `token` with your main project token which you can find in the Settings tab of your project.

## 3. Update `gatsby-config.ts`

Update your `gatsby-config.ts` to load the environment variables with `dotenv`:

{% code title="gatsby-config.ts" %}

```tsx
import type { GatsbyConfig } from 'gatsby'

// Load environment variables
require('dotenv').config({
  path: `.env.${process.env.NODE_ENV}`,
})

const config: GatsbyConfig = {
  siteMetadata: {
    title: `Hypertune Gatsby Demo`,
    siteUrl: `https://www.yourdomain.tld`,
  },
  graphqlTypegen: true,
  plugins: [],
}

export default config
```

{% endcode %}

## 4. Update `.babelrc`

First install the `babel-preset-gatsby` package as a devDependency:

{% tabs %}
{% tab title="npm" %}

```bash
npm install -D babel-preset-gatsby
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add -D babel-preset-gatsby
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm add -D babel-preset-gatsby
```

{% endtab %}
{% endtabs %}

Then create a `.babelrc` at the root of your project:

{% code title=".babelrc" %}

```json
{
  "presets": [
    [
      "babel-preset-gatsby",
      {
        "targets": {
          "browsers": [">0.25%", "not dead"]
        },
        "exclude": ["@babel/plugin-transform-classes"]
      }
    ]
  ]
}
```

{% endcode %}

## 5. Generate the client

Generate a type-safe client to access your flags by running:

{% tabs %}
{% tab title="npm" %}

```bash
npx hypertune
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn hypertune
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm hypertune
```

{% endtab %}
{% endtabs %}

## 6. Use the client

Add a new file called `getHypertune.ts` that creates and exports a `getHypertune` function:

{% code title="lib/getHypertune.ts" %}

```typescript
import { createSourceForServerOnly } from '../generated/hypertune'

const hypertuneSource = createSourceForServerOnly({
  token: process.env.GATSBY_HYPERTUNE_TOKEN!,
})

export default async function getHypertune() {
  await hypertuneSource.initIfNeeded() // Check for flag updates

  return hypertuneSource.root({
    args: {
      context: {
        environment:
          process.env.NODE_ENV === 'development'
            ? 'development'
            : 'production',
        user: {
          id: 'e23cc9a8-0287-40aa-8500-6802df91e56a',
          name: 'Example User',
          email: 'user@example.com',
        },
      },
    },
  })
}
```

{% endcode %}

{% tabs %}
{% tab title="Server-side Rendering" %}
To access flags in `getServerData` during Server-side Rendering (SSR), use the `getHypertune` function:

{% code title="src/pages/ssr.tsx" %}

```tsx
import { GetServerData } from 'gatsby'
import * as React from 'react'
import getHypertune from '../lib/getHypertune'

type ServerData = { exampleFlag: boolean }

export const getServerData: GetServerData<
  ServerData
> = async () => {
  const hypertune = await getHypertune()

  const exampleFlag = hypertune.exampleFlag({ fallback: false })

  return { props: { exampleFlag } }
}

export default function Page({
  serverData,
}: {
  serverData: ServerData
}) {
  return <div>Example Flag: {serverData.exampleFlag}</div>
}
```

{% endcode %}
{% endtab %}

{% tab title="Client-side Rendering" %}
To access flags in the browser during Client-side Rendering (CSR), first create a new `<AppHypertuneProvider>` component that wraps the generated `<HypertuneProvider>` component:

{% code title="components/AppHypertuneProvider.tsx" %}

```tsx
import * as React from 'react'
import { HypertuneProvider } from '../generated/hypertune.react'

export default function AppHypertuneProvider({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <HypertuneProvider
      createSourceOptions={{
        token: process.env.GATSBY_HYPERTUNE_TOKEN!,
      }}
      rootArgs={{
        context: {
          environment:
            process.env.NODE_ENV === 'development'
              ? 'development'
              : 'production',
          user: {
            id: 'e23cc9a8-0287-40aa-8500-6802df91e56a',
            name: 'Example User',
            email: 'user@example.com',
          },
        },
      }}
    >
      {children}
    </HypertuneProvider>
  )
}
```

{% endcode %}

Then wrap your app with the `<AppHypertuneProvider>` component in both `gatsby-browser.tsx` and `gatsby-ssr.tsx`:

{% code title="gatsby-ssr.tsx" %}

```tsx
import * as React from 'react'
import AppHypertuneProvider from './src/components/AppHypertuneProvider'
import type { GatsbyBrowser } from 'gatsby'

export const wrapRootElement: GatsbyBrowser['wrapRootElement'] =
  ({ element }) => {
    return <AppHypertuneProvider>{element}</AppHypertuneProvider>
  }
```

{% endcode %}

Then use the generated `useHypertune` hook:

{% code title="src/components/ClientComponent.tsx" %}

```tsx
import * as React from 'react'
import { useHypertune } from '../generated/hypertune.react'

export default function ClientComponent() {
  const hypertune = useHypertune()

  const exampleFlag = hypertune.exampleFlag({ fallback: false })

  return <div>Example Flag: {String(exampleFlag)}</div>
}
```

{% endcode %}

If you access a flag immediately after your app loads, you'll get your hardcoded fallback value if the SDK hasn't initialized from [Hypertune Edge](https://docs.hypertune.com/concepts/hypertune-edge) yet. This can result in layout shift or a flicker if the flag value changes when the SDK initializes.

To avoid this, wrap your page with the generated `<HypertuneHydrator>` and `<HypertuneRootProvider>` components, passing them `dehydratedState` and `rootArgs` from the server:

{% code title="src/pages/csr.tsx" %}

```tsx
import { GetServerData } from 'gatsby'
import * as React from 'react'
import ClientComponent from '../components/ClientComponent'
import {
  DehydratedState,
  RootArgs,
} from '../generated/hypertune'
import {
  HypertuneHydrator,
  HypertuneRootProvider,
} from '../generated/hypertune.react'
import getHypertune from '../lib/getHypertune'

type ServerData = {
  dehydratedState: DehydratedState | null
  rootArgs: RootArgs
}

export const getServerData: GetServerData<
  ServerData
> = async () => {
  const hypertune = await getHypertune()

  const dehydratedState = hypertune.dehydrate()
  const rootArgs = hypertune.getRootArgs()

  return {
    props: { dehydratedState, rootArgs },
  }
}

export default function Page({
  serverData,
}: {
  serverData: ServerData
}) {
  const { dehydratedState, rootArgs } = serverData

  return (
    <HypertuneHydrator dehydratedState={dehydratedState}>
      <HypertuneRootProvider rootArgs={rootArgs}>
        <ClientComponent />
      </HypertuneRootProvider>
    </HypertuneHydrator>
  )
}
```

{% endcode %}

If you have a Content Security Policy, add the following to your `connect-src` directive: `https://edge.hypertune.com https://gcp.fasthorse.workers.dev`. This enables reporting of flag evaluations, experiment exposures, and analytics events.
{% endtab %}

{% tab title="Functions" %}
To access flags in Gatsby Functions, use the `getHypertune` function:

{% code title="src/api/hello.ts" %}

```typescript
import {
  GatsbyFunctionRequest,
  GatsbyFunctionResponse,
} from 'gatsby'
import getHypertune from '../lib/getHypertune'

export default async function handler(
  req: GatsbyFunctionRequest,
  res: GatsbyFunctionResponse
) {
  const hypertune = await getHypertune()

  const exampleFlag = hypertune.exampleFlag({ fallback: false })

  res.send({ exampleFlag })
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## 7. (Optional) Add the Hypertune Toolbar

The Hypertune Toolbar lets you view and override feature flags directly in your frontend. [Follow the guide](https://docs.hypertune.com/sdk-reference/hypertune-toolbar) to add it to your app.

## 8. (Optional) Include a build-time snapshot

To improve reliability, you can include a snapshot of your flag logic in the generated client at build time. The SDK will instantly initialize from the snapshot first before fetching the latest flag logic from [Hypertune Edge](https://docs.hypertune.com/concepts/hypertune-edge).

Add the following environment variable to your `.env` file:

```bash
HYPERTUNE_INCLUDE_INIT_DATA=true
```

Then regenerate the client.

You can keep the snapshot fresh by setting up a [webhook](https://docs.hypertune.com/integrations/webhooks) to regenerate the client on every Hypertune commit. In this case, you don't need to initialize from Hypertune Edge at all, eliminating network latency and bandwidth, improving both performance and efficiency.

## Next steps

Now you can update the logic for `exampleFlag` from the Hypertune UI without updating your code or waiting for a new build, deployment, or app release.

To add a new flag, create it in the Hypertune UI then regenerate the client.
