Feedback System

In-app user feedback collection with Microsoft Teams notification delivery — manual reports plus automatic friction-signal detection.

Architecture

LayerLocation
Routebackend/src/routes/feedback.ts
Servicebackend/src/services/feedback/feedback-service.ts
Componentsfrontend/src/components/feedback/

Frontend Components

ComponentPurpose
FeedbackAgentOrchestrates feedback UI lifecycle (trigger, form, confirmation)
FeedbackFabFloating action button trigger
FeedbackFormForm with category, description, screenshot option
FeedbackToastConfirmation toast after submission
feedbackService.tsAPI client for feedback submission
useFeedbackState.tsFeedback UI state hook
detectors/Automatic friction detectors: useRageClickDetector, useSentryEventDetector, useSlowLoadDetector

How It Works

  1. User clicks feedback trigger (accessible from any page) — or a detector fires automatically
  2. FeedbackForm collects:
    • Category (bug, feature request, general feedback)
    • Description text
    • Optional screenshot
    • Automatic context (current page URL, user info, browser details)
  3. Submission sent to backend/src/routes/feedback.ts
  4. Backend builds an Adaptive Card and posts it to Teams: manual reports via TEAMS_SUPPORT_WEBHOOK_URL, auto-detected signals via TEAMS_AUTOMATED_WEBHOOK_URL
  5. FeedbackToast confirms submission

Screenshots are uploaded to object storage and linked from the Teams card.

Context Capture

The feedback system automatically captures contextual information with each submission:

  • Current page URL
  • Authenticated user identity
  • Browser and device information
  • Timestamp

This context helps the development team reproduce issues without requiring back-and-forth with the reporter.

Teams Integration

Feedback notifications are sent to Microsoft Teams channels via incoming (Power Automate) webhooks. Two destinations are configured: TEAMS_SUPPORT_WEBHOOK_URL for manual user reports and TEAMS_AUTOMATED_WEBHOOK_URL for auto-detected signals (rage clicks, Sentry events, slow loads). Each entry posts a formatted Adaptive Card with the submission details and context; if a webhook is not configured, the report is logged only.