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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@owlmeans/web-wl

v0.1.1

Published

Web-specific whitelabeling functionality for OwlMeans Common Libraries. This package provides React components and browser-optimized services for implementing client-side whitelabeling, enabling web applications to dynamically customize branding, theming,

Readme

@owlmeans/web-wl

Web-specific whitelabeling functionality for OwlMeans Common Libraries. This package provides React components and browser-optimized services for implementing client-side whitelabeling, enabling web applications to dynamically customize branding, theming, and content based on entity-specific configurations.

Overview

The @owlmeans/web-wl package serves as the web-specific implementation of the OwlMeans Whitelabeling Subsystem, designed for React-based frontend applications with focus on dynamic branding and user experience customization. It provides:

  • Web Whitelabeling Service: Browser-optimized service for loading and caching whitelabeling data
  • React Components: React components for whitelabel-aware UI elements
  • Caching Strategy: Efficient client-side caching of whitelabeling configurations
  • API Integration: Seamless integration with server-side whitelabeling providers
  • Performance Optimization: Optimized loading and rendering of dynamic branding content

This package follows the OwlMeans "quadra" pattern as the web implementation, complementing:

  • @owlmeans/wled: Common whitelabeling declarations and base functionality (base package)
  • @owlmeans/client-wl: Base client whitelabeling functionality
  • @owlmeans/server-wl: Server-side whitelabeling implementation
  • @owlmeans/web-wl: Web browser whitelabeling implementation (this package)

Installation

npm install @owlmeans/web-wl

Dependencies

This package requires and integrates with:

  • @owlmeans/wled: Core whitelabeling types and modules
  • @owlmeans/client: Base client functionality
  • @owlmeans/client-module: Client module system for API calls
  • @owlmeans/context: Context management and service registration
  • React: Peer dependency for web components

Key Concepts

Web Whitelabeling Service

Browser-optimized service that:

  • Loads Whitelabeling Data: Fetches entity-specific branding from server APIs
  • Caches Configurations: Implements client-side caching for performance
  • Extracts Data: Provides convenient access to specific whitelabeling data types
  • Handles Errors: Graceful error handling for failed whitelabeling requests

React Component Integration

React components that automatically adapt to whitelabeling configurations:

  • Dynamic Branding: Components that change appearance based on entity branding
  • Conditional Rendering: Show/hide content based on whitelabeling rules
  • Theme Integration: Automatic theme switching based on entity configurations
  • Performance: Optimized rendering with minimal re-renders

Client-side Caching

Efficient caching strategy:

  • Memory Caching: In-memory cache for frequently accessed configurations
  • Cache Invalidation: Smart cache invalidation strategies
  • Performance: Reduced API calls and improved user experience

API Reference

Factory Functions

makeWlService(alias?: string): WlWebService

Creates a web whitelabeling service instance with caching capabilities.

import { makeWlService } from '@owlmeans/web-wl'

const wlService = makeWlService('main-wl')
context.registerService(wlService)

Parameters:

  • alias: Optional service alias (defaults to DEFAULT_ALIAS)

Returns: WlWebService - Web whitelabeling service instance

Core Interfaces

WlWebService

Web-specific whitelabeling service interface.

interface WlWebService extends InitializedService {
  load: (entityId: string) => Promise<ProvidedWLSet>
  extract: <T>(key: string, set: ProvidedWLSet) => T | undefined
}

Methods:

load(entityId: string): Promise<ProvidedWLSet>

  • Purpose: Load complete whitelabeling data set for an entity
  • Parameters: entityId - Entity identifier
  • Returns: Promise resolving to whitelabeling data set
  • Behavior:
    • Checks cache first for existing data
    • Makes API call to server if not cached
    • Caches successful responses
    • Returns comprehensive whitelabeling data

extract<T>(key: string, set: ProvidedWLSet): T | undefined

  • Purpose: Extract specific whitelabeling data type from a data set
  • Parameters:
    • key - Provider key (e.g., 'company-provider', 'styles-provider')
    • set - Whitelabeling data set
  • Returns: Extracted data of type T or undefined if not found
  • Usage: Convenient access to specific provider data

ProvidedWLSet

Collection of whitelabeling data from multiple providers.

interface ProvidedWLSet<T extends Record<string, any> = Record<string, any>> {
  [providerKey: string]: ProvidedWL<T>
}

Config

Configuration interface for web whitelabeling.

interface Config extends ClientConfig {
  // Inherits client configuration
  // Plus whitelabeling-specific web settings
}

Context<C extends Config = Config>

Web context interface with whitelabeling support.

interface Context<C extends Config = Config> extends ClientContext<C> {
  // Inherits client context functionality
  // With typed configuration for whitelabeling
}

React Components

Whitelabeling Provider Component

