npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ops-ai/gatsby-feature-flags-toggly

v1.1.0

Published

Toggly feature flags SDK for Gatsby with SSR, SSG, and build-time page gating

Readme

Toggly Feature Flags SDK for Gatsby

npm version License: MIT

A comprehensive Gatsby plugin for Toggly feature flags with support for SSR, SSG, build-time page gating, and edge worker filtering.

Features

  • 🚀 Gatsby Plugin Integration - Automatic setup via gatsby-config.js
  • ⚛️ Modern React Hooks - useFeatureFlag, useFeatureGate, useToggly
  • 🧩 React Components - <Feature>, <FeatureGate>, <TogglyProvider>
  • 🏗️ Build-Time Page Gating - Extract feature requirements from page frontmatter
  • 🌐 Hybrid Approach - Build with all features enabled, filter at edge/runtime
  • 🔄 Reactive State - Powered by nanostores for minimal bundle size
  • 📦 TypeScript Support - Full type definitions included
  • 🎯 User Targeting - Identity-based feature rollouts
  • Edge Worker Ready - Generate manifests for Cloudflare Workers

Installation

npm install @ops-ai/gatsby-feature-flags-toggly

Quick Start

1. Configure the Plugin

Add the plugin to your gatsby-config.js:

module.exports = {
  plugins: [
    {
      resolve: '@ops-ai/gatsby-feature-flags-toggly',
      options: {
        appKey: 'your-app-key', // Get this from toggly.io
        environment: 'Production', // Optional, defaults to 'Production'
        allFeaturesEnabledDuringBuild: true, // Optional, for hybrid approach
        flagDefaults: {
          // Optional fallback values
          'my-feature': false,
        },
      },
    },
  ],
};

2. Use in Components

Using Hooks

import { useFeatureFlag } from '@ops-ai/gatsby-feature-flags-toggly';

function MyComponent() {
  const { isEnabled, isReady, error } = useFeatureFlag('new-dashboard');

  if (!isReady) return <Loading />;
  if (error) return <ErrorMessage />;

  return isEnabled ? <NewDashboard /> : <OldDashboard />;
}

Using Components

import { Feature } from '@ops-ai/gatsby-feature-flags-toggly';

function MyPage() {
  return (
    <div>
      <Feature flag="new-header">
        <NewHeader />
      </Feature>

      <Feature flag="beta-feature" fallback={<ComingSoon />}>
        <BetaContent />
      </Feature>
    </div>
  );
}

3. Page-Level Gating

Add x-feature to your page frontmatter:

---
title: Beta Features
x-feature: beta-access
---

# Beta Features

This page requires the 'beta-access' feature flag.

During build, the plugin generates a toggly-page-features.json manifest that maps pages to required features, enabling edge worker filtering.

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | appKey | string | required | Your Toggly application key | | environment | string | 'Production' | Environment name (e.g., 'Staging', 'Dev') | | baseURI | string | 'https://client.toggly.io' | Toggly API base URL | | flagDefaults | object | {} | Default flag values when API unavailable | | featureFlagsRefreshInterval | number | 180000 | Client refresh interval (ms) | | allFeaturesEnabledDuringBuild | boolean | false | Enable all features during build | | identity | string | undefined | User identity for targeting | | isDebug | boolean | false | Enable debug logging | | connectTimeout | number | 5000 | API connection timeout (ms) |

API Reference

Hooks

useFeatureFlag(flagKey, defaultValue?)

Check if a single feature flag is enabled.

const { isEnabled, isReady, error } = useFeatureFlag('my-feature', false);

Parameters:

  • flagKey (string): Feature flag key
  • defaultValue (boolean, optional): Default value if flag not found

Returns:

  • isEnabled (boolean): Whether the flag is enabled
  • isReady (boolean): Whether flags have been loaded
  • error (Error | null): Error if loading failed

useFeatureGate(flagKeys, requirement?, negate?)

Check multiple feature flags with gate logic.

const { isEnabled, isReady, error } = useFeatureGate(
  ['feature1', 'feature2'],
  'all', // or 'any'
  false // negate
);

Parameters:

  • flagKeys (string[]): Array of feature flag keys
  • requirement ('all' | 'any', optional): Gate requirement (default: 'all')
  • negate (boolean, optional): Negate the result (default: false)

Returns:

  • isEnabled (boolean): Whether the gate condition is met
  • isReady (boolean): Whether flags have been loaded
  • error (Error | null): Error if loading failed

useToggly()

Access the full Toggly store and utilities.

const {
  flags,
  isReady,
  error,
  refreshFlags,
  setIdentity,
  clearIdentity,
} = useToggly();

Returns:

  • flags (object): All feature flags
  • isReady (boolean): Whether flags have been loaded
  • error (Error | null): Error if loading failed
  • refreshFlags (function): Manually refresh flags
  • setIdentity (function): Set user identity for targeting
  • clearIdentity (function): Clear user identity

