# Architecture Overview

Pebbl follows modern Android development best practices with a clean, maintainable architecture.

#### Technology Stack

**Core Android**

| Technology          | Version           | Purpose                      |
| ------------------- | ----------------- | ---------------------------- |
| **Kotlin**          | 2.0.21            | Primary programming language |
| **Android SDK**     | Min 24, Target 36 | Platform framework           |
| **Jetpack Compose** | 2024.09.00        | Declarative UI framework     |
| **Material 3**      | Latest            | Design system                |

**Architecture Components**

| Component              | Version | Purpose                   |
| ---------------------- | ------- | ------------------------- |
| **Room**               | 2.6.1   | Local SQLite database ORM |
| **ViewModel**          | 2.8.0   | UI state management       |
| **Navigation Compose** | 2.7.7   | Type-safe navigation      |
| **DataStore**          | 1.1.1   | Key-value preferences     |

**Networking & AI**

| Library      | Version | Purpose                    |
| ------------ | ------- | -------------------------- |
| **Retrofit** | 2.9.0   | HTTP client                |
| **OkHttp**   | 4.12.0  | HTTP engine & interceptors |
| **Gson**     | 2.10.1  | JSON serialization         |

**Speech Recognition**

| Library      | Version | Purpose                |
| ------------ | ------- | ---------------------- |
| **Vosk SDK** | 0.3.38  | Offline speech-to-text |

**Async & Reactive**

| Component             | Version | Purpose               |
| --------------------- | ------- | --------------------- |
| **Kotlin Coroutines** | 1.8.0   | Async/await pattern   |
| **Flow & StateFlow**  | Core    | Reactive data streams |

**Build Tools**

| Tool       | Version       | Purpose                        |
| ---------- | ------------- | ------------------------------ |
| **Gradle** | 8.13.0        | Build system                   |
| **KSP**    | 2.0.21-1.0.29 | Annotation processing for Room |
| **AGP**    | 8.5.1         | Android Gradle Plugin          |

#### Project Structure

```
Pebbl/
├── app/
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/com/fouwaz/Pebbl/
│   │   │   │   ├── data/                    # Data Layer
│   │   │   │   │   ├── local/               # Local data sources
│   │   │   │   │   │   ├── entity/          # Room database entities
│   │   │   │   │   │   │   ├── ProjectEntity.kt
│   │   │   │   │   │   │   ├── VoiceStreamEntity.kt
│   │   │   │   │   │   │   ├── DraftEntity.kt
│   │   │   │   │   │   │   ├── LectureEntity.kt
│   │   │   │   │   │   │   ├── LectureOutputEntity.kt
│   │   │   │   │   │   │   └── AchievementEntity.kt
│   │   │   │   │   │   ├── dao/              # Data Access Objects
│   │   │   │   │   │   │   ├── ProjectDao.kt
│   │   │   │   │   │   │   ├── VoiceStreamDao.kt
│   │   │   │   │   │   │   ├── DraftDao.kt
│   │   │   │   │   │   │   ├── LectureDao.kt
│   │   │   │   │   │   │   ├── LectureOutputDao.kt
│   │   │   │   │   │   │   └── AchievementDao.kt
│   │   │   │   │   │   ├── preferences/      # DataStore preferences
│   │   │   │   │   │   └── VoiceStreamDatabase.kt
│   │   │   │   │   ├── remote/               # Remote data sources
│   │   │   │   │   │   ├── api/
│   │   │   │   │   │   │   └── OpenRouterService.kt
│   │   │   │   │   │   └── model/            # API models
│   │   │   │   │   │       ├── ChatRequest.kt
│   │   │   │   │   │       ├── ChatResponse.kt
│   │   │   │   │   │       └── ChatMessage.kt
│   │   │   │   │   └── repository/           # Repository implementations
│   │   │   │   │       └── AiRepository.kt
│   │   │   │   ├── domain/                   # Domain Layer
│   │   │   │   │   └── model/                # Domain models (UI-friendly)
│   │   │   │   │       ├── Project.kt
│   │   │   │   │       ├── FinalDraftConfig.kt
│   │   │   │   │       ├── PebbleType.kt
│   │   │   │   │       └── LectureOutputType.kt
│   │   │   │   ├── speech/                   # Speech Recognition
│   │   │   │   │   └── VoiceRecognitionManager.kt
│   │   │   │   ├── ui/                       # Presentation Layer
│   │   │   │   │   ├── screens/              # Compose screens
│   │   │   │   │   │   ├── ProjectListScreen.kt
│   │   │   │   │   │   ├── NewProjectScreen.kt
│   │   │   │   │   │   ├── VoiceSessionScreen.kt
│   │   │   │   │   │   ├── DraftViewScreen.kt
│   │   │   │   │   │   ├── LectureRecordingScreen.kt
│   │   │   │   │   │   ├── LectureOutputViewScreen.kt
│   │   │   │   │   │   ├── PebbleCollectionScreen.kt
│   │   │   │   │   │   └── WelcomeScreen.kt
│   │   │   │   │   ├── viewmodel/            # ViewModels
│   │   │   │   │   │   ├── ProjectViewModel.kt
│   │   │   │   │   │   ├── VoiceSessionViewModel.kt
│   │   │   │   │   │   ├── LectureRecordingViewModel.kt
│   │   │   │   │   │   └── LectureOutputViewModel.kt
│   │   │   │   │   ├── navigation/           # Navigation setup
│   │   │   │   │   │   ├── Screen.kt
│   │   │   │   │   │   └── Navigation.kt
│   │   │   │   │   ├── theme/                # Material 3 theming
│   │   │   │   │   │   ├── Color.kt
│   │   │   │   │   │   ├── Theme.kt
│   │   │   │   │   │   └── Type.kt
│   │   │   │   │   ├── components/           # Reusable UI components
│   │   │   │   │   │   ├── MilestoneCelebrationDialog.kt
│   │   │   │   │   │   └── RecentPebblesRow.kt
│   │   │   │   │   ├── share/                # Share functionality
│   │   │   │   │   └── util/                 # UI utilities
│   │   │   │   ├── MainActivity.kt
│   │   │   │   └── VoiceStreamApplication.kt
│   │   │   ├── res/                          # Resources
│   │   │   │   ├── drawable/                 # Icons, images
│   │   │   │   ├── values/
│   │   │   │   │   ├── strings.xml
│   │   │   │   │   ├── colors.xml
│   │   │   │   │   └── themes.xml
│   │   │   │   └── mipmap/                   # App icons
│   │   │   ├── assets/                       # Static assets
│   │   │   │   └── vosk-model-small-en-us-0.15/  # Speech model
│   │   │   └── AndroidManifest.xml
│   │   └── test/                             # Unit tests
│   └── build.gradle.kts                      # App-level build config
├── gradle/                                   # Gradle wrapper
│   ├── libs.versions.toml                    # Version catalog
│   └── wrapper/
├── build.gradle.kts                          # Project-level build config
├── settings.gradle.kts                       # Settings
├── local.properties                          # API keys (not in VCS)
├── README.md
└── docs.md                                   # This file
```

