# How Meetily’s Onboarding Module Handles First-Time User Experience and Model Setup

> Explore how Meetily's onboarding module streamlines first-time user experience and model setup. Learn about automatic AI model downloads, verification, and configuration.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Meetily’s onboarding module detects first-time launches via SQLite persistence flags, triggers a React wizard for LLM provider and Whisper model configuration, and automatically downloads, verifies, and loads AI models onto GPU or CPU backends before persisting completion state.**

Meetily, an open-source meeting assistant built on Tauri and React, streamlines initial setup through a cohesive architecture that bridges Rust backend persistence with frontend UI wizardry. This **onboarding module handles first-time user experience and model setup** by preparing required speech-to-text and language model infrastructure before users access the main meeting interface.

## Detecting First-Time Launches

The onboarding sequence initiates through backend persistence checks that determine whether the user has previously completed setup.

### SQLite Flag Verification

When the application launches, the Rust entry point in [`frontend/src-tauri/src/lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/lib.rs) queries the local SQLite database defined in [`frontend/src-tauri/src/database/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/mod.rs). The system checks for the `first_run_completed` flag. If this flag is absent or false, the backend emits the `onboarding-start` event to the frontend, triggering the wizard interface.

```rust
// src/lib.rs
#[tauri::command]
async fn check_first_run(app: AppHandle) -> Result<(), String> {
    let db = Database::open().await?;
    if !db.get_flag("first_run_completed").await? {
        app.emit_all("onboarding-start", ())?;
    }
    Ok(())
}

```

## Frontend Onboarding Experience

The frontend listens for backend events and renders a multi-step wizard that guides users through provider selection and API configuration.

### Event-Driven UI Activation

In [`frontend/src/app/page.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/app/page.tsx), the application listens for the `onboarding-start` event using Tauri’s `listen` API. Upon receiving this signal, the **Onboarding Wizard** component ([`frontend/src/components/OnboardingWizard.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/OnboardingWizard.tsx)) mounts and presents the configuration interface.

### Configuration Steps

The wizard walks users through three critical selections:

- **LLM Provider Selection**: Choose between local Ollama instances or remote APIs including Claude and Groq
- **API Key Management**: Secure storage of credentials via OS keychain encryption
- **Whisper Model Selection**: Pick a transcription model suited to the user’s hardware capabilities

## Automated Model Setup

Once the user confirms their selections, the backend executes automated setup routines that prepare the AI infrastructure without manual intervention.

### Whisper Model Download and Loading

The wizard invokes the `load_whisper_model` Tauri command defined in [`frontend/src-tauri/src/whisper_engine/whisper_engine.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/whisper_engine/whisper_engine.rs). This executes `WhisperEngine::load_model()`, which performs the following operations:

- Checks the model directory (`frontend/models/` or the platform-specific application data folder) for the requested model
- Automatically downloads the model from the official repository if absent
- Loads the model onto the most suitable GPU backend (Metal for macOS, CUDA for NVIDIA hardware, or Vulkan) with CPU fallback

The loading routine uses `perf_debug!` macros to maintain lightweight logging in production builds while providing detailed performance metrics during development.

### LLM Provider Configuration

The selected provider persists through the `set_provider` function in [`frontend/src-tauri/src/config/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/config/mod.rs). For local Ollama instances, the system invokes `start_ollama_server`, while remote providers undergo API key validation through lightweight health-check requests. Keys are encrypted using the operating system’s native keychain before storage.

```rust
// src/config/mod.rs
pub async fn set_provider(app: &AppHandle, provider: ProviderConfig) -> Result<(), anyhow::Error> {
    let mut cfg = Config::load(app).await?;
    cfg.provider = Some(provider);
    cfg.save(app).await?;
    Ok(())
}

```

## Completion and Resilience Mechanisms

After both Whisper and LLM models report ready status, the backend updates the `first_run_completed` flag in the SQLite database. The frontend transitions automatically from the wizard to the main meeting interface.

### Error Handling and Flow Reset

If model downloads fail due to network interruptions, the wizard displays a retry interface and logs errors through the centralized logger in [`frontend/src-tauri/src/logging.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/logging.rs). Users can also re-trigger onboarding from the settings page ([`frontend/src/components/Settings.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/components/Settings.tsx)), which clears the completion flag and restarts the flow.

```typescript
// frontend/src/components/OnboardingWizard.tsx
const loadModel = async (modelName: string) => {
  try {
    await invoke('load_whisper_model', { modelName });
    // proceed to next step
  } catch (e) {
    setError(`Failed to load model: ${e}`);
  }
};

```

## Summary

- **First-run detection** relies on SQLite flags in [`frontend/src-tauri/src/database/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/mod.rs) checked at application startup in [`frontend/src-tauri/src/lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/lib.rs)
- **Event-driven architecture** uses Tauri’s `onboarding-start` event to synchronize Rust backend state with React frontend rendering
- **Automated model preparation** downloads Whisper models to `frontend/models/` and loads them onto Metal, CUDA, or Vulkan backends via `WhisperEngine::load_model()`
- **Secure credential storage** encrypts API keys using the OS keychain during LLM provider configuration
- **Resilient error handling** provides retry mechanisms and allows flow reset via the settings page

## Frequently Asked Questions

### How does Meetily determine if a user has completed onboarding?

Meetily checks the SQLite database for the `first_run_completed` flag on every application launch. If the flag is missing or false, the Rust backend in [`frontend/src-tauri/src/lib.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/lib.rs) emits an `onboarding-start` event to display the configuration wizard.

### Can users change their LLM provider after completing initial setup?

Yes, users can modify provider configuration through the settings page. The settings interface allows clearing the `first_run_completed` flag to re-trigger the full onboarding wizard, or individual provider parameters can be updated directly through the configuration module at [`frontend/src-tauri/src/config/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/config/mod.rs).

### What happens if the Whisper model download fails during setup?

The onboarding wizard captures download errors through the `load_whisper_model` command and displays a retry UI. Errors are logged via the centralized logging system in [`frontend/src-tauri/src/logging.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/logging.rs), and users can retry the download without restarting the application.

### Does Meetily support GPU acceleration during model setup?

Yes, the `WhisperEngine::load_model()` function automatically detects and utilizes Metal on macOS, CUDA on NVIDIA hardware, or Vulkan as fallback options. If no GPU backend is available, the system gracefully falls back to CPU inference, though this impacts transcription performance.