diff --git a/src/components/sidebar/SideToolbar.vue b/src/components/sidebar/SideToolbar.vue
index 44dff5fc2..d79de919f 100644
--- a/src/components/sidebar/SideToolbar.vue
+++ b/src/components/sidebar/SideToolbar.vue
@@ -50,6 +50,7 @@
+
@@ -66,6 +67,7 @@ import SidebarSettingsButton from '@/components/sidebar/SidebarSettingsButton.vu
import SidebarShortcutsToggleButton from '@/components/sidebar/SidebarShortcutsToggleButton.vue'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import { useSettingStore } from '@/platform/settings/settingStore'
+import NightlySurveyController from '@/platform/surveys/NightlySurveyController.vue'
import { useTelemetry } from '@/platform/telemetry'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCommandStore } from '@/stores/commandStore'
diff --git a/src/platform/surveys/NightlySurveyController.vue b/src/platform/surveys/NightlySurveyController.vue
new file mode 100644
index 000000000..d42ed89f4
--- /dev/null
+++ b/src/platform/surveys/NightlySurveyController.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/platform/surveys/useSurveyFeatureTracking.test.ts b/src/platform/surveys/useSurveyFeatureTracking.test.ts
new file mode 100644
index 000000000..a0c2c3b81
--- /dev/null
+++ b/src/platform/surveys/useSurveyFeatureTracking.test.ts
@@ -0,0 +1,61 @@
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+
+const mockSurveyConfigs: Record = {}
+
+vi.mock('./surveyRegistry', () => ({
+ getSurveyConfig: (featureId: string) => mockSurveyConfigs[featureId]
+}))
+
+describe('useSurveyFeatureTracking', () => {
+ beforeEach(() => {
+ localStorage.clear()
+ vi.resetModules()
+ Object.keys(mockSurveyConfigs).forEach(
+ (key) => delete mockSurveyConfigs[key]
+ )
+ })
+
+ afterEach(() => {
+ localStorage.clear()
+ })
+
+ it('tracks usage when config is enabled', async () => {
+ mockSurveyConfigs['test-feature'] = { enabled: true }
+
+ const { useSurveyFeatureTracking } =
+ await import('./useSurveyFeatureTracking')
+ const { trackFeatureUsed, useCount } =
+ useSurveyFeatureTracking('test-feature')
+
+ expect(useCount.value).toBe(0)
+
+ trackFeatureUsed()
+
+ expect(useCount.value).toBe(1)
+ })
+
+ it('does not track when config is disabled', async () => {
+ mockSurveyConfigs['disabled-feature'] = { enabled: false }
+
+ const { useSurveyFeatureTracking } =
+ await import('./useSurveyFeatureTracking')
+ const { trackFeatureUsed, useCount } =
+ useSurveyFeatureTracking('disabled-feature')
+
+ trackFeatureUsed()
+
+ expect(useCount.value).toBe(0)
+ })
+
+ it('does not track when config does not exist', async () => {
+ const { useSurveyFeatureTracking } =
+ await import('./useSurveyFeatureTracking')
+ const { trackFeatureUsed, useCount } = useSurveyFeatureTracking(
+ 'nonexistent-feature'
+ )
+
+ trackFeatureUsed()
+
+ expect(useCount.value).toBe(0)
+ })
+})
diff --git a/src/platform/surveys/useSurveyFeatureTracking.ts b/src/platform/surveys/useSurveyFeatureTracking.ts
new file mode 100644
index 000000000..72ac47edc
--- /dev/null
+++ b/src/platform/surveys/useSurveyFeatureTracking.ts
@@ -0,0 +1,30 @@
+import { getSurveyConfig } from './surveyRegistry'
+import { useFeatureUsageTracker } from './useFeatureUsageTracker'
+
+/**
+ * Convenience composable for tracking feature usage for surveys.
+ * Use this at the feature site to track when a feature is used.
+ *
+ * @example
+ * ```typescript
+ * const { trackFeatureUsed } = useSurveyFeatureTracking('simple-mode')
+ *
+ * function onFeatureAction() {
+ * trackFeatureUsed()
+ * }
+ * ```
+ */
+export function useSurveyFeatureTracking(featureId: string) {
+ const config = getSurveyConfig(featureId)
+ const { trackUsage, useCount } = useFeatureUsageTracker(featureId)
+
+ function trackFeatureUsed() {
+ if (!config?.enabled) return
+ trackUsage()
+ }
+
+ return {
+ trackFeatureUsed,
+ useCount
+ }
+}