Hypertune
Search
⌃K

Feature flags quickstart

Create a new project

Sign up at app.hypertune.com/register and create a new project.

Define your configuration schema

Hypertune uses GraphQL for its schema definition language.
Define a new feature flag called enable_paypal on the Root type:
type Root {
example_flag: Boolean!
enable_paypal: Boolean!
}

Define your configuration logic

Switch to the "Logic" tab and select the "Enable Paypal" flag.
Add a "Flag Targeting" expression with a rule that enables the flag if context > user > id is test_id and disables it by default.

Preview your configuration result

Switch to the Preview tab and enter the following query:
query TestQuery {
root {
enable_paypal
}
}
Hypertune uses GraphQL for its query language. In the result panel, you can see just the part of your configuration logic that matches your query.
Now pass the context argument containing the user object in the query:
query TestQuery {
root(
context: {
user: {
id: "test_id"
name: "Test"
}
}
) {
enable_paypal
}
}
Now you can see a more reduced version of your configuration logic, where the "Flag Targeting" expression has been replaced with its result.

Activate your changes

Click "Save & Activate" in the navigation bar.

Install the Hypertune SDK and generate code

Open a terminal in the root of your TypeScript project and run:
npm install hypertune
Add a .env file in the root of your project and define an environment variable called HYPERTUNE_TOKEN. Copy your Token from the Settings tab and set it as the value.
HYPERTUNE_TOKEN=paste_token_from_settings_tab_here
If you're using Hypertune on the frontend, prefix the variable name so it's exposed to the browser. For React, name it REACT_APP_HYPERTUNE_TOKEN. For Next.js, name it NEXT_PUBLIC_HYPERTUNE_TOKEN.
Now add a new file in the root of your project called hypertune.graphql with the following contents:
query InitQuery {
root {
enable_paypal
}
}
This is your SDK initialization query. It determines what configuration logic is downloaded when the SDK initializes or fetches an update. And you get auto-generated code, based on this query, to use the SDK with end-to-end type-safety.
Add another file in the root of your project called hypertune.json with the following contents:
{
"projectId": 0,
"queryFilePath": "hypertune.graphql",
"outputDirectoryPath": "src/generated",
"buildTimeFallback": true
}
Copy your project ID from the Settings tab and set projectId to it.
Set outputDirectoryPath to wherever you want Hypertune to generate your code.
Then run:
npx hypertune
You now have a generated TypeScript source file which you can use to interact with the SDK.

Use the Hypertune SDK

Add a new file called hypertune.ts with the following contents:
import { initializeHypertune } from "./generated/project_0";
const hypertune = initializeHypertune({});
export default hypertune;
Replace "../generated/project_0" with the path to your generated file.
Now you can import this top-level hypertune singleton and use its auto-generated type-safe methods to access your feature flag.
React
Node.js
Add a new file called useHypertune.ts with the following contents:
import React, { useEffect, useMemo } from "react";
import hypertune from "./hypertune";
export default function useHypertune() {
const [isInitialized, setIsInitialized] = React.useState<boolean>(
hypertune.isInitialized()
);
useEffect(() => {
hypertune.waitForInitialization().then(() => {
setIsInitialized(true);
});
}, []);
return useMemo(
() =>
hypertune
.root({
context: {
user: { id: "test_id", name: "Test", email: "[email protected]" },
},
}),
[]
);
}
Then use the hook in your app:
import useHypertune from "./useHypertune";
export default function App() {
const rootNode = useHypertune();
const enablePaypal = rootNode.enable_paypal({}).get(/* fallback */ false);
return (
<div>Enable Paypal: {String(enablePaypal)}</div>
);
}
import express, { Express } from "express";
import hypertune from "./hypertune";
export default function getApp(): Express {
const app = express();
app.get("/purchase", (req, res, next) => {
const rootNode = hypertune.root({
context: { user: { id: "test_id", name: "Test", email: "[email protected]" } },
});
const enablePaypal = rootNode.enable_paypal({}).get(/* fallback */ false);
if (enablePaypal) {
// Paypal code
}
});
return app;
}
If you're using Hypertune on the frontend and have a Content Security Policy, add the following URLs to the connect-src directive: https://hypertune.edgecompute.app https://gcp.fasthorse.workers.dev
When you ran npx hypertune, a snapshot of your configuration logic was saved in the generated file. The SDK instantly initializes from this snapshot first, before fetching the latest configuration logic from the server. So if you try accessing your flag just as your Node server or React app starts up, it'll use the logic in the snapshot if the SDK hasn't had a chance to initialize from the server yet.
You can explicitly wait for the SDK to initialize with hypertune.waitForInitialization():
React
Node.JS
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
hypertune.waitForInitialization().then(() => {
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
});
app.get("/purchase", (req, res, next) => {
await hypertune.waitForInitialization();
const rootNode = hypertune.root({
context: { user: { id: "test_id", name: "Test", email: "[email protected]" } },
});
const enablePaypal = rootNode.enable_paypal({}).get(/* fallback */ false);
if (enablePaypal) {
// Paypal code
}
});
If you've turned off buildTimeFallback in your hypertune.json, your generated file won't have a snapshot so the SDK will use your hardcoded fallback values.

That's it

Now you can update the logic for your enable_paypal flag from the Hypertune UI without a code update, build, deployment, app release or service restart.
When you hit "Save & Activate", the SDK will download your new logic and use it for the next evaluation.
The Logic tab shows you live counts of how often different parts of your configuration logic are evaluated.
And the Logs tab gives you a realtime stream of every SDK operation, including any errors.
To add another new field, you just need to define it in the schema, include it in your SDK initialization query and rerun code generation with npx hypertune.