Open Feature Web SDK
The Basestack Open Feature Web SDK provider allows you to use Basestack Feature Flags with the Open Feature standard, providing a vendor-neutral, portable feature flag solution for web applications. This provider bridges Basestack's feature flag infrastructure with Open Feature's standardized API, giving you the flexibility to switch providers without changing your code.
Open Feature is an open standard for feature flag management that provides a consistent API across different providers. With this provider, you can leverage Open Feature's excellent developer experience including type safety, context-aware evaluation, and a standardized API while using Basestack as your feature flag backend.
Preview Status: This provider is currently in preview and still under active development. Basic feature flag functionality is supported, but advanced features like evaluation context and user identity targeting are still in the works. We recommend using this provider if you only need basic feature flag functionality.
Getting started
Install
Install the Open Feature Web SDK, core package, and the Basestack provider. The @openfeature/web-sdk provides the core Open Feature functionality for browsers, while @basestack/openfeature-provider connects it to Basestack's API.
npm install @openfeature/web-sdk @openfeature/core @basestack/openfeature-providerpnpm install @openfeature/web-sdk @openfeature/core @basestack/openfeature-provideryarn add @openfeature/web-sdk @openfeature/core @basestack/openfeature-providerbun add @openfeature/web-sdk @openfeature/core @basestack/openfeature-providerEnvironment Variables
Configure your environment variables to connect to your Basestack Feature Flags project. The variable names depend on your build tool (Vite uses VITE_, Next.js uses NEXT_PUBLIC_, etc.).
When it comes to environment variables, pay attention to the framework you're using. For example, NEXT_PUBLIC_ is specific to Next.js, while in Vite.js, it would be VITE_. Example VITE_FEATURE_FLAGS_PROJECT_KEY= or FEATURE_FLAGS_PROJECT_KEY=
# BASESTACK FEATURE FLAGS
FEATURE_FLAGS_PROJECT_KEY=""
FEATURE_FLAGS_ENVIRONMENT_KEY=""You can find your project and environment keys in your Basestack Feature Flags Dashboard.
Make sure to add your .env file to .gitignore to keep your keys secure. Never commit sensitive credentials to version control.
Initialize the Provider
Create and configure the Basestack provider, then set it as the default provider for Open Feature. The provider handles API communication, caching, and automatic flag refreshing.
import { OpenFeature } from '@openfeature/web-sdk';
import { createBasestackWebProvider } from "@basestack/openfeature-provider/web";
const provider = createBasestackWebProvider({
apiUrl: "https://flags-api.basestack.co/v1",
projectKey: import.meta.env.FEATURE_FLAGS_PROJECT_KEY, // or process.env for Node-based tools
environmentKey: import.meta.env.FEATURE_FLAGS_ENVIRONMENT_KEY,
prefetch: true, // Prefetch all flags on initialization
refreshIntervalMs: 30_000, // Refresh flags every 30 seconds
});
try {
await OpenFeature.setProviderAndWait(provider);
console.log('OpenFeature provider initialized successfully');
} catch (error) {
console.error('Failed to initialize provider:', error);
}The provider configuration includes:
apiUrl: Your Basestack API endpointprojectKey&environmentKey: Your Basestack credentialsprefetch: Whether to fetch all flags on initializationrefreshIntervalMs: How often to refresh flags automatically (in milliseconds)
Use Flags in Your Application
Once initialized, get a client instance and use it to evaluate flags throughout your application. The client provides type-safe methods for different flag value types.
import { OpenFeature } from '@openfeature/web-sdk';
import { createBasestackWebProvider } from "@basestack/openfeature-provider/web";
// ... provider initialization ...
const client = OpenFeature.getClient();
// Get boolean flag value
const isHeaderEnabled = client.getBooleanValue('header', false);
if (isHeaderEnabled) {
console.log("Header is enabled");
// Show new header
} else {
// Show default header
}
// Get object flag value
const config = client.getObjectValue('checkout-config', {});The client provides methods for different value types:
getBooleanValue(key, defaultValue): Get a boolean flaggetObjectValue(key, defaultValue): Get an object/JSON flag
Advanced Usage
Flag Details
Get detailed information about flag evaluations, including metadata and reasons:
const client = OpenFeature.getClient();
// Get boolean flag details
const details = client.getBooleanDetails('header', false);
console.log(details.value); // The flag value
console.log(details.variant); // The variant name
console.log(details.reason); // Why this value was returned
console.log(details.flagMetadata); // Additional metadata
// Similar methods exist for other types
const objectDetails = client.getObjectDetails('config', {});Framework Integration
Vanilla JavaScript / TypeScript
For vanilla JavaScript applications, initialize the provider in your entry point:
import { OpenFeature } from '@openfeature/web-sdk';
import { createBasestackWebProvider } from "@basestack/openfeature-provider/web";
async function initApp() {
const provider = createBasestackWebProvider({
apiUrl: "https://flags-api.basestack.co/v1",
projectKey: import.meta.env.FEATURE_FLAGS_PROJECT_KEY,
environmentKey: import.meta.env.FEATURE_FLAGS_ENVIRONMENT_KEY,
prefetch: true,
refreshIntervalMs: 30_000,
});
await OpenFeature.setProviderAndWait(provider);
const client = OpenFeature.getClient();
// Use flags throughout your app
const showNewFeature = client.getBooleanValue('new-feature', false);
if (showNewFeature) {
// Initialize new feature
}
}
initApp();Configuration Options
The createBasestackWebProvider function accepts the following configuration:
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
apiUrl | string | Yes | - | Basestack API endpoint URL |
projectKey | string | Yes | - | Your Basestack project key |
environmentKey | string | Yes | - | Your Basestack environment key |
prefetch | boolean | No | false | Whether to fetch all flags on initialization |
refreshIntervalMs | number | No | 30000 | How often to refresh flags automatically (milliseconds) |
Best Practices
1. Initialize Provider Early
Initialize the provider as early as possible in your application lifecycle to ensure flags are available when needed:
// Initialize before rendering
await OpenFeature.setProviderAndWait(provider);
// Then render your app2. Use Appropriate Default Values
Always provide sensible default values that represent the "off" or "safe" state:
// Good: Safe default
const isEnabled = client.getBooleanValue('risky-feature', false);
// Avoid: Unsafe default
const isEnabled = client.getBooleanValue('risky-feature', true);3. Set Evaluation Context
Provide user context for targeted flag evaluation:
const context = {
targetingKey: userId,
email: userEmail,
plan: userPlan,
};
client.setContext(context);4. Handle Provider Errors
Always handle provider initialization errors gracefully:
try {
await OpenFeature.setProviderAndWait(provider);
} catch (error) {
console.error('Failed to initialize provider:', error);
// Fallback to default behavior or show error message
}5. Use Flag Details for Debugging
Use getDetails methods when you need to understand why a flag returned a specific value:
const details = client.getBooleanDetails('feature', false);
console.log('Flag reason:', details.reason);
console.log('Flag metadata:', details.flagMetadata);6. Optimize Refresh Intervals
Balance freshness with performance by setting appropriate refresh intervals:
// Frequent updates for critical flags
refreshIntervalMs: 10_000, // 10 seconds
// Less frequent for stable flags
refreshIntervalMs: 60_000, // 1 minuteTroubleshooting
Provider Not Initializing
If the provider fails to initialize:
- Check Environment Variables: Ensure your project and environment keys are set correctly
- Verify API URL: Confirm the
apiUrlis correct and accessible - Check Network: Verify your application can reach the Basestack API endpoint
- Review Console: Check browser console for detailed error messages
Flags Always Returning Default Values
If flags always return default values:
- Check Flag Keys: Verify the flag key matches what's configured in Basestack
- Verify Credentials: Ensure project and environment keys are correct
- Check Provider Status: Ensure the provider initialized successfully
- Inspect Network: Check browser network tab to see if API calls are being made
Flags Not Updating
If flags aren't updating:
- Check Refresh Interval: Flags refresh based on
refreshIntervalMs. Wait for the interval or reduce it - Verify Prefetch: If
prefetchis enabled, flags are fetched on initialization - Check Provider Events: Listen to
ConfigurationChangedevents to detect updates - Manual Refresh: Consider implementing manual refresh if needed
Type Errors
If you're getting TypeScript errors:
- Install Types: Ensure
@openfeature/coretypes are installed - Check Imports: Verify you're importing from the correct packages
- Type Assertions: Use type assertions for object values when needed
Performance Issues
If you're experiencing performance problems:
- Increase Refresh Interval: Reduce API calls by increasing
refreshIntervalMs - Disable Prefetch: If you don't need all flags, set
prefetch: false - Use Caching: The provider includes built-in caching, but you can optimize further
- Lazy Load: Consider lazy loading flags that aren't needed immediately