interface WlProviderProps {
  entityId: string                    // Entity to load whitelabeling for
  children: React.ReactNode          // Child components
  fallback?: React.ReactNode         // Fallback content while loading
  onError?: (error: Error) => void   // Error handler
}

const WlProvider: FC<WlProviderProps> = (props) => { /* ... */ }

Whitelabel-aware Components

interface WlBrandProps {
  entityId: string
  type: 'square' | 'wide'           // Logo type
  alt?: string                      // Alt text
  fallback?: React.ReactNode        // Fallback if no logo
}

const WlBrand: FC<WlBrandProps> = (props) => { /* ... */ }

interface WlThemeProps {
  entityId: string
  children: React.ReactNode
}

const WlTheme: FC<WlThemeProps> = (props) => { /* ... */ }

Constants

DEFAULT_ALIAS

Default service alias for whitelabeling service.

const DEFAULT_ALIAS = 'wl-web-service'

Usage Examples

Basic Web Whitelabeling Setup

import { makeWlService } from '@owlmeans/web-wl'
import { makeWebContext } from '@owlmeans/web-client'

// Create web context
const context = makeWebContext(config)

// Create and register whitelabeling service
const wlService = makeWlService()
context.registerService(wlService)

// Initialize context
await context.configure().init()

// Load whitelabeling data for an entity
const entityId = 'company-123'
const whitelabelData = await wlService.load(entityId)

console.log('Whitelabeling data:', whitelabelData)

React Component Integration

import React, { useEffect, useState } from 'react'
import { useContext } from '@owlmeans/client'
import type { WlWebService, ProvidedWLSet } from '@owlmeans/web-wl'
import type { CompanyInfo, CustomStyles, CustomMedia } from '@owlmeans/wled'

interface WhitelabeledAppProps {
  entityId: string
  children: React.ReactNode
}

const WhitelabeledApp: React.FC<WhitelabeledAppProps> = ({ entityId, children }) => {
  const context = useContext()
  const [whitelabelData, setWhitelabelData] = useState<ProvidedWLSet | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<Error | null>(null)

  useEffect(() => {
    const loadWhitelabeling = async () => {
      try {
        setLoading(true)
        const wlService = context.service<WlWebService>('wl-web-service')
        const data = await wlService.load(entityId)
        setWhitelabelData(data)
      } catch (err) {
        setError(err as Error)
      } finally {
        setLoading(false)
      }
    }

    loadWhitelabeling()
  }, [entityId, context])

  if (loading) {
    return <div>Loading branding...</div>
  }

  if (error) {
    return <div>Error loading branding: {error.message}</div>
  }

  if (!whitelabelData) {
    return <div>No branding data available</div>
  }

  // Extract specific whitelabeling data
  const wlService = context.service<WlWebService>('wl-web-service')
  const companyInfo = wlService.extract<CompanyInfo>('company-provider', whitelabelData)
  const customStyles = wlService.extract<CustomStyles>('styles-provider', whitelabelData)
  const customMedia = wlService.extract<CustomMedia>('media-provider', whitelabelData)

  return (
    <WhitelabelThemeProvider styles={customStyles}>
      <div className="whitelabeled-app">
        <header>
          {customMedia?.brand?.wideLogo && (
            <img 
              src={customMedia.brand.wideLogo} 
              alt={companyInfo?.fullName || 'Logo'} 
              className="company-logo"
            />
          )}
          <h1>{companyInfo?.fullName || 'Application'}</h1>
        </header>
        
        <main>
          {children}
        </main>
        
        <footer>
          <p>{companyInfo?.description}</p>
        </footer>
      </div>
    </WhitelabelThemeProvider>
  )
}

Dynamic Theme Application

import React, { useMemo } from 'react'
import { ThemeProvider, createTheme } from '@mui/material/styles'
import type { CustomStyles } from '@owlmeans/wled'

interface WhitelabelThemeProviderProps {
  styles?: CustomStyles
  children: React.ReactNode
}

const WhitelabelThemeProvider: React.FC<WhitelabelThemeProviderProps> = ({ 
  styles, 
  children 
}) => {
  const theme = useMemo(() => {
    const baseTheme = createTheme()

    if (!styles) {
      return baseTheme
    }

    return createTheme({
      ...baseTheme,
      palette: {
        ...baseTheme.palette,
        primary: {
          main: styles.colors.primaryColor,
          contrastText: '#ffffff'
        },
        secondary: {
          main: styles.colors.secondaryColor || baseTheme.palette.secondary.main
        },
        background: {
          default: styles.colors.primaryBackground || baseTheme.palette.background.default,
          paper: styles.colors.secondaryBackground || baseTheme.palette.background.paper
        }
      },
      typography: {
        ...baseTheme.typography,
        fontFamily: styles.font.fontFamily || baseTheme.typography.fontFamily,
        fontSize: styles.font.basicSize || baseTheme.typography.fontSize
      }
    })
  }, [styles])

  return (
    <ThemeProvider theme={theme}>
      {children}
    </ThemeProvider>
  )
}

