Skip to main content

Feature Flags

Flo uses database-backed feature flags to control functionality at runtime. Flags can be toggled by admins without redeployment.

Available Flags

FlagControls
enable_bookingsBooking/scheduling system
enable_dynamic_entitiesDynamic entity management (SchemaGen)
enable_user_managementUser administration panel
enable_professionalsStaff/professional management
enable_services_managementService/activity management
enable_blogsBlog content management (Strapi)
enable_newsletterNewsletter subscription and sending
enable_galleryMedia gallery
enable_closure_managementStudio closure/holiday management
enable_analyticsBusiness analytics dashboard
enable_sidebar_v2New collapsible sidebar with GSAP animations
enable_immobiliReal estate bounded context

How It Works

Backend

Feature flags are stored in the database and checked via FeatureFlagsHelper:

if (!FeatureFlagsHelper.IsFeatureEnabled(featureFlags, "enable_bookings"))
return NotFound();

Flags are loaded from the database on each request and cached for 5 minutes (ResponseCache).

Frontend

Flags are fetched before authentication during APP_INITIALIZER. This means the UI can hide/show features even before the user logs in.

Routes are protected using FeatureFlagGuard:

{
path: 'prenotazioni',
canActivate: [FeatureFlagGuard],
data: { ff: 'enable_bookings' }
}

The sidebar dynamically shows/hides menu items based on active flags.

Admin Panel

Admins can toggle feature flags from Settings > Feature Flags in the admin panel. Changes take effect immediately (after the 5-minute cache expires, or on next page reload).

Adding a New Feature Flag

  1. Database: Add the flag name to the feature flags table via migration or admin panel
  2. Backend: Check the flag in relevant controllers/services using FeatureFlagsHelper
  3. Frontend: Add FeatureFlagGuard to routes and conditionally render UI elements
  4. Sidebar: Update sidebar configuration to include/exclude menu items based on the flag

Bounded Context Flags

For the dynamic entity system, bounded contexts have their own enable flag:

  • enable_dynamic_entities must be ON (master switch)
  • enable_<boundedContext> must also be ON (e.g., enable_immobili for real estate)

Both must be active for a bounded context's entities to load at runtime.