Components

<Feature>

Conditionally render content based on a feature flag.

<Feature flag="my-feature" fallback={<Loading />}>
  <Content />
</Feature>

Props:

  • flag (string): Feature flag key
  • fallback (ReactNode, optional): Content when flag is disabled
  • children (ReactNode): Content when flag is enabled

<FeatureGate>

Conditionally render content based on multiple feature flags.

<FeatureGate
  flags={['feature1', 'feature2']}
  requirement="all"
  negate={false}
  fallback={<Restricted />}
>
  <Content />
</FeatureGate>

Props:

  • flags (string[]): Array of feature flag keys
  • requirement ('all' | 'any', optional): Gate requirement (default: 'all')
  • negate (boolean, optional): Negate the result (default: false)
  • fallback (ReactNode, optional): Content when gate is not met
  • children (ReactNode): Content when gate is met

<TogglyProvider>

Provider component (automatically wrapped by plugin).

<TogglyProvider config={options}>
  <App />
</TogglyProvider>

Note: When using the Gatsby plugin, you don't need to manually wrap your app with TogglyProvider. The plugin handles this automatically.

Advanced Usage

User Targeting

Set user identity for targeted feature rollouts:

import { useToggly } from '@ops-ai/gatsby-feature-flags-toggly';

function UserProfile({ userId }) {
  const { setIdentity } = useToggly();

  useEffect(() => {
    setIdentity(userId);
  }, [userId, setIdentity]);

  return <Profile />;
}

Manual Flag Refresh

Manually refresh flags without waiting for the refresh interval:

import { useToggly } from '@ops-ai/gatsby-feature-flags-toggly';

function RefreshButton() {
  const { refreshFlags } = useToggly();

  const handleRefresh = async () => {
    await refreshFlags();
  };

  return <button onClick={handleRefresh}>Refresh Flags</button>;
}

Direct Store Access

For advanced use cases, access the nanostores directly:

import { useStore } from '@nanostores/react';
import { $flags, $flag } from '@ops-ai/gatsby-feature-flags-toggly';

function AdvancedComponent() {
  // Access all flags
  const allFlags = useStore($flags);

  // Access specific flag as computed atom
  const isEnabled = useStore($flag('my-feature', false));

  return <div>{/* ... */}</div>;
}

Build-Time Strategy: Hybrid Approach

The recommended approach for Gatsby sites:

1. Enable All Features During Build

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: '@ops-ai/gatsby-feature-flags-toggly',
      options: {
        appKey: 'your-app-key',
        allFeaturesEnabledDuringBuild: true, // ← Enable this
      },
    },
  ],
};

2. Benefits

  • SEO-Friendly: All content is in the static HTML
  • No Broken Links: All pages are built and accessible
  • Dynamic Control: Features can be toggled without rebuilding
  • Edge Enforcement: Use Cloudflare Workers to filter at the edge

3. Edge Worker Filtering

After build, the plugin generates two manifest files in public/:

  • toggly-page-features.json - Maps pages to required features
  • toggly-config.json - Sanitized config for edge workers

Use these with a Cloudflare Worker to enforce feature gates before serving static HTML:

// Example Cloudflare Worker
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    // Load page features manifest
    const manifest = await env.ASSETS.fetch('/toggly-page-features.json');
    const pageFeatures = await manifest.json();

    // Check if page requires a feature
    const requiredFeature = pageFeatures[url.pathname];

    if (requiredFeature) {
      // Fetch flags from Toggly API
      const flags = await fetchTogglyFlags(env.TOGGLY_APP_KEY);

      // If feature is disabled, return 404
      if (!flags[requiredFeature]) {
        return new Response('Not Found', { status: 404 });
      }
    }

    // Serve the static asset
    return env.ASSETS.fetch(request);
  },
};

Page-Level Gating

Using Frontmatter

For MDX or Markdown pages, add x-feature to frontmatter:

---
title: Beta Page
x-feature: beta-access
---

# Beta Content

Programmatic Pages

When creating pages programmatically, add x-feature to page context:

// gatsby-node.js
exports.createPages = async ({ actions }) => {
  actions.createPage({
    path: '/beta',
    component: require.resolve('./src/templates/beta.js'),
    context: {
      frontmatter: {
        'x-feature': 'beta-access',
      },
    },
  });
};

Generated Manifest

The plugin generates toggly-page-features.json:

{
  "/beta": "beta-access",
  "/premium": "premium-features",
  "/new-dashboard": "new-dashboard-feature"
}

TypeScript Support

The SDK includes full TypeScript definitions:

import type {
  TogglyPluginOptions,
  Flags,
  GateRequirement,
  UseFeatureFlagResult,
  UseFeatureGateResult,
  UseTogglyResult,
} from '@ops-ai/gatsby-feature-flags-toggly';

