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

@interzept/interzept-environment-selector

v1.1.0

Published

Multi-environment data source selector with feature flags and production safety

Readme

interzept-environment-selector

Multi-environment data source selector with feature flags and production safety. Perfect for testing and debugging across multiple environments simultaneously.


Environment Selector vs Data Source Selector

Environment Selector: Lets you choose which app environment to use (e.g., development, staging, production). Useful for testing how your app behaves in different deployment contexts.

Data Source Selector: Lets you choose where your app gets its data (e.g., mock data, local database, remote API). Useful for switching between test data and real data sources.

This package combines both!

  • Select environments (dev, UAT, prod) and data sources (mock, local, API) in one UI.
  • Multi-select and merge data from several sources/environments for advanced testing and debugging.

This flexibility makes it a powerful tool for development, QA, and debugging.


Features

Multi-Select - Select and merge data from multiple environments simultaneously
🔒 Production Safe - Automatically hidden in production deployments
🎯 Feature Flag - Company-only internal tool with "Internal" badge
💾 Persistent - Selection saved to localStorage
🚀 Zero Config - Works out of the box in development
Parallel Fetching - Fetch from multiple sources in parallel

Installation

npm install @interzept/interzept-environment-selector
# or
pnpm add @interzept/interzept-environment-selector
# or
yarn add @interzept/interzept-environment-selector

Quick Start

1. Wrap your app with the provider

// app/layout.tsx
import { DataSourceProvider } from '@interzept/interzept-environment-selector'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <DataSourceProvider>
          {children}
        </DataSourceProvider>
      </body>
    </html>
  )
}

Using Wrappers for Customization

You can create thin wrapper files in your app or in this package to customize, feature-flag, or style the exports from @interzept/interzept-environment-selector. Wrappers help keep your import paths stable and allow you to add app-specific logic.

Example: Custom Wrapper for DataSourceToggle

// src/data-source-toggle-wrapper.tsx
// Add feature flags, custom props, or styling here if needed
export { DataSourceToggle } from '@interzept/interzept-environment-selector'

Why use wrappers?

  • Add feature flags or environment checks
  • Apply custom styling or theming
  • Set default props or behaviors
  • Add logging, analytics, or permission checks
  • Keep your app's import paths stable

Other developers can import from your wrapper instead of the package directly if they need custom logic. For most use cases, importing directly from the package is fine.

2. Add the toggle to your sidebar

Choose the version that fits your project:

Option A: With Tailwind CSS

// components/sidebar.tsx
import { DataSourceToggle } from '@interzept/interzept-environment-selector'

export function Sidebar() {
  return (
    <nav>
      <DataSourceToggle />
    </nav>
  )
}

Then configure Tailwind to scan the package:

// tailwind.config.js
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx}',
    './node_modules/@interzept/interzept-environment-selector/dist/**/*.{js,mjs}'
  ],
}

Option B: Without Tailwind (Plain CSS)

// components/sidebar.tsx
import { DataSourceToggleUnstyled } from '@interzept/interzept-environment-selector/unstyled'
import '@interzept/interzept-environment-selector/styles.css'

export function Sidebar() {
  return (
    <nav>
      <DataSourceToggleUnstyled />
    </nav>
  )
}

No configuration needed! Works in any React project.

3. Use in your components

// components/my-component.tsx
import { useDataSource, useMockData } from '@interzept/interzept-environment-selector'

export function MyComponent() {
  const isMockMode = useMockData()
  const { getApiBaseUrls } = useDataSource()
  
  useEffect(() => {
    if (isMockMode) {
      setData(MOCK_DATA)
      return
    }
    
    // Fetch from all selected sources in parallel
    const urls = getApiBaseUrls()
    const results = await Promise.allSettled(
      urls.map(url => fetch(`${url}/api/endpoint?tenantId=${tenantId}`))
    )
    
    // Merge all successful results
    const allData = []
    results.forEach((result) => {
      if (result.status === 'fulfilled') {
        allData.push(...result.value.data)
      }
    })
    
    setData(allData)
  }, [isMockMode, getApiBaseUrls])
  
  return <div>{/* Your UI */}</div>
}

Environment Configuration

Create a .env.local file:

# Data source configuration
NEXT_PUBLIC_DATA_SOURCE=local

# Feature flag (optional - enabled by default in dev)
# NEXT_PUBLIC_ENABLE_DATA_SOURCE_TOGGLE=false

# Production safety (optional - recommended)
NEXT_PUBLIC_PRODUCTION_READ_ONLY=true

# Environment-specific API URLs
NEXT_PUBLIC_DEV_API_URL=https://dev-api.yourapp.com
NEXT_PUBLIC_UAT_API_URL=https://uat-api.yourapp.com
NEXT_PUBLIC_PROD_API_URL=https://api.yourapp.com

Data Sources

