Feature flags quickstart
Define a new feature flag called
enable_paypal
on the Root
type:type Root {
example_flag: Boolean!
enable_paypal: Boolean!
}
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.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"
email: "[email protected]"
}
}
) {
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.
Click "Save & Activate" in the navigation bar.
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.
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.devWhen 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.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
.Last modified 3d ago