#### Design Patterns

**MVVM (Model-View-ViewModel)**

**Separation of Concerns**

```
┌─────────────┐
│    View     │  Jetpack Compose UI
│  (Screen)   │  - Observes StateFlow
└──────┬──────┘  - Emits user events
       │
       ↓
┌─────────────┐
│  ViewModel  │  State Management
│             │  - Exposes StateFlow
└──────┬──────┘  - Business logic orchestration
       │
       ↓
┌─────────────┐
│ Repository  │  Data Abstraction
│             │  - Combines data sources
└──────┬──────┘  - Caching logic
       │
       ↓
┌─────────────┐
│    Model    │  Data Layer
│ (Entity/DAO)│  - Room database
└─────────────┘  - API services
```

**Benefits:**

* Testable business logic (ViewModels)
* Reactive UI updates (StateFlow)
* Lifecycle-aware components
* Clear data flow

**Repository Pattern**

Abstracts data sources from ViewModels:

```kotlin
class AiRepository(
    private val apiService: OpenRouterService
) {
    suspend fun generateFollowUpQuestions(
        transcribedText: String
    ): Result<List<String>> {
        return try {
            val response = apiService.chat(buildRequest(transcribedText))
            Result.success(parseQuestions(response))
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
}
```

**Benefits:**

* Single source of truth
* Easy to mock for testing
* Centralized error handling
* Can switch data sources without changing ViewModels

**Sealed Classes for State**

Type-safe state representation prevents impossible states:

```kotlin
sealed class LectureRecordingState {
    object Idle : LectureRecordingState()
    object Initializing : LectureRecordingState()
    object Ready : LectureRecordingState()
    object Recording : LectureRecordingState()
    object Paused : LectureRecordingState()
    object Processing : LectureRecordingState()
    data class GeneratingOutputs(val progress: Float) : LectureRecordingState()
    data class Complete(val lectureId: Long) : LectureRecordingState()
    data class Error(val message: String) : LectureRecordingState()
}
```

**Benefits:**

* Exhaustive when expressions
* Impossible to have invalid state combinations
* Clear state transitions
* Type-safe data associated with states

**Dependency Injection (Manual)**

Currently using manual DI via Application class:

```kotlin
class VoiceStreamApplication : Application() {
    val database: VoiceStreamDatabase by lazy {
        Room.databaseBuilder(
            applicationContext,
            VoiceStreamDatabase::class.java,
            "voice_stream_db"
        ).build()
    }
}
```

Access in Activities:

```kotlin
val db = (application as VoiceStreamApplication).database
```

> **Note**: Consider migrating to Hilt/Dagger for larger-scale DI needs.