Whitelabel-aware Components

import React from 'react'
import { useContext } from '@owlmeans/client'
import type { WlWebService } from '@owlmeans/web-wl'
import type { CustomMedia } from '@owlmeans/wled'

interface CompanyLogoProps {
  entityId: string
  type?: 'square' | 'wide'
  className?: string
  alt?: string
}

const CompanyLogo: React.FC<CompanyLogoProps> = ({ 
  entityId, 
  type = 'wide', 
  className,
  alt = 'Company Logo'
}) => {
  const context = useContext()
  const [logoUrl, setLogoUrl] = React.useState<string | null>(null)

  React.useEffect(() => {
    const loadLogo = async () => {
      try {
        const wlService = context.service<WlWebService>('wl-web-service')
        const whitelabelData = await wlService.load(entityId)
        const mediaData = wlService.extract<CustomMedia>('media-provider', whitelabelData)
        
        const logo = type === 'square' 
          ? mediaData?.brand?.squareLogo 
          : mediaData?.brand?.wideLogo
          
        setLogoUrl(logo || null)
      } catch (error) {
        console.error('Failed to load company logo:', error)
        setLogoUrl(null)
      }
    }

    loadLogo()
  }, [entityId, type, context])

  if (!logoUrl) {
    return (
      <div className={`company-logo-placeholder ${className || ''}`}>
        {alt}
      </div>
    )
  }

  return (
    <img 
      src={logoUrl} 
      alt={alt} 
      className={`company-logo ${className || ''}`}
    />
  )
}

// Usage
<CompanyLogo 
  entityId="company-123" 
  type="wide" 
  className="header-logo"
  alt="Acme Corporation"
/>

Custom Hook for Whitelabeling

import { useState, useEffect } from 'react'
import { useContext } from '@owlmeans/client'
import type { WlWebService, ProvidedWLSet } from '@owlmeans/web-wl'

interface UseWhitelabelResult<T = any> {
  data: T | null
  loading: boolean
  error: Error | null
  reload: () => void
}

export const useWhitelabel = <T = any>(
  entityId: string, 
  providerKey?: string
): UseWhitelabelResult<T> => {
  const context = useContext()
  const [data, setData] = useState<T | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<Error | null>(null)

  const loadData = async () => {
    try {
      setLoading(true)
      setError(null)
      
      const wlService = context.service<WlWebService>('wl-web-service')
      const whitelabelData = await wlService.load(entityId)
      
      if (providerKey) {
        const extracted = wlService.extract<T>(providerKey, whitelabelData)
        setData(extracted || null)
      } else {
        setData(whitelabelData as T)
      }
    } catch (err) {
      setError(err as Error)
      setData(null)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    loadData()
  }, [entityId, providerKey])

  return {
    data,
    loading,
    error,
    reload: loadData
  }
}

// Usage examples
const CompanyInfoDisplay: React.FC<{ entityId: string }> = ({ entityId }) => {
  const { data: companyInfo, loading, error } = useWhitelabel<CompanyInfo>(
    entityId, 
    'company-provider'
  )

  if (loading) return <div>Loading company info...</div>
  if (error) return <div>Error: {error.message}</div>
  if (!companyInfo) return <div>No company information available</div>

  return (
    <div>
      <h2>{companyInfo.fullName}</h2>
      <p>{companyInfo.description}</p>
    </div>
  )
}

const StylesDisplay: React.FC<{ entityId: string }> = ({ entityId }) => {
  const { data: styles, loading, error } = useWhitelabel<CustomStyles>(
    entityId, 
    'styles-provider'
  )

  if (loading || error || !styles) return null

  return (
    <div style={{
      backgroundColor: styles.colors.primaryBackground,
      color: styles.colors.primaryColor,
      fontFamily: styles.font.fontFamily
    }}>
      Custom styled content
    </div>
  )
}

Multi-entity Whitelabeling

import React, { useState } from 'react'
import { useWhitelabel } from './useWhitelabel'

const MultiEntityDemo: React.FC = () => {
  const [selectedEntity, setSelectedEntity] = useState('entity-1')
  
  const entities = [
    { id: 'entity-1', name: 'Company A' },
    { id: 'entity-2', name: 'Company B' },
    { id: 'entity-3', name: 'Company C' }
  ]

  const { data: whitelabelData, loading } = useWhitelabel(selectedEntity)

  return (
    <div>
      <select 
        value={selectedEntity} 
        onChange={(e) => setSelectedEntity(e.target.value)}
      >
        {entities.map(entity => (
          <option key={entity.id} value={entity.id}>
            {entity.name}
          </option>
        ))}
      </select>

      {loading ? (
        <div>Loading whitelabel data...</div>
      ) : (
        <WhitelabeledApp entityId={selectedEntity}>
          <div>Content for {selectedEntity}</div>
        </WhitelabeledApp>
      )}
    </div>
  )
}

