You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Dec 12, 2025. It is now read-only.
- supports *server-side rendering* and *static site generation*
30
-
- supports *middleware* and *edge functions*
31
-
- supports *user targeting*, *custom rules* and *rollouts*
32
-
30
+
- supports Server-Side Rendering and Static Site Generation
31
+
- supports Middleware and Edge Functions
32
+
- supports User Targeting, Custom Rules and Rollouts
33
+
33
34
<br />
34
35
35
36
<details>
@@ -56,15 +57,11 @@ import { useFlags } from "flags/client";
56
57
exportdefaultfunctionIndexPage(props) {
57
58
constflagBag=useFlags();
58
59
59
-
returnflagBag.flags.greeting==="dog"
60
-
?"Who's a good boye"
61
-
:"Hello";
60
+
returnflagBag.flags.greeting==="dog"?"Who's a good boye":"Hello";
62
61
}
63
62
```
64
63
65
-
66
-
The self documenting examples at [flags.happykit.dev](https://flags.happykit.dev/) show how to use `@happykit/flags` for client-side, static and server-side rendering.
67
-
64
+
The self documenting examples at [flags.happykit.dev](https://flags.happykit.dev/) show how to use `@happykit/flags` for client-side, static and server-side rendering.
@@ -156,16 +156,15 @@ It's recommended to enable [Absolute Imports](https://nextjs.org/docs/advanced-f
156
156
This will allow you to later import your flags like
157
157
158
158
```ts
159
-
import { useFlag } from"flags/client"
159
+
import { useFlag } from"flags/client";
160
160
```
161
161
162
162
instead of having to use relative imports like
163
163
164
164
```ts
165
-
import { useFlag } from"../../../flags/client"
165
+
import { useFlag } from"../../../flags/client";
166
166
```
167
167
168
-
169
168
### Setting up the Environment Variable
170
169
171
170
You might have noticed that `flags/config.ts` uses an Environment Variable called `
@@ -186,7 +185,6 @@ Later on, don't forget to also provide the environment variable in production.
186
185
187
186
> There's also [a full walkthrough of the setup](https://medium.com/frontend-digest/using-feature-flags-in-next-js-c5c8d0795a2?source=friends_link&sk=d846a29f376acf9cfa41e926883923ab), which explains the setup in your project and in HappyKit Flags itself.
188
187
189
-
190
188
That's it. You're now ready to use your first feature flag.
191
189
192
190
## Basic Usage
@@ -199,7 +197,7 @@ import { useFlags } from "flags/client";
- `@happykit/flags/server`: Use flags in `getServerSideProps` & `getStaticProps`
234
232
- `@happykit/flags/client`: Use flags on the client
@@ -245,7 +243,7 @@ This section describes the exports of your `flags` folder.
245
243
246
244
### `config`
247
245
248
-
*exported from `flags/config`*
246
+
_exported from `flags/config`_
249
247
250
248
Exports a `config` object which is shared across all runtimes (server, client, edge).
251
249
@@ -254,10 +252,9 @@ Exports a `config` object which is shared across all runtimes (server, client, e
254
252
- `config.defaultFlags=undefined` _(object)_ _optional_: Key-value pairs of flags and their values. These values are used as fallbacks in `useFlags` and `getFlags`. The fallbacks are used while the actual flags are loaded, in case a flag is missing or when the request loading the flags fails for unexpected reasons. If you don't declare `defaultFlags`, then the flag values will be `undefined`.
255
253
- `config.endpoint="https://happykit.dev/api/flags"` _(string)_ _optional_: The endpoint to load flags from. This does not usually need to be changed.
256
254
257
-
258
255
### `useFlags`
259
256
260
-
*exported from `flags/client`*
257
+
_exported from `flags/client`_
261
258
262
259
This hook loads the flags on the client.
263
260
@@ -271,7 +268,6 @@ This hook loads the flags on the client.
271
268
- `options.pause` _(boolean)_ _optional_: Set this to `true` to delay fetching of the passed inputs. This is useful in case you need to wait for your `user` or `traits` to be loaded before kicking off the feature flag evaluation request.
272
269
- `options.clientLoadingTimeout=3000` _(number)_ _optional_: A timeout in milliseconds after which any client-side evaluation requests will be aborted. Pass `false` to disable this feature. This feature is only supported in [browsers which support](https://caniuse.com/abortcontroller) the [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). Overwrites `config.clientLoadingTimeout`.
273
270
274
-
275
271
The `useFlags` function returns an object called [`flagBag`](#flagBag). The returned `flagBag` is described [below](#flagbag).
276
272
277
273
#### `flagBag`
@@ -296,10 +292,9 @@ Provide any of these attributes to store them in HappyKit. You will be able to u
296
292
- `avatar` _(string)_: URL to users profile picture
297
293
- `country` _(string)_: Two-letter uppercase country-code of user's county, see [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1)
298
294
299
-
300
295
#### `getFlags`
301
296
302
-
*exported from `flags/server`*
297
+
_exported from `flags/server`_
303
298
304
299
- `getFlags(options)`
305
300
- `options.context` _(object)_ _required_: The context which you receive from `getStaticProps` or `getServerSideProps`.
@@ -324,17 +319,16 @@ This function returns a promise resolving to an object that looks like this:
324
319
325
320
### `getEdgeFlags`
326
321
327
-
*exported from `flags/edge`*
322
+
_exported from `flags/edge`_
328
323
329
324
This function is meant to be used from [Next.js Middleware](https://nextjs.org/docs/middleware) (`middleware` files) and [Edge API Routes](https://nextjs.org/docs/api-routes/edge-api-routes).
330
325
331
-
*exported from `@happykit/flags/edge`*
326
+
_exported from `@happykit/flags/edge`_
332
327
333
328
- `getEdgeFlags(options)`
334
329
- `options.request` _(NextRequest)_ _required_: The Next.js Request.
335
330
- `options.user` _(object)_ _optional_: Same as `user` in `useFlags()`. If pass a user here, make sure to pass the same user to `useFlags({ user })`.
336
331
- `options.traits` _(object)_ _optional_: Same as `traits` in `useFlags()`. If pass traits here, make sure to pass the same traits to `useFlags({ traits })`.
337
-
338
332
339
333
This function returns a promise resolving to an object that looks like this:
340
334
@@ -348,7 +342,7 @@ This function returns a promise resolving to an object that looks like this:
348
342
error: string |null,
349
343
// The preloaded state, which can be provided to useFlags({ initialState })
350
344
initialFlagState: object,
351
-
// Use this to set the response cookie from the middleware
345
+
// Use this to set the response cookie from the middleware
352
346
// with `response.cookie(...cookie.args)`
353
347
cookie:null| {
354
348
name: string;
@@ -359,7 +353,6 @@ This function returns a promise resolving to an object that looks like this:
359
353
}
360
354
```
361
355
362
-
363
356
## Advanced Usage
364
357
365
358
### With user targeting
@@ -371,7 +364,7 @@ You can provide a `user` as the first argument. Use this to enable per-user targ
@@ -610,9 +603,9 @@ And make this change in `flags/edge.ts`
610
603
611
604
Now `@happykit/flags` will load your feature flag definitions from your own storage every time you use `getFlags` or `getEdgeFlags`.
612
605
613
-
*In theory you could commit a file to your own repository containing HappyKit's feature flag definitions and load this json from `getDefinitions`. This would give you feature flags at 0 latency.*
606
+
_In theory you could commit a file to your own repository containing HappyKit's feature flag definitions and load this json from `getDefinitions`. This would give you feature flags at 0 latency._
614
607
615
-
*The downside would be that updates to your flags would require a redeployment, and that changes would not affect other preview deployments.*
608
+
_The downside would be that updates to your flags would require a redeployment, and that changes would not affect other preview deployments._
616
609
617
610
### With same domain evaluations
618
611
@@ -663,17 +656,15 @@ You can use a property called `settled` which turns `true` once the flags are fr
663
656
664
657
> Note: This example does not include the setup of your `flags` folder.
@@ -699,9 +690,9 @@ export default function Page(props) {
699
690
//
700
691
// So the check for "settled" is unnecessary in this example,
701
692
// but useful if you want to use `getStaticProps`.
702
-
if (!flagBag.settled) returnnull
693
+
if (!flagBag.settled) returnnull;
703
694
704
-
returnflagBag.flags?.profileVariant==='A'? (
695
+
returnflagBag.flags?.profileVariant==="A"? (
705
696
<ProfileVariantA user={props.user} />
706
697
) : (
707
698
<ProfileVariantB user={props.user} />
@@ -741,7 +732,7 @@ export type AppFlags = {
741
732
```
742
733
743
734
When you open your project on [happykit.dev](https://happykit.dev/),
744
-
you can go to Flags > Types to generate your `AppFlags` types.
735
+
you can go to Flags > Types to generate your `AppFlags` types.
745
736
746
737
### Code splitting
747
738
@@ -751,21 +742,21 @@ When you open your project on [happykit.dev](https://happykit.dev/),
751
742
If you have two variants of a page and you only want to render one depending on a feature flag, you're able to keep the client-side bundle small by using dynamic imports.
@@ -803,17 +793,15 @@ export default function Page(props) {
803
793
initialState:props.initialFlagState,
804
794
});
805
795
806
-
returnflagBag.flags?.profileVariant==='A'? (
796
+
returnflagBag.flags?.profileVariant==="A"? (
807
797
<ProfileVariantA user={props.user} />
808
798
) : (
809
799
<ProfileVariantB user={props.user} />
810
800
);
811
801
}
812
802
```
813
803
814
-
*This technique of removing the loading state works only with `getServerSideProps`. If you use `getStaticProps`, the server has no concept of the current visitor, but a visitor could influence flag rollouts. The client thus needs to reevaluate the flags and will only settle (pass `settled:true`) once the client-side reevaluation has completed.*
815
-
816
-
804
+
_This technique of removing the loading state works only with `getServerSideProps`. If you use `getStaticProps`, the server has no concept of the current visitor, but a visitor could influence flag rollouts. The client thus needs to reevaluate the flags and will only settle (pass `settled:true`) once the client-side reevaluation has completed._
817
805
818
806
### Middleware example
819
807
@@ -848,15 +836,15 @@ if (flagBag.cookie) {
848
836
response.cookie(
849
837
flagBag.cookie.name,
850
838
flagBag.cookie.value,
851
-
flagBag.cookie.options,
852
-
)
839
+
flagBag.cookie.options
840
+
);
853
841
}
854
842
```
855
843
856
844
There is a shortcut to make this more concise:
857
845
858
846
```ts
859
-
if (flagBag.cookie) response.cookie(...flagBag.cookie.args)
847
+
if (flagBag.cookie) response.cookie(...flagBag.cookie.args);
860
848
```
861
849
862
850
`flagBag.cookie.args` is an array that contains `[cookie.name, cookie.value, cookie.options]`, so `cookie.args` can simply be applied onto `response.cookie`.
@@ -865,7 +853,6 @@ Both of these methods of using `flagBag.cookie` set a cookie called `hkvk` on th
865
853
866
854
You can see this example in action at [flags.happykit.dev/demo/middleware](https://flags.happykit.dev/demo/middleware).
867
855
868
-
869
856
## FAQs
870
857
871
858
### Why should I only ever render the `useFlags` hook once per page?
@@ -878,6 +865,6 @@ Depending on the rendering mode, you might need to pass some `initialState` to t
878
865
879
866
From there it's best to pass the returned `flagBag` to each component that needs it.
880
867
881
-
You can do so directly or by using `@happykit/flags/context`.
868
+
You can do so directly or by using `@happykit/flags/context`.
882
869
883
870
This allows you to switch between flags, and prevents you from calling `useFlags()` with inconsistent values on the same page. Only calling `useFlags()` once per page ensures you'll see the same feature flags on the whole page.
0 commit comments