Skip to main content

Browser Utils

Browser environment detection and URL manipulation utilities for the WorkPayCore frontend application.

Domain Functions

getSubdomain()

Extracts the subdomain and domain from the current window location.

Parameters: None (uses window.location.hostname)

Returns:

  • object: Object containing subdomain and domain properties
    • subdomain (string | null): The subdomain part
    • domain (string | null): The domain part

Example:

// Current URL: https://dashboard.myworkpay.com/users
const { subdomain, domain } = getSubdomain();
// Returns: { subdomain: 'dashboard', domain: 'myworkpay.com' }

// Current URL: https://myworkpay.com/login
const { subdomain, domain } = getSubdomain();
// Returns: { subdomain: null, domain: 'myworkpay.com' }

// Invalid/missing hostname
const { subdomain, domain } = getSubdomain();
// Returns: { subdomain: null, domain: null }

Use Cases:

  • Multi-tenant application routing
  • Subdomain-based feature toggling
  • Environment-specific configurations
  • Analytics and tracking based on subdomain

Environment Detection

isProd

Boolean constant indicating if the application is running in production mode.

Type: boolean

Example:

import { isProd } from '@/utils/browser';

if (isProd) {
// Production-specific code
console.log('Running in production mode');
initAnalytics();
} else {
// Development-specific code
console.log('Running in development mode');
}

// Conditional API endpoints
const apiUrl = isProd ? 'https://api.workpay.com' : 'http://localhost:3000';

Use Cases:

  • Environment-specific configurations
  • Conditional logging
  • Feature flags based on environment
  • API endpoint selection

isDev

Boolean constant indicating if the application is running in development mode.

Type: boolean

Example:

import { isDev } from '@/utils/browser';

if (isDev) {
// Development-only features
window.debugUtils = {
/* debug utilities */
};
console.log('Development mode active');
}

// Development-only debugging
const logApiCall = (url, data) => {
if (isDev) {
console.log('API Call:', url, data);
}
};

Use Cases:

  • Development-only debugging
  • Hot reload configurations
  • Development tools integration
  • Verbose logging

Usage Examples

Environment-Based Configuration

import { isProd, isDev } from '@/utils/browser';

const config = {
apiUrl: isProd ? 'https://api.workpay.com' : 'http://localhost:3000',
logLevel: isDev ? 'debug' : 'error',
enableAnalytics: isProd,
enableDevTools: isDev,
timeout: isProd ? 30000 : 5000,
};

Subdomain-Based Routing

import { getSubdomain } from '@/utils/browser';

const AppRouter = () => {
const { subdomain, domain } = getSubdomain();

// Route based on subdomain
switch (subdomain) {
case 'dashboard':
return <DashboardApp />;
case 'admin':
return <AdminApp />;
case 'api':
return <ApiDocumentation />;
default:
return <PublicSite />;
}
};

Multi-Tenant Configuration

import { getSubdomain } from '@/utils/browser';

const useTenantConfig = () => {
const { subdomain } = getSubdomain();

const tenantConfigs = {
'company-a': {
theme: 'blue',
features: ['payroll', 'hr', 'analytics'],
logo: '/logos/company-a.png',
},
'company-b': {
theme: 'green',
features: ['payroll', 'hr'],
logo: '/logos/company-b.png',
},
};

return tenantConfigs[subdomain] || tenantConfigs.default;
};

Conditional Feature Loading

import { isProd, isDev, getSubdomain } from '@/utils/browser';

const FeatureProvider = ({ children }) => {
const { subdomain } = getSubdomain();

const features = {
analytics: isProd && subdomain !== 'demo',
debugTools: isDev,
betaFeatures: subdomain === 'beta' || isDev,
advancedReporting: ['enterprise', 'premium'].includes(subdomain),
};

return (
<FeatureContext.Provider value={features}>
{children}
</FeatureContext.Provider>
);
};

Environment-Specific Error Handling

import { isProd, isDev } from '@/utils/browser';

const errorHandler = (error, errorInfo) => {
if (isProd) {
// Production error handling
sendToLoggingService(error, errorInfo);
showUserFriendlyMessage();
}

if (isDev) {
// Development error handling
console.error('Error:', error);
console.error('Error Info:', errorInfo);
// Show detailed error in dev mode
}
};

API Configuration Based on Environment

import { isProd, getSubdomain } from '@/utils/browser';

const createApiClient = () => {
const { subdomain } = getSubdomain();

const baseURL = isProd
? `https://${subdomain}-api.workpay.com`
: 'http://localhost:3001';

return axios.create({
baseURL,
timeout: isProd ? 30000 : 5000,
headers: {
'X-Tenant': subdomain,
},
});
};

Error Handling

The browser utilities handle edge cases gracefully:

  • Missing hostname: Returns null values instead of throwing errors
  • Invalid URL structure: Safely handles malformed URLs
  • Environment detection: Uses Vite's built-in environment detection

Performance Considerations

  • getSubdomain(): O(1) - simple string operations
  • isProd/isDev: O(1) - constant values set at build time
  • URL parsing: Minimal overhead using native browser APIs

Security Considerations

  • Subdomain validation: Consider validating subdomains against allowed values
  • Environment exposure: Be careful not to expose sensitive development information in production
  • Tenant isolation: Ensure proper isolation between different subdomains in multi-tenant setups


TypeScript Definitions

interface SubdomainInfo {
subdomain: string | null;
domain: string | null;
}

export function getSubdomain(): SubdomainInfo;
export const isProd: boolean;
export const isDev: boolean;

Build-Time Constants

These utilities depend on Vite's environment variables:

// Set at build time by Vite
import.meta.env.PROD; // Used for isProd
import.meta.env.DEV; // Used for isDev