Caching Strategy

Memory Cache Implementation

// Internal caching implementation (simplified)
class WhitelabelCache {
  private cache = new Map<string, ProvidedWLSet>()
  private ttl = 5 * 60 * 1000 // 5 minutes
  private timestamps = new Map<string, number>()

  set(entityId: string, data: ProvidedWLSet): void {
    this.cache.set(entityId, data)
    this.timestamps.set(entityId, Date.now())
  }

  get(entityId: string): ProvidedWLSet | undefined {
    const timestamp = this.timestamps.get(entityId)
    if (timestamp && Date.now() - timestamp > this.ttl) {
      this.cache.delete(entityId)
      this.timestamps.delete(entityId)
      return undefined
    }
    return this.cache.get(entityId)
  }

  clear(): void {
    this.cache.clear()
    this.timestamps.clear()
  }

  invalidate(entityId: string): void {
    this.cache.delete(entityId)
    this.timestamps.delete(entityId)
  }
}

Cache Management

// Utility functions for cache management
export const clearWhitelabelCache = (context: Context) => {
  const wlService = context.service<WlWebService>('wl-web-service')
  // Cache clearing would be implemented in the service
}

export const preloadWhitelabeling = async (
  context: Context, 
  entityIds: string[]
) => {
  const wlService = context.service<WlWebService>('wl-web-service')
  
  // Preload whitelabeling data for multiple entities
  await Promise.all(
    entityIds.map(entityId => wlService.load(entityId))
  )
}

Error Handling

Graceful Error Handling

const ErrorBoundaryWhitelabel: React.FC<{ 
  children: React.ReactNode
  fallback?: React.ReactNode 
}> = ({ children, fallback }) => {
  return (
    <ErrorBoundary
      fallback={fallback || <div>Failed to load branding</div>}
      onError={(error) => {
        console.error('Whitelabeling error:', error)
        // Report to error tracking service
      }}
    >
      {children}
    </ErrorBoundary>
  )
}

// Usage
<ErrorBoundaryWhitelabel fallback={<DefaultBranding />}>
  <WhitelabeledApp entityId={entityId}>
    <AppContent />
  </WhitelabeledApp>
</ErrorBoundaryWhitelabel>

Performance Optimization

Lazy Loading and Code Splitting

import React, { lazy, Suspense } from 'react'

// Lazy load whitelabel components
const WhitelabeledDashboard = lazy(() => import('./WhitelabeledDashboard'))

const App: React.FC = () => (
  <Suspense fallback={<div>Loading...</div>}>
    <WhitelabeledDashboard entityId="company-123" />
  </Suspense>
)

Memoization

import React, { memo, useMemo } from 'react'

const MemoizedWhitelabelComponent = memo<{ entityId: string }>(({ entityId }) => {
  const { data } = useWhitelabel(entityId, 'company-provider')
  
  const memoizedContent = useMemo(() => {
    if (!data) return null
    
    return (
      <div>
        <h1>{data.fullName}</h1>
        <p>{data.description}</p>
      </div>
    )
  }, [data])

  return memoizedContent
})

Integration with OwlMeans Ecosystem

Context Integration

import { makeWebContext } from '@owlmeans/web-client'

const context = makeWebContext(config)
const wlService = context.service<WlWebService>('wl-web-service')

Module System Integration

import { modules } from '@owlmeans/web-wl'

// Modules are automatically integrated via service
context.registerService(wlService)

Client Integration

import { useContext } from '@owlmeans/client'

const wlService = useContext().service<WlWebService>('wl-web-service')

Best Practices

  1. Caching: Implement appropriate caching strategies for performance
  2. Error Handling: Provide graceful fallbacks for failed whitelabeling requests
  3. Performance: Use memoization and lazy loading for large applications
  4. User Experience: Show loading states during whitelabeling data fetch
  5. Accessibility: Ensure dynamic content maintains accessibility standards
  6. Testing: Test with different entity configurations and error scenarios

Related Packages

  • @owlmeans/wled: Core whitelabeling types and modules
  • @owlmeans/client-wl: Base client whitelabeling functionality
  • @owlmeans/server-wl: Server-side whitelabeling implementation
  • @owlmeans/client: Base client functionality
  • @owlmeans/client-module: Client module system for API calls

TypeScript Support

This package is written in TypeScript and provides full type safety:

import type { 
  WlWebService,
  ProvidedWLSet,
  Config,
  Context
} from '@owlmeans/web-wl'

const wlService: WlWebService = makeWlService()
const context: Context = makeWebContext(config)