This document explains how to use the feature toggle system in Tracktor.
The feature toggle system allows you to enable or disable specific features throughout the application. This is useful for:
- Rolling out features gradually
- A/B testing
- Providing customization options to users
- Hiding incomplete features
The following features can be toggled:
- Fuel Log - Track and manage fuel consumption and refueling history
- Maintenance - Record and schedule vehicle maintenance activities
- PUCC - Manage Pollution Under Control Certificate records
- Reminders - Set and receive reminders for important vehicle events
- Insurance - Manage vehicle insurance details and renewals
- Overview - Display overview dashboard with key vehicle metrics
Features are configured through the Settings page under the "Features" tab. Each feature has a checkbox that can be toggled on or off.
Feature toggles are stored in the configs table with the following keys:
featureFuelLogfeatureMaintenancefeaturePuccfeatureRemindersfeatureInsurancefeatureOverview
Values are stored as strings: 'true' or 'false'
The easiest way to conditionally show/hide components based on feature flags:
<script>
import FeatureGate from '$lib/components/feature/FeatureGate.svelte';
</script>
<!-- Show component only if fuel log feature is enabled -->
<FeatureGate feature="fuelLog">
<FuelLogComponent />
</FeatureGate>
<!-- Require multiple features (all must be enabled) -->
<FeatureGate requireAll={['fuelLog', 'maintenance']}>
<CombinedView />
</FeatureGate>
<!-- Require at least one feature to be enabled -->
<FeatureGate requireAny={['insurance', 'pucc']}>
<DocumentsSection />
</FeatureGate>
<!-- With fallback content -->
<FeatureGate feature="overview">
{#snippet children()}
<OverviewDashboard />
{/snippet}
{#snippet fallback()}
<p>Overview feature is currently disabled</p>
{/snippet}
</FeatureGate>For more programmatic control:
import {
isFeatureEnabled,
Features,
getEnabledFeatures,
areAllFeaturesEnabled,
isAnyFeatureEnabled
} from '$lib/helper/feature.helper';
// Check if a single feature is enabled
if (isFeatureEnabled(Features.FUEL_LOG)) {
// Show fuel log functionality
}
// Get all enabled features
const enabledFeatures = getEnabledFeatures();
console.log('Enabled features:', enabledFeatures);
// Check if all features are enabled
if (areAllFeaturesEnabled([Features.FUEL_LOG, Features.MAINTENANCE])) {
// Show combined view
}
// Check if any feature is enabled
if (isAnyFeatureEnabled([Features.INSURANCE, Features.PUCC])) {
// Show documents section
}import { configStore } from '$stores/config.svelte';
// In a Svelte component
let showFuelLog = $derived(configStore.configs.featureFuelLog);You can use feature flags to conditionally show/hide navigation items:
<script>
import { configStore } from '$stores/config.svelte';
</script>
{#if configStore.configs.featureFuelLog}
<NavItem href="/fuel-log">Fuel Log</NavItem>
{/if}
{#if configStore.configs.featureMaintenance}
<NavItem href="/maintenance">Maintenance</NavItem>
{/if}- Always provide fallback UI - Consider what users should see when a feature is disabled
- Use semantic checks - Instead of checking multiple flags separately, use
requireAllorrequireAny - Keep flags granular - Each feature should be independently toggleable
- Document dependencies - If Feature B requires Feature A, document this relationship
- Test both states - Always test with features both enabled and disabled
To add a new feature toggle:
-
Create a migration to add the config:
INSERT INTO `configs` VALUES ('featureNewFeature','true','Description of the feature', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
-
Update the Config interface in src/lib/domain/config.ts:
export interface Configs { // ... existing fields featureNewFeature?: boolean; }
-
Update the config store in src/lib/stores/config.svelte.ts:
- Add default value
- Add case in switch statement
-
Update the schema in SettingsForm.svelte:
const configSchema = z.object({ // ... existing fields featureNewFeature: z.boolean().optional() });
-
Add checkbox to the Features tab in SettingsForm.svelte
-
Update the Features constant in src/lib/helper/feature.helper.ts:
export const Features = { // ... existing features NEW_FEATURE: 'newFeature' } as const;
Run migrations to apply the feature toggle configs:
pnpm db:push
# or
pnpm db:migrate