| Source | Description | Icon | Use Case | |--------|-------------|------|----------| | Mock | Static test data | 🧪 | UI development without backend | | Local | Local Supabase/DB | 💾 | Feature development | | Dev | Preview environment | 🖥️ | Testing commits/PRs | | UAT | Main branch | 🏢 | Pre-production testing | | Production | Release branch | 🌐 | Live data (read-only by default) |

API Reference

DataSourceProvider

Wraps your app to provide data source context.

<DataSourceProvider>
  {children}
</DataSourceProvider>

useDataSource()

Access data source state and methods.

const {
  selectedSources,      // DataSourceMode[] - Currently selected sources
  toggleSource,         // (mode: DataSourceMode) => void - Toggle a source
  setSelectedSources,   // (modes: DataSourceMode[]) => void - Set sources
  useMockData,          // () => boolean - Is mock mode active?
  getApiBaseUrls,       // () => string[] - Get all selected API URLs
  primarySource,        // DataSourceMode - First selected source
  isProductionReadOnly, // boolean - Is production read-only?
  canShowToggle,        // boolean - Should toggle be visible?
} = useDataSource()

useMockData()

Shorthand to check if mock mode is active.

const isMockMode = useMockData()

useApiData()

Check if any real API source is selected.

const hasApiData = useApiData()

DataSourceToggle / DataSourceToggleUnstyled

UI component for source selection. Choose based on your styling preference:

// Tailwind version (requires Tailwind CSS setup)
import { DataSourceToggle } from '@interzept/interzept-environment-selector'
<DataSourceToggle />

// Plain CSS version (works everywhere)
import { DataSourceToggleUnstyled } from '@interzept/interzept-environment-selector/unstyled'
import '@interzept/interzept-environment-selector/styles.css'
<DataSourceToggleUnstyled />

Styling & Customization

Tailwind Version

Uses Tailwind utility classes. Requires:

  1. Tailwind CSS configured in your project
  2. Package path added to Tailwind content config
  3. lucide-react installed

Plain CSS Version

Uses standalone CSS with class prefix dst-*. To customize:

/* Override in your own CSS file */
.dst-container {
  margin-bottom: 2rem !important;
}

.dst-header {
  color: #your-color !important;
}

.dst-item-button:hover {
  background-color: #your-hover-color !important;
}

Available CSS Classes:

  • .dst-container - Main wrapper
  • .dst-header - Collapsible header button
  • .dst-badge - "Internal" badge
  • .dst-item-button - Each data source button
  • .dst-icon-purple, .dst-icon-blue, .dst-icon-green, .dst-icon-amber, .dst-icon-red - Icon colors
  • .dst-footer - Footer with selection count

Comparison

| Feature | Tailwind (DataSourceToggle) | Plain CSS (DataSourceToggleUnstyled) | |---------|-------------------------------|----------------------------------------| | Setup | Requires Tailwind config | Import CSS once | | Customization | Tailwind classes or wrapper | CSS overrides with !important | | Bundle Size | Smaller (utility classes) | Includes compiled CSS (~3KB) | | Best For | Tailwind projects | Any React project |

Production Deployment

The toggle automatically hides in production when:

  • NODE_ENV === 'production' AND
  • NEXT_PUBLIC_VERCEL_ENV === 'production'

Deployment Visibility Matrix

| Environment | Toggle Visible? | Production Selectable? | |-------------|-----------------|------------------------| | Local dev | ✅ Always | 🔒 No (if read-only enabled) | | Vercel Preview | ✅ Always | 🔒 No (if read-only enabled) | | Vercel Production | ❌ Never | ❌ Never |

Advanced Usage

Custom Environment URLs

const API_URLS = {
  local: process.env.NEXT_PUBLIC_LOCAL_URL || 'http://localhost:55321',
  dev: process.env.NEXT_PUBLIC_DEV_API_URL || 'https://dev.api.com',
  // ...
}

Fetching from Multiple Sources

async function fetchMultiSource(endpoint: string) {
  const { getApiBaseUrls } = useDataSource()
  const urls = getApiBaseUrls()
  
  const results = await Promise.allSettled(
    urls.map(baseUrl => 
      fetch(`${baseUrl}${endpoint}`)
        .then(res => res.json())
    )
  )
  
  // Handle results
  const allData = results
    .filter(r => r.status === 'fulfilled')
    .flatMap(r => r.value.data)
  
  return allData
}

Conditional Rendering

const { canShowToggle } = useDataSource()

return (
  <nav>
    {canShowToggle && <DataSourceToggle />}
  </nav>
)

TypeScript

Full TypeScript support included:

import type { DataSourceMode } from '@interzept/interzept-environment-selector'

type DataSourceMode = 'mock' | 'local' | 'dev' | 'uat' | 'production'

Contributing

Contributions welcome!

License

MIT

Credits

Built with ❤️ for developers who need to test across multiple environments simultaneously.

Check out other Interzept projects:


Need help? Open an issue on GitHub