# How Meetily's Onboarding Flow Initializes and Stores User Preferences

> Learn how Meetily's onboarding flow initializes and stores user preferences. Discover how defaults are loaded, selections saved to SQLite, and completion tracked in the Tauri store.

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

---

**Meetily's onboarding flow initializes user preferences by loading defaults from a JSON store, persists model selections to SQLite, and updates the Tauri store to mark completion, ensuring preferences survive app restarts.**

The onboarding system in [Zackriya-Solutions/meetily](https://github.com/Zackriya-Solutions/meetily) guides first-time users through initial configuration while maintaining state across sessions. This Rust-powered Tauri application uses a dual-storage approach—JSON for quick UI state checks and SQLite for durable configuration—to ensure that LLM and transcription model selections remain available after reinstalls.

## Loading Default Onboarding State from JSON

When the application starts, the Rust backend invokes `load_onboarding_status` to retrieve the current onboarding progress. This function attempts to read [`onboarding-status.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/onboarding-status.json) via the Tauri Store plugin. If the file is missing or malformed, it falls back to a hard-coded `OnboardingStatus::default()` struct containing the app version, a "not completed" flag, step index `0`, and a `ModelStatus` with both `parakeet` and `summary` fields set to `"not_downloaded"`.

The implementation in [`frontend/src-tauri/src/onboarding.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/onboarding.rs) (lines 45–74) handles this initialization:

```rust
let status = load_onboarding_status(&app).await?;
println!("Onboarding step: {}, completed: {}", status.current_step, status.completed);

```

This default state provides the frontend with immediate knowledge of which models require downloading and which onboarding steps remain incomplete.

## Persisting Model Choices to SQLite Database

When a user completes onboarding by selecting a summarization model, the `complete_onboarding` command executes. This critical function, defined in [`frontend/src-tauri/src/onboarding.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/onboarding.rs) (lines 78–104), performs durable persistence by writing to the embedded SQLite database through two repository methods:

1. **SettingsRepository::save_model_config** – Stores the LLM configuration (`builtin-ai` model)
2. **SettingsRepository::save_transcript_config** – Persists the transcription provider (`parakeet`)

These database writes ensure that preferences survive full application reinstalls, as the SQLite file remains in the user's data directory. The method signatures include provider names, model identifiers, and optional configuration parameters:

```rust
#[tauri::command]
async fn complete_onboarding(app: AppHandle, state: State<'_, AppState>, model: String) {
    // Persist chosen LLM & transcription provider in SQLite
    SettingsRepository::save_model_config(pool, "builtin-ai", &model, "large-v3", None).await?;
    SettingsRepository::save_transcript_config(pool, "parakeet", DEFAULT_PARAKEET_MODEL).await?;
    // ... status updates follow
}

```

The actual SQL operations live in [`frontend/src-tauri/src/database/repositories/setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/repositories/setting.rs), which handles the complex logic of inserting or updating configuration rows while maintaining data integrity.

## Marking Onboarding Complete in the Tauri Store

After successfully writing to SQLite, the flow updates the transient JSON store to reflect completion. The code reloads the onboarding status, updates specific fields (`completed = true`, `current_step = 4`), marks both models as `"downloaded"`, and stores the selected summary model identifier.

This final persistence step in [`frontend/src-tauri/src/onboarding.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/onboarding.rs) (lines 106–122) uses `save_onboarding_status` to write the updated struct back to [`onboarding-status.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/onboarding-status.json):

```rust
let mut status = load_onboarding_status(&app).await?;
status.completed = true;
status.current_step = 4;
status.model_status.parakeet = "downloaded".into();
status.model_status.summary = "downloaded".into();
status.model_status.selected_summary_model = Some(model);
save_onboarding_status(&app, &status).await?;

```

This JSON file serves as the source of truth for UI components checking onboarding completion without querying the database.

## Frontend Helper Utilities for Model Status

The TypeScript layer retrieves onboarding state via the `get_onboarding_status` command and processes it using utilities in [`frontend/src/lib/onboarding-summary-model.ts`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/lib/onboarding-summary-model.ts) (lines 19–55). The `resolveOnboardingSummaryModelStatus` function determines which summary model to display based on the stored configuration:

```typescript
import { resolveOnboardingSummaryModelStatus } from '@/lib/onboarding-summary-model';

const result = resolveOnboardingSummaryModelStatus({
  selectedModel: '',
  recommendedModel: 'qwen3.5:2b',
  selectedModelReady: false,
});

console.log(result.selectedSummaryModel); // → "qwen3.5:2b"
console.log(result.summaryModelDownloaded); // → false

```

Additional helper `getSummaryModelSizeLabel` provides human-readable size formatting for the onboarding UI, ensuring users understand model storage requirements before downloading.

## Summary

- **Dual-storage architecture**: Meetily uses JSON for fast UI state checks ([`onboarding-status.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/onboarding-status.json)) and SQLite for permanent configuration storage
- **Rust command handlers**: `load_onboarding_status`, `complete_onboarding`, and `save_onboarding_status` manage the flow in [`frontend/src-tauri/src/onboarding.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/onboarding.rs)
- **Database persistence**: `SettingsRepository` methods save model selections to survive app reinstalls
- **Frontend integration**: TypeScript helpers interpret `ModelStatus` to render appropriate UI states and download indicators

## Frequently Asked Questions

### Where does Meetily store onboarding completion status?

Meetily stores onboarding completion in two locations: a JSON file ([`onboarding-status.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/onboarding-status.json)) accessed via the Tauri Store plugin for quick UI checks, and an SQLite database for permanent model configuration. The JSON file tracks whether onboarding is complete and which step the user reached, while the database stores the actual LLM and transcription provider selections in [`frontend/src-tauri/src/database/repositories/setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/repositories/setting.rs).

### What happens if the onboarding status file is corrupted?

If [`onboarding-status.json`](https://github.com/Zackriya-Solutions/meetily/blob/main/onboarding-status.json) is missing or malformed, the `load_onboarding_status` function in [`frontend/src-tauri/src/onboarding.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/onboarding.rs) automatically returns `OnboardingStatus::default()`. This default initializes the app version, sets `completed` to `false`, resets the step counter to `0`, and marks both `parakeet` and `summary` models as `"not_downloaded"`, effectively restarting the onboarding flow.

### Which Rust functions handle the onboarding completion process?

The `complete_onboarding` command handles the entire completion process. It first calls `SettingsRepository::save_model_config` and `SettingsRepository::save_transcript_config` to persist selections to SQLite, then updates the JSON store via `save_onboarding_status` with completion flags and model download status. This ensures both transient UI state and permanent user preferences are synchronized.

### How does the frontend determine which summary model to display?

The frontend uses the `resolveOnboardingSummaryModelStatus` helper from [`frontend/src/lib/onboarding-summary-model.ts`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/lib/onboarding-summary-model.ts) to parse the `ModelStatus` returned by the Rust backend. This utility compares the user's selected model against the recommended default and checks download readiness, returning the appropriate display name and boolean flags for the UI components.