Overview
The @flagsync/js-sdk integrates into web applications for client-side feature management and event tracking—ideal for single-user contexts like browser environments.
Installation
Install the SDK with your preferred package manager:
npm install @flagsync/js-sdk
npm install -D @flagsync/cli
Quickstart
A basic example of using the SDK in a JavaScript application:
import { FlagSyncFactory } from '@flagsync/js-sdk' ;
// Initialize the SDK
const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: {
key: 'user-123' , // Unique identifier
attributes: {
plan: 'premium' ,
country: 'US'
}
}
});
// Get the client
const client = factory . client ()
// Wait for SDK to be ready
await client . waitForReady ();
// Evaluate a flag
const isFeatureEnabled = client . flag ( 'my-first-kill-switch' );
Initialization
Get Your SDK Key
Find your client-side SDK key in your workspace settings —safe for web/mobile apps (keep server-side keys private).
Initialize the SDK
Initialize the SDK with your SDK key and a user context (e.g., user ID):
import { FlagSyncFactory } from '@flagsync/js-sdk' ;
const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: {
key: 'user123' , // Unique identifier
attributes: {
email: 'user@example.com'
}
}
});
const client = factory . client ();
Ensure the key in FsUserContext is unique and persistent for accurate MAU tracking and consistent flag evaluations. See User Context Best Practices for details.
Wait for Readiness
Use events or promises to ensure the SDK is ready before evaluating flags.
Always wait for SDK initialization before evaluating any flags. Initialization usually completes within 15–30ms, depending on flag count and ruleset complexity.
Promises
async/await
async/await (throws)
await client . waitForReady ();
// SDK is ready
Events
SDK_READY
SDK_READY_FROM_STORE
import { FsEvent } from '@flagsync/js-sdk' ;
client . once ( FsEvent . SDK_READY , () => {
// SDK is ready
});
This event only fires when using the localstorage storage type; the default is memory.
SDK Not Ready
If the SDK isn’t ready, it returns the defaultValue or control:
// SDK not ready
client . flag ( 'flag-one' , false ); // false (defaultValue)
client . flag ( 'flag-two' ); // "control"
SDK Ready
Once ready, flag() returns the server-evaluated value:
await client . waitForReady ();
const value = client . flag ( 'flag-one' ); // Server-evaluated value
Client-side SDKs can bootstrap via LocalStorage or an initial flag set—values apply until the SDK is ready.
See Flag Evaluation: Overview .
Usage
Evaluate Flags
Evaluates a feature flag for the user context. Applies targeting rules, rollouts, and defaults values.
client . flag < T >( flagKey : string , defaultValue ?: T ): T ;
FlagSync CLI
When using the CLI, flag values are automatically inferred from the generated types:
client . flag ( 'layout' ); // Type: 'v1' | 'v2' | 'v3'
client . flag ( 'killswitch' ); // Type: boolean
client . flag ( 'price-discount' ); // Type: 0.1 | 0.2
client . flag ( 'price-discount' , 0.5 ); // ❌ TS Error: Invalid default value
client . flag ( 'invalid-flag' ); // ❌ TS Error: Invalid flag key
Without generated types, you must manually specify the type:
client . flag < 'v1' | 'v2' >( 'layout' ); // Type: 'v1' | 'v2'
client . flag < number >( 'price-discount' ); // Type: number
client . flag < boolean >( 'enable-feature' , false ); // Type: boolean (defaultValue must be true or false)
client . flag ( 'no-type' ) // Type: unknown
An Impression is automatically registered when flag() is called.
Track Events
Submit user actions with track()—use eventValue for numeric data or properties for rich context:
client . track (
eventKey : string ,
eventValue ?: number | null ,
properties ?: Record < string , any > | null
);
There are two types of events:
client . track ( 'page-load-time' , 1.42 );
SDK Event Listeners
The SDK emits these events for SDK lifecycle management:
SDK_UPDATE: Emitted when flags are updated
SDK_READY: Emitted when the SDK is ready
SDK_READY_FROM_STORE: Emitted when flags are loaded from storage
ERROR: Emitted when an error occurs during initialization
import { FsEvent } from '@flagsync/js-sdk' ;
// Flag updates
client . on ( FsEvent . SDK_UPDATE , () => {
console . log ( `Flags updated at ${ new Date (). toISOString () } ` )
});
SDK_UPDATE does not fire if syncing is disabled.
Error Handling
import { FsServiceError } from '@flagsync/js-sdk' ;
// Via events
client . on ( FsEvent . ERROR , ( error : FsServiceError ) => {
console . error ( 'SDK Error:' , error );
});
// Via promises
try {
await client . waitForReadyCanThrow ();
} catch ( error ) {
console . error ( 'Initialization Error:' , error as FsServiceError );
}
All exposed errors are normalized to FsServiceError.
Configuration
Configure the SDK with the FsConfig interface:
interface FsConfig {
sdkKey : string ; // Required: Your SDK key
core : {
key : string ; // Required: User identifier
attributes ?: Record < string , any >; // Optional: Custom user attributes
};
bootstrap ?: Record < string , any >; // Optional: Initial flag values
storage ?: {
type ?: 'memory' | 'localstorage' ; // Optional: Storage type
prefix ?: string ; // Optional: Storage key prefix
};
sync ?: {
type ?: 'stream' | 'poll' | 'off' ; // Optional: Sync strategy
pollRate ?: number ; // Optional: Polling interval in seconds
};
tracking ?: {
impressions ?: {
maxQueueSize : number ; // Required: Max impressions queue size
pushRate : number ; // Required: Impressions push rate
};
events ?: {
maxQueueSize : number ; // Required: Max events queue size
pushRate : number ; // Required: Events push rate
};
};
urls ?: {
sdk ?: string ; // Optional: SDK endpoint URL
};
logger ?: Partial < ILogger >; // Optional: Custom logger
logLevel ?: LogLevel ; // Optional: Logging level
metadata ?: Record < string , any >; // Optional: Additional metadata
}
Custom Attributes
Define user attributes for targeting in Flags: User Segments .
const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: {
key: 'user-123' ,
attributes: {
plan: 'premium' ,
country: 'US' ,
userType: 'enterprise'
}
}
});
Ensure the key in FsUserContext is unique and persistent for accurate MAU tracking and consistent flag evaluations. See User Context Best Practices for details.
Flag Syncing
Configure flag update strategies with the sync object: stream, poll, or off.
By default, flag updates propagate in milliseconds via server-side events (SSE), ensuring the latest values are used in evaluations.
Stream (Default)
Stream updates via SSE—flag updates are reevaluated on the server and sent to the client: const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
sync: {
type: 'stream'
}
});
Polling
Poll the server on an interval: const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
sync: {
type: 'poll' ,
pollRate: 60
}
});
Off
Disable syncing: const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
sync: {
type: 'off'
}
});
Bootstrapping
Initialize the SDK with a set of bootstrap flags:
const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
bootstrap: {
'my-first-kill-switch' : false ,
'another-flag' : 'value'
}
});
Storage
Choose between memory and LocalStorage storage types:
Memory (Default)
const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
storage: {
type: 'memory'
}
});
LocalStorage
const factory = FlagSyncFactory ({
sdkKey: 'your-sdk-key' ,
core: { key: 'user-123' },
storage: {
type: 'localstorage'
prefix : 'flagsync' // Optional: Custom prefix for storage keys
}
});
The SDK_READY_FROM_STORE event fires when loading from LocalStorage—no network request needed, but data may be stale.
Best Practices
Wait for SDK readiness before evaluating flags.
Select a sync strategy (stream/poll/off) based on your application’s needs.
Add user attributes for targeted feature rollouts.
Consider bootstrapping for faster initial renders.
Environment Variables
Set the following environment variable:
FLAGSYNC_SDK_KEY: Your client-side FlagSync SDK key (required)