featurely-site-manager
v1.1.1
Published
Complete site management SDK for maintenance mode, status messages, feature flags, version checking, and analytics
Maintainers
Readme
featurely-site-manager
Powerful site management SDK for controlling maintenance mode, displaying status messages, and managing site-wide features from your Featurely dashboard.
📦 Installation
npm install featurely-site-manager🚀 Quick Start
import { SiteManager } from "featurely-site-manager";
const siteManager = new SiteManager({
apiKey: "your-featurely-api-key",
projectId: "your-project-id",
});
siteManager.init();✨ Features
🔧 Maintenance Mode
- Default or custom maintenance pages
- Expected restoration time countdown
- Status page links
- Smart whitelist system:
- localStorage keys
- Email addresses
- Custom bypass functions
📢 Status Messages
- Multiple message types: info, warning, error, success
- Flexible positioning: top, bottom banners or toast notifications
- Dismissible messages with persistence
- Scheduled messages (start/end times)
- Page targeting (show on specific URLs)
- Call-to-action buttons
- Auto-expire functionality
🚀 Version Management
- Automatic version checking
- Force updates for critical releases (minimum version)
- Recommended version notifications
- Configurable check intervals (default: 1 hour)
- Release notes and download URLs
- Beta version support
- Update callbacks for custom UI
🔐 Feature Flags
- Enable/disable features remotely
- Percentage-based rollouts
- User targeting by email
- A/B testing with variants
- Consistent user bucketing
📊 Analytics
- Track custom events
- Automatic feature flag usage tracking
- Session management
- User identification
📖 Usage
Basic Setup
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
});
manager.init();With User Context
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
userEmail: "[email protected]", // For whitelist checks
});
manager.init();
// Update user later
manager.setUser("[email protected]");With Callbacks
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
onMaintenanceEnabled: (config) => {
console.log("Maintenance mode enabled:", config);
// Track in analytics
},
onMaintenanceDisabled: () => {
console.log("Site is back online!");
},
onMessageReceived: (message) => {
console.log("New message:", message);
},
onError: (error) => {
console.error("Site Manager error:", error);
},
});
manager.init();Custom Maintenance Bypass
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
bypassCheck: () => {
// Custom logic - e.g., check if user is admin
return window.location.search.includes("admin=true");
},
});
manager.init();Version Checking
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
appVersion: "1.2.3", // Your current app version
enableVersionCheck: true,
versionCheckInterval: 3600000, // Check every hour (default)
onUpdateAvailable: (versionInfo) => {
console.log("Update available:", versionInfo.latestVersion);
// Show optional update notification to user
},
onUpdateRequired: (versionInfo) => {
console.log("Update required:", versionInfo.latestVersion);
// Force user to update (breaking changes)
if (confirm(`Update required: ${versionInfo.latestVersion.title}\n\n${versionInfo.latestVersion.releaseNotes}`)) {
window.location.href = versionInfo.latestVersion.downloadUrl || '/update';
}
},
});
manager.init();
// Manual version check
const versionStatus = await manager.checkVersion();
if (versionStatus?.updateAvailable) {
console.log("New version:", versionStatus.latestVersion);
}Feature Flags
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
userEmail: "[email protected]",
onFeatureFlagsUpdated: (flags) => {
console.log("Feature flags updated:", flags);
},
});
manager.init();
// Check if a feature is enabled
if (manager.isFeatureEnabled("new-checkout")) {
// Show new checkout UI
}
// Get A/B test variant
const variant = manager.getFeatureVariant("homepage-design");
if (variant === "variant-a") {
// Show design A
}
// Get all enabled features
const enabledFeatures = manager.getEnabledFeatures();
console.log("Enabled features:", enabledFeatures);Analytics
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
userId: "user_123",
enableAnalytics: true,
analyticsFlushInterval: 60000, // Flush every minute
});
manager.init();
// Track custom events
manager.trackEvent("button_clicked", {
button: "signup",
page: "/home",
});
manager.trackEvent("feature_used", {
feature: "dark_mode",
enabled: true,
});Custom Poll Interval
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
pollInterval: 30000, // Check every 30 seconds instead of default 60s
});
manager.init();🔧 Configuration
SiteManagerConfig
| Option | Type | Required | Default | Description |
| ------------------------ | --------------- | -------- | ------------------------- | ----------------------------------------- |
| apiKey | string | ✅ | - | Your Featurely API key |
| projectId | string | ✅ | - | Your Featurely project ID |
| apiUrl | string | ❌ | 'https://featurely.no' | Custom API endpoint |
| pollInterval | number | ❌ | 60000 | Config polling interval in ms |
| userEmail | string | ❌ | - | User email for whitelist & targeting |
| userId | string | ❌ | - | User ID for analytics & feature flags |
| bypassCheck | () => boolean | ❌ | - | Custom maintenance bypass function |
| onMaintenanceEnabled | function | ❌ | - | Maintenance enabled callback |
| onMaintenanceDisabled | function | ❌ | - | Maintenance disabled callback |
| onMessageReceived | function | ❌ | - | Message received callback |
| onMessageDismissed | function | ❌ | - | Message dismissed callback |
| onFeatureFlagsUpdated | function | ❌ | - | Feature flags updated callback |
| enableAnalytics | boolean | ❌ | true | Enable analytics tracking |
| analyticsFlushInterval | number | ❌ | 60000 | Analytics flush interval in ms |
| appVersion | string | ❌ | - | Current app version for version checking |
| enableVersionCheck | boolean | ❌ | false | Enable automatic version checking |
| versionCheckInterval | number | ❌ | 3600000 | Version check interval in ms (1 hour) |
| onUpdateAvailable | function | ❌ | - | Callback when update is available |
| onUpdateRequired | function | ❌ | - | Callback when update is required (forced) |
| onError | function | ❌ | - | Error callback |
🎯 API Methods
Core Methods
init()
Initialize and start the site manager.
await manager.init();setUser(email: string, userId?: string)
Update user email and ID for whitelist and targeting.
manager.setUser("[email protected]", "user_123");refresh()
Manually refresh configuration from server.
await manager.refresh();destroy()
Stop the manager and clean up.
manager.destroy();Version Management Methods
checkVersion(currentVersion?: string)
Manually check if an update is available.
const versionInfo = await manager.checkVersion();
if (versionInfo?.updateAvailable) {
console.log("Update available:", versionInfo.latestVersion);
console.log("Is required?", versionInfo.updateRequired);
console.log("Is recommended?", versionInfo.updateRecommended);
}
// Check a specific version
const customCheck = await manager.checkVersion("1.0.0");getLastVersionCheck()
Get the last cached version check result.
const lastCheck = manager.getLastVersionCheck();
if (lastCheck?.updateAvailable) {
// Show update notification
}Feature Flag Methods
isFeatureEnabled(flagKey: string)
Check if a feature flag is enabled for the current user.
if (manager.isFeatureEnabled("new-dashboard")) {
// Show new dashboard
}getFeatureVariant(flagKey: string)
Get the assigned variant for A/B testing.
const variant = manager.getFeatureVariant("homepage-redesign");
// Returns: 'control', 'variant-a', 'variant-b', etc.getAllFeatureFlags()
Get all feature flags.
const flags = manager.getAllFeatureFlags();
console.log("All flags:", flags);getEnabledFeatures()
Get all enabled feature flag keys for the current user.
const enabledFeatures = manager.getEnabledFeatures();
// Returns: ['feature-1', 'feature-2', ...]Analytics Methods
trackEvent(eventName: string, properties?: object)
Track a custom analytics event.
manager.trackEvent("button_clicked", {
button: "signup",
page: "/pricing",
});
manager.trackEvent("purchase_completed", {
amount: 99.99,
currency: "USD",
plan: "pro",
});💼 Use Cases
Update Notifications
const manager = new SiteManager({
apiKey: "ft_live_...",
projectId: "proj_...",
appVersion: "1.2.3",
enableVersionCheck: true,
onUpdateRequired: (versionInfo) => {
// Block app usage until updated
document.body.innerHTML = `
<div style="text-align: center; padding: 60px;">
<h1>Critical Update Required</h1>
<p>${versionInfo.latestVersion.title}</p>
<p>${versionInfo.latestVersion.releaseNotes}</p>
<a href="${versionInfo.latestVersion.downloadUrl}">
<button>Download Update</button>
</a>
</div>
`;
},
onUpdateAvailable: (versionInfo) => {
// Show non-blocking notification
if (!versionInfo.latestVersion.isBeta) {
showToast(`Update available: ${versionInfo.latestVersion.version}`);
}
},
});Feature Rollouts
// Dashboard configuration
manager.init();
// Gradually enable new checkout for 20% of users
if (manager.isFeatureEnabled("new-checkout-v2")) {
loadNewCheckout();
} else {
loadLegacyCheckout();
}
// A/B test with variants
const buttonColor = manager.getFeatureVariant("cta-button-color");
switch (buttonColor) {
case "green":
setButtonColor("#00CC66");
break;
case "blue":
setButtonColor("#0066CC");
break;
default:
setButtonColor("#FF6600"); // control
}Custom Poll Interval
const manager = new SiteManager({
apiKey: "ft_live_your_api_key",
projectId: "proj_your_project_id",
pollInterval: 30000, // Check every 30 seconds instead of default 60s
});
manager.init();🔧 Configuration
SiteManagerConfig
| Option | Type | Required | Default | Description |
| ----------------------- | --------------- | -------- | ------------------------- | ----------------------------- |
| apiKey | string | ✅ | - | Your Featurely API key |
| projectId | string | ✅ | - | Your Featurely project ID |
| apiUrl | string | ❌ | 'https://featurely.no' | Custom API endpoint |
| pollInterval | number | ❌ | 60000 | Polling interval in ms |
| userEmail | string | ❌ | - | User email for whitelist |
| bypassCheck | () => boolean | ❌ | - | Custom bypass function |
| onMaintenanceEnabled | function | ❌ | - | Maintenance enabled callback |
| onMaintenanceDisabled | function | ❌ | - | Maintenance disabled callback |
| onMessageReceived | function | ❌ | - | Message received callback |
| onMessageDismissed | function | ❌ | - | Message dismissed callback |
| onError | function | ❌ | - | Error callback |
🎯 API Methods
init()
Initialize and start the site manager.
await manager.init();setUser(email: string)
Update user email for whitelist checks.
manager.setUser("[email protected]");refresh()
Manually refresh configuration from server.
await manager.refresh();destroy()
Stop the manager and clean up.
manager.destroy();🎨 Maintenance Mode
Default Page
The SDK includes a beautiful default maintenance page with:
- Professional gradient background
- Maintenance icon
- Customizable messages
- Expected restoration time
- Optional status page link
Custom Page
Provide your own HTML:
// Set in Featurely dashboard:
{
"type": "custom",
"customHtml": "<div>Your custom HTML here</div>"
}Whitelist System
localStorage Keys: Users with specific localStorage keys bypass maintenance.
// In Featurely dashboard, set whitelist keys: ['featurely_admin', 'bypass_key']
// Users can set: localStorage.setItem('featurely_admin', 'true');Email Addresses: Specific users bypass maintenance.
// In Featurely dashboard: ['[email protected]', '[email protected]']
const manager = new SiteManager({
apiKey: "ft_live_...",
projectId: "proj_...",
userEmail: "[email protected]", // This user bypasses
});Custom Function: Complex bypass logic.
const manager = new SiteManager({
apiKey: "ft_live_...",
projectId: "proj_...",
bypassCheck: () => {
// E.g., check if admin query param is present
return new URLSearchParams(window.location.search).get("admin") === "true";
},
});📢 Status Messages
Messages are managed from your Featurely dashboard and automatically displayed based on:
- Start/end times
- Target pages (URL patterns)
- Message type and priority
Message Types
- info (blue) - Informational messages
- warning (orange) - Warnings and alerts
- error (red) - Critical errors
- success (green) - Success notifications
Message Styles
- banner - Full-width top or bottom banner
- toast - Small notification in corner
Example Message Configuration
{
"id": "msg_123",
"type": "warning",
"title": "Scheduled Maintenance",
"message": "We'll be performing maintenance tonight at 3 AM EST.",
"position": "top",
"style": "banner",
"dismissible": true,
"startsAt": "2026-03-14T10:00:00Z",
"expiresAt": "2026-03-15T03:00:00Z",
"cta": {
"text": "Learn More",
"url": "/maintenance-info"
}
}🌐 Framework Integration
React
import { useEffect } from "react";
import { SiteManager } from "featurely-site-manager";
function App() {
useEffect(() => {
const manager = new SiteManager({
apiKey: process.env.REACT_APP_FEATURELY_API_KEY!,
projectId: process.env.REACT_APP_FEATURELY_PROJECT_ID!,
});
manager.init();
return () => manager.destroy();
}, []);
return <div>Your app</div>;
}Next.js
// app/layout.tsx
"use client";
import { useEffect } from "react";
import { SiteManager } from "featurely-site-manager";
export default function RootLayout({ children }) {
useEffect(() => {
if (typeof window === "undefined") return;
const manager = new SiteManager({
apiKey: process.env.NEXT_PUBLIC_FEATURELY_API_KEY!,
projectId: process.env.NEXT_PUBLIC_FEATURELY_PROJECT_ID!,
});
manager.init();
return () => manager.destroy();
}, []);
return (
<html>
<body>{children}</body>
</html>
);
}Vue
<script setup>
import { onMounted, onUnmounted } from "vue";
import { SiteManager } from "featurely-site-manager";
let manager = null;
onMounted(() => {
manager = new SiteManager({
apiKey: import.meta.env.VITE_FEATURELY_API_KEY,
projectId: import.meta.env.VITE_FEATURELY_PROJECT_ID,
});
manager.init();
});
onUnmounted(() => {
manager?.destroy();
});
</script>🌐 Environment Variables
React/Vite:
VITE_FEATURELY_API_KEY=ft_live_your_key
VITE_FEATURELY_PROJECT_ID=proj_your_idNext.js:
NEXT_PUBLIC_FEATURELY_API_KEY=ft_live_your_key
NEXT_PUBLIC_FEATURELY_PROJECT_ID=proj_your_id🎨 Styling
The SDK injects minimal, scoped styles. All classes are prefixed with featurely- to avoid conflicts.
Custom Styling
Override default styles:
/* Customize maintenance page */
.featurely-maintenance-overlay {
background: linear-gradient(to right, #your #colors) !important;
}
/* Customize messages */
.featurely-message-info {
background: #your-color !important;
}📊 Dashboard Management
Manage all settings from your Featurely dashboard at:
https://featurely.no/dashboard/settings → Site Management tab
Maintenance Mode Panel
- Toggle on/off
- Set expected restoration time
- Configure whitelist (emails, localStorage keys)
- Choose default or custom page
- Add status page link
Status Messages Panel
- Create new messages
- Set type, title, and content
- Schedule start/end times
- Target specific pages
- Add CTA buttons
- Set priority
🔒 Security
- API keys should be environment variables
- All requests use HTTPS
- Whitelist checks happen client-side (easily bypassable - use for convenience, not security)
- For true access control, implement server-side authentication
📱 Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Mobile browsers
📄 License
MIT License - see LICENSE file for details.
🔗 Links
💬 Support
- Open a GitHub issue
- Contact [email protected]
- Check the documentation
