How Meetily's Onboarding Flow Collects User Preferences: A Technical Deep Dive

Meetily's onboarding flow collects user preferences through a React context that manages audio permissions and AI model selections, persisting them via Tauri commands to a local JSON store and SQLite database.

The open-source meeting assistant Meetily (Zackriya-Solutions/meetily) implements a privacy-first onboarding sequence that captures critical user choices before allowing access to recording features. This flow gathers audio permission grants and AI model preferences through a tightly coupled frontend React context and backend Rust Tauri commands, ensuring preferences survive application restarts while maintaining local data sovereignty.

React Context State Management

The frontend UI relies on frontend/src/contexts/OnboardingContext.tsx to orchestrate the onboarding sequence. This context maintains the current step index, permission states, and model selection in a centralized state.

The context initializes by invoking the Tauri command get_onboarding_status to hydrate any previously saved preferences from onboarding-status.json. It validates that required models—the Parakeet speech-to-text model and the selected summary LLM—exist on disk before allowing progression. The state structure tracks:

  • microphone, systemAudio, and screenRecording permission states
  • selectedSummaryModel identifier
  • model_status objects for both Parakeet and the summary model

When users toggle permissions or change models, the context updates via setPermissionStatus and setSelectedSummaryModel mutators, which trigger auto-save operations after a debounce period.

Permission Handling and Audio Setup

Meetily requests platform-specific audio permissions through the Tauri plugin system defined in frontend/src-tauri/src/audio/permissions.rs. The React context exposes these permission states to UI components, displaying granular controls for microphone access, system audio capture, and screen recording authorization.

Each permission change flows through the context's setPermissionStatus method, which updates the local state and queues a persistence operation. The backend validates these permissions before allowing any recording operations, creating a security boundary that prevents unauthorized audio capture.

AI Model Selection and Validation

The onboarding flow resolves the preferred summary model by calling the Tauri command builtin_ai_get_recommended_model, which returns a default or previously selected LLM configuration. Users may override this recommendation through the UI, triggering validation via builtin_ai_is_model_ready.

If the selected model is missing from local storage, the context invokes builtin_ai_download_model (wrapped in the requestSummaryModelDownload function) to fetch the required files. This ensures that only locally-available models can be selected as the active preference, preventing configuration errors during meeting transcription.

Persistence Layer: Tauri Store and SQLite

User preferences persist through two mechanisms depending on the onboarding stage. During the active flow, the Rust implementation in frontend/src-tauri/src/onboarding.rs handles serialization via save_onboarding_status_cmd:

#[tauri::command]
pub async fn save_onboarding_status_cmd<R: Runtime>(
    app: AppHandle<R>,
    status: OnboardingStatus,
) -> Result<(), String> {
    save_onboarding_status(&app, &status)
        .await
        .map_err(|e| format!("Failed to save onboarding status: {}", e))
}

The OnboardingStatus struct captures:

  • model_status.parakeet: Availability of the transcription model
  • model_status.summary: Availability of the LLM
  • selected_summary_model: The user's chosen AI model identifier

When the user completes the flow by invoking complete_onboarding, the Rust backend performs database operations through SettingsRepository::save_model_config to persist the LLM configuration in SQLite, records the transcription provider as parakeet, and marks the onboarding status as completed = true in the JSON store.

Gatekeeping and Post-Onboarding Enforcement

The system gate-keeps core functionality based on onboarding completion status. The tray implementation in frontend/src-tauri/src/tray.rs checks the persisted onboarding flag before allowing recording initiation, ensuring that users cannot bypass the permission and model selection requirements.

This design creates a hard dependency chain: the UI loads persisted preferences on mount, validates model availability, captures new user choices, auto-saves incremental changes, and finalizes the configuration in the database only upon explicit completion.

Summary

  • Meetily's onboarding flow uses a React context in OnboardingContext.tsx to manage the UI state for audio permissions and AI model selection.
  • Permission states for microphone, system audio, and screen recording are captured through setPermissionStatus and validated via Tauri's audio/permissions.rs module.
  • AI model preferences are resolved using builtin_ai_get_recommended_model, validated with builtin_ai_is_model_ready, and downloaded via builtin_ai_download_model if missing.
  • Preferences persist to onboarding-status.json through save_onboarding_status_cmd and finalize in SQLite via complete_onboarding, which saves the LLM config and marks the flow as completed.
  • Recording access is gated by the completion flag checked in tray.rs, ensuring models and permissions are configured before use.

Frequently Asked Questions

How does Meetily store user preferences during the onboarding flow?

Meetily stores preferences incrementally in a local JSON file (onboarding-status.json) using Tauri's store API via the save_onboarding_status_cmd command. When the user completes onboarding, the system migrates the final AI model configuration to an SQLite database through SettingsRepository::save_model_config, while maintaining the completion flag in the JSON store for fast startup checks.

What audio permissions does Meetily request during onboarding?

The onboarding flow requests three specific audio permissions: microphone access for voice capture, system audio for capturing meeting participants, and screen recording for display capture. These are managed through the audio/permissions.rs Tauri plugin and tracked in the React context's permissions state object until persisted.

Can users change their AI model after completing onboarding?

While the onboarding flow sets the initial selected_summary_model via builtin_ai_get_recommended_model, the architecture supports model changes through the same validation pipeline. The context checks model availability with builtin_ai_is_model_ready and triggers downloads via builtin_ai_download_model, though the specific post-onboarding UI for model switching would depend on the application's settings implementation.

What happens if required AI models are missing during onboarding?

If the Parakeet transcription model or selected summary model is missing when the context loads, the loadOnboardingStatus function detects this through the model status checks. The UI then prompts the user to download the missing model via requestSummaryModelDownload, which invokes builtin_ai_download_model. The onboarding cannot proceed to completion until builtin_ai_is_model_ready returns true for both required models.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →