# Guide

This guide builds on the SDK quickstart and shows you how to model, manage, and experiment on your in-app content using Hypertune.

You'll learn how to:

* Create custom object types to model your in-app content
* Create flags that use those custom object types
* Access those flags and render content in your code
* Update and target your in-app content
* Run experiments on your in-app content

## Prerequisites

[Set up Hypertune](https://docs.hypertune.com/getting-started/set-up-hypertune)

## Create custom object types to model your content

Go to the **Schema** view in the dashboard. Click the **+** button in the top-right of the sidebar. Select **Object**, enter a name, and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FOMPDsZc85r9gIa9Qp47Y%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull.png?alt=media&#x26;token=8f970966-46dd-42a4-931f-2fe3a2c301bc" alt=""><figcaption></figcaption></figure>

By default, the new object type has no fields.

Click **+ Add** to add a new field. Enter a name, set its type, and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FhzLkPi56SktVjjCNBkKB%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(1).png?alt=media&#x26;token=61b38706-aa3b-42a4-aa78-cea680976354" alt=""><figcaption></figcaption></figure>

Repeat for each field you want to add, then click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FdC9eLQYJPnIda0aVLgFF%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(3).png?alt=media&#x26;token=9c2927c9-fb13-4308-be37-2db36bafccd7" alt=""><figcaption></figcaption></figure>

## Create flags for your content

Go to the **Flags** view in the dashboard. Click the **+** button in the top-right of the sidebar and select **Flag**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FRedhKpbFv55kiedI78qr%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(4).png?alt=media&#x26;token=06e77c5d-0051-421d-8997-5a2a5584e755" alt=""><figcaption></figcaption></figure>

Enter a name, set its type to the one you created earlier, and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FVsogasbkJCYaC451OX4r%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(5).png?alt=media&#x26;token=9e1e6496-46fc-4d8b-a439-25918955847c" alt=""><figcaption></figcaption></figure>

Enter the initial content, then click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FPUKcHXBr131WCKjylCsw%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(9).png?alt=media&#x26;token=15ab55be-d62c-4c45-aea5-49859c9402c3" alt=""><figcaption></figcaption></figure>

## Access flags to retrieve your content

Regenerate the client:

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

```bash
npx hypertune
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn hypertune
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm hypertune
```

{% endtab %}
{% endtabs %}

Create a React component that accepts a prop typed with your custom Hypertune object type:

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

```tsx
'use client'

import { type ModalContent } from '@/generated/hypertune'

export default function Modal({
  content,
  onClick,
}: {
  content: ModalContent
  onClick: () => void
}) {
  return (
    <div>
      <h1>{content.title}</h1>
      <p>{content.message}</p>
      <button type="button" onClick={onClick}>
        {content.buttonText}
      </button>
    </div>
  )
}

```

{% endcode %}

Then evaluate your flag and pass the result to your component:

```tsx
'use client'

import Modal from '@/components/Modal'
import { useHypertune } from '@/generated/hypertune.react'
import useOrganization from '@/lib/useOrganization'
import useUpgrade from '@/lib/useUpgrade'

export default function PaidFeature({
  children,
}: {
  children: React.ReactNode
}) {
  const content = useHypertune().upgradeModalContent().get()
  const organization = useOrganization()
  const upgrade = useUpgrade()

  return organization.plan === 'free' ? (
    <Modal
      content={content}
      onClick={() => {
        upgrade()
      }}
    />
  ) : (
    children
  )
}
```

By defining React components that accept props typed with your custom Hypertune types, changes to your types only affect the components that use them. This creates clean boundaries between content types, making your content model and codebase modular, maintainable, and easy to evolve.

## Update your in-app content

Go to the **Flags** view in the dashboard, and select the flag with your in-app content from the left sidebar.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2F0yZs1tbT1wej2T9A1DvW%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(9).png?alt=media&#x26;token=ba4352ed-19a6-4bfb-8076-29658a7558b3" alt=""><figcaption></figcaption></figure>

Make your changes, then open the **Diff** view to review them. Click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FDI7jiHYQhg3LW6aUTKk2%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(10).png?alt=media&#x26;token=2d1d7d99-f3df-4dec-b0c8-2daf6f8303f2" alt=""><figcaption></figcaption></figure>

## Target your in-app content

Go to the **Flags** view in the dashboard, and select the flag with your in-app content from the left sidebar.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FDGHP52S7PhnkEkbh1sxN%2Flocalhost_3000_projects_6715_main_draft_schema_setup%3D0%26selected_schema_type%3Dnull%20(11).png?alt=media&#x26;token=eadf1407-2b9b-4891-bbe6-7be3340ade72" alt=""><figcaption></figcaption></figure>

Click **+ Rule**, set your condition, provide alternate content for that condition, and click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2F2xEqiurMp8tKr0FMFudg%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26selecte.png?alt=media&#x26;token=7ad5064d-27ac-45cf-964e-5b340af65a57" alt=""><figcaption></figcaption></figure>

## Experiment on your in-app content

Go to the **Flags** view in the dashboard, and select the flag with your in-app content from the left sidebar.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FyaVBWAjbf4z6px80Lajs%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26sel%20(1).png?alt=media&#x26;token=34886e75-b9d6-463a-9e2b-c3a82936d1de" alt=""><figcaption></figcaption></figure>

Click **+ Experiment**. In the dropdown, select **New experiment**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FlLEnJ8YZRi9s8WZf0DFZ%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26sel%20(5).png?alt=media&#x26;token=ce598693-df0f-4f4b-ab93-dc92d0c42ab8" alt=""><figcaption></figcaption></figure>

Enter a name for your experiment and click **Create**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FAZNXC129tOxRgyT4GFA0%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26se%20(10).png?alt=media&#x26;token=87617160-d224-4389-bf03-05db6e7a94dc" alt=""><figcaption></figcaption></figure>

Click **Insert** and update the **Test** variant of your content.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FQIU500PMG6fQ5mmItvP6%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26sel%20(7).png?alt=media&#x26;token=ebadc803-9cf6-4a41-935c-b521e4fc0466" alt=""><figcaption></figcaption></figure>

Review your changes in the **Diff** view and click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FDQbjxmacYsKppZiDKHjl%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26sel%20(8).png?alt=media&#x26;token=444f39e2-9787-418b-9f1d-a1fd7b10f187" alt=""><figcaption></figcaption></figure>

Once you've [analyzed your experiment results](https://docs.hypertune.com/experimentation/guide#analyze-experiment-results) and decided on a winning variant, go to the **Flags** view and select your flag. Click the options button (⋯) next to the variant you want to ship and select **Ship variant**, then click **Save**.

<figure><img src="https://2048905609-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWa3rQLiu4JZhBRkiyoKz%2Fuploads%2FXbQ2E2ekTxBHl5DwPn9H%2Flocalhost_3000_projects_6715_main_draft_logic_setup%3D0%26selected_schema_type%3D%257B%2522type%2522%253A%2522input%2522%252C%2522name%2522%253A%2522Context%2522%252C%2522selectedChildName%2522%253Anull%252C%2522count%2522%253A1%257D%26selected_field_path%3Droot%253EupgradeModalContent%26sel%20(9).png?alt=media&#x26;token=3989cf59-3803-40e1-a43e-fdf732a05f1b" alt=""><figcaption></figcaption></figure>

## Next steps

* Run a [multivariate test](https://docs.hypertune.com/concepts/multivariate-tests) to find the best combination of content variants to maximize conversion lift.
* Set up an [AI loop](https://docs.hypertune.com/concepts/ai-loops) to automatically personalize content for each unique user to maximize conversion lift.
* Add content collections with list flags, e.g. `List[Tutorial]`, where `Tutorial` is a custom type that you define.