Examples

Example 1: Feature Toggle

import { useFeatureFlag } from '@ops-ai/gatsby-feature-flags-toggly';

function Dashboard() {
  const { isEnabled } = useFeatureFlag('new-dashboard');

  return (
    <div>
      <h1>Dashboard</h1>
      {isEnabled ? <NewDashboardWidget /> : <OldDashboardWidget />}
    </div>
  );
}

Example 2: A/B Testing

import { useFeatureFlag } from '@ops-ai/gatsby-feature-flags-toggly';

function Hero() {
  const { isEnabled: variantA } = useFeatureFlag('hero-variant-a');

  return variantA ? <HeroVariantA /> : <HeroVariantB />;
}

Example 3: Gradual Rollout

import { useEffect } from 'react';
import { useToggly } from '@ops-ai/gatsby-feature-flags-toggly';

function App({ user }) {
  const { setIdentity } = useToggly();

  useEffect(() => {
    // Set user ID for gradual rollout
    if (user?.id) {
      setIdentity(user.id);
    }
  }, [user, setIdentity]);

  return <div>{/* ... */}</div>;
}

Example 4: Multiple Flag Gates

import { FeatureGate } from '@ops-ai/gatsby-feature-flags-toggly';

function PremiumContent() {
  return (
    <FeatureGate
      flags={['premium-tier', 'beta-access']}
      requirement="any"
      fallback={<UpgradePrompt />}
    >
      <PremiumFeatures />
    </FeatureGate>
  );
}

Example 5: Maintenance Mode

import { Feature } from '@ops-ai/gatsby-feature-flags-toggly';

function App() {
  return (
    <Feature flag="maintenance-mode" fallback={<MainApp />}>
      <MaintenancePage />
    </Feature>
  );
}

Troubleshooting

Flags Not Loading

  1. Check that appKey is correct in gatsby-config.js
  2. Verify network connectivity to https://client.toggly.io
  3. Enable debug mode: isDebug: true in plugin options
  4. Check browser console for errors

Build Errors

  1. Ensure all dependencies are installed: npm install
  2. Clear Gatsby cache: gatsby clean
  3. Rebuild: gatsby build

TypeScript Errors

  1. Ensure @types/react is installed
  2. Check tsconfig.json includes the SDK types
  3. Restart TypeScript server in your IDE

Contributing

Contributions are welcome! Please open an issue or pull request on GitHub.

License

MIT © Ops.AI

Resources

Related Packages

Extensibility with Hooks

Toggly provides a powerful hooks system that allows you to extend SDK functionality by hooking into feature flag lifecycle events. This is perfect for integrating with analytics, monitoring tools, or implementing custom behaviors.

What are Hooks?

Hooks let you execute custom code at specific points in the feature flag evaluation lifecycle:

  • beforeEvaluation: Called before a feature flag is evaluated
  • afterEvaluation: Called after a feature flag is evaluated (with the result)
  • beforeIdentify: Called before user identity is set or cleared
  • afterIdentify: Called after user identity is set or cleared
  • afterRefresh: Called after feature definitions are refreshed from Toggly

Creating a Hook

import { Hook } from '@ops-ai/toggly-hooks-types';

const myAnalyticsHook: Hook = {
  getMetadata: () => ({
    name: 'MyAnalyticsHook',
    version: '1.0.0'
  }),
  
  afterEvaluation: async (data) => {
    // Send to analytics
    analytics.track('Feature Flag Evaluated', {
      feature: data.featureKey,
      enabled: data.result
    });
  }
};

Registering Hooks

During initialization in gatsby-config:

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: '@ops-ai/gatsby-feature-flags-toggly',
      options: {
        appKey: 'your-app-key',
        environment: 'your-environment-name',
        hooks: [myAnalyticsHook]
      }
    }
  ]
};

At runtime:

import { addHook, removeHook } from '@ops-ai/gatsby-feature-flags-toggly';

// Add a hook
addHook(myAnalyticsHook);

// Remove a hook
removeHook(myAnalyticsHook);

Common Use Cases

Analytics Integration:

const clarityHook: Hook = {
  getMetadata: () => ({ name: 'Microsoft Clarity', version: '1.0.0' }),
  afterEvaluation: async (data) => {
    if (typeof clarity !== 'undefined') {
      clarity('event', `FeatureFlag:${data.featureKey}`);
    }
  }
};

Debug Logging:

const debugHook: Hook = {
  getMetadata: () => ({ name: 'DebugLogger', version: '1.0.0' }),
  afterEvaluation: async (data) => {
    if (process.env.NODE_ENV === 'development') {
      console.debug('[Toggly]', data.featureKey, '=', data.result);
    }
  }
};

Related SDKs