Skip to main content
Kafka uses a highly modular architecture with feature-based modules and shared core modules. This organization provides clear separation of concerns, faster build times, and better code reusability across platforms.

Module Overview

The project consists of 30+ modules organized into several categories:
kafka/
├── app/                    # Main Android application
├── desktop-app/            # Desktop application (KMP)
├── base/                   # Foundation modules
│   ├── annotations/
│   └── domain/            # Core domain patterns
├── core/                   # Core functionality
│   ├── analytics/
│   ├── downloader/
│   ├── image-loading/
│   ├── networking/
│   ├── play/
│   └── remote-config/
├── data/                   # Data layer modules
│   ├── database/
│   ├── models/
│   ├── platform/
│   ├── prefs/
│   └── repo/
├── domain/                 # Business logic
├── navigation/             # Navigation logic
└── ui/                     # Feature UI modules
    ├── auth/
    ├── common/
    ├── components/
    ├── downloader/
    ├── homepage/
    ├── item/detail/
    ├── library/
    ├── profile/
    ├── reader/{epub,online,pdf}/
    ├── search/
    ├── shared/
    ├── summary/
    ├── theme/
    └── webview/

Module Categories

Base Modules

Foundation modules that define core patterns and annotations.
include ':base:domain' // kmp
Purpose: Defines base classes for the architecture:
  • Interactor<P>: Base class for use cases
  • SubjectInteractor<P, T>: Base class for observable use cases
  • ResultInteractor<P, R>: Base class for result-based operations
  • CoroutineDispatchers: Abstraction for coroutine dispatchers
// base/domain/src/commonMain/kotlin/com/kafka/base/domain/Interactor.kt
abstract class Interactor<in P> {
    suspend operator fun invoke(params: P, timeoutMs: Long = defaultTimeoutMs): Flow<InvokeStatus> {
        return flow {
            try {
                withTimeout(timeoutMs) {
                    emit(InvokeStarted)
                    doWork(params)
                    emit(InvokeSuccess)
                }
            } catch (t: TimeoutCancellationException) {
                emit(InvokeError(t))
            }
        }.catch { t ->
            emit(InvokeError(t))
        }
    }

    protected abstract suspend fun doWork(params: P)
}

Core Modules

Shared functionality used across features.
Analytics and logging functionality
  • Firebase Analytics integration
  • Event logging abstraction
  • Crashlytics reporting
Download management
  • File downloading with progress
  • Download queue management
  • Based on DatMusic
Image loading utilities
  • Coil integration
  • Image caching strategies
  • Cover art loading
Network layer setup
  • Ktor client configuration
  • API interceptors
  • Network error handling
Playback functionality
  • Audio player integration
  • Uses Sarahang library
  • Playback controls
Remote configuration
  • Firebase Remote Config
  • Feature flags
  • A/B testing support

Data Layer Modules

Modules responsible for data management and persistence.

data:database

Room database implementation with entities and DAOs.
@Database(
    entities = [
        ItemDetail::class,
        File::class,
        Item::class,
        QueueEntity::class,
        RecentSearch::class,
        RecentTextItem::class,
        RecentAudioItem::class,
        DownloadRequest::class,
    ],
    version = 9,
    exportSchema = true
)
@TypeConverters(AppTypeConverters::class)
abstract class KafkaRoomDatabase : RoomDatabase(), KafkaDatabase {
    // Auto-generated DAO getters
}

data:models

Data transfer objects and API models.
  • Network response models
  • Serialization with kotlinx.serialization
  • Archive.org API models
  • Search filters and queries

data:repo

Repository implementations.
@ApplicationScope
class HomepageRepository @Inject constructor(
    private val firestoreGraph: FirestoreGraph,
    private val homepageMapper: HomepageMapper,
    private val userDataRepository: UserDataRepository
) {
    fun observeHomepageCollection() =
        firestoreGraph.homepageCollection.snapshots
            .flatMapLatest { it.toHomepage(userDataRepository.getUserCountry()) }

    suspend fun getHomepageIds() = 
        firestoreGraph.homepageCollection.get()
            .documents
            .map { it.getHomepageData() }
            .filter { it.enabled }
            .sortedBy { it.index }
}

data:prefs

DataStore-based preferences management.
  • User preferences
  • App settings
  • Reading state persistence

data:platform

Platform-specific data utilities.
  • User country detection
  • App version information
  • Platform-specific storage paths

Domain Module

Business logic layer with interactors and observers.
domain/src/commonMain/kotlin/com/kafka/domain/interactors/
├── UpdateHomepage.kt
├── UpdateItemDetail.kt
├── UpdateFavorite.kt
├── UpdateRecentItem.kt
├── SearchQueryItems.kt
├── AddRecentSearch.kt
├── account/
│   ├── SignInUser.kt
│   ├── SignUpUser.kt
│   └── LogoutUser.kt
└── recent/
    ├── AddRecentItem.kt
    ├── RemoveRecentItem.kt
    └── RemoveAllRecentItems.kt

UI Modules

Feature-based UI modules using Jetpack Compose.

ui:auth

Authentication screens
  • Sign in/Sign up
  • Google authentication
  • Password reset

ui:homepage

Main homepage
  • Featured collections
  • Recent items
  • Recommendations

ui:search

Search functionality
  • Query builder
  • Filters (subject, creator, language)
  • Search history

ui:library

User library
  • Favorites
  • Downloads
  • Reading history

ui:item:detail

Item details
  • Metadata display
  • Files list
  • Actions (favorite, download, share)

ui:reader

Readers (epub, pdf, online)
  • PDF reader
  • EPUB reader
  • Online text reader

ui:profile

User profile
  • Account settings
  • Preferences
  • Feedback

ui:components

Shared UI components
  • Reusable composables
  • Item cards
  • Common widgets

Module Dependencies

The app module brings everything together:
dependencies {
    // Base
    implementation(projects.base.domain)
    
    // Core modules
    implementation(projects.core.analytics)
    implementation(projects.core.downloader)
    implementation(projects.core.networking)
    implementation(projects.core.play)
    implementation(projects.core.remoteConfig)
    
    // Data modules
    implementation(projects.data.database)
    implementation(projects.data.platform)
    implementation(projects.data.prefs)
    implementation(projects.data.repo)
    
    // Domain
    implementation(projects.domain)
    
    // Navigation
    implementation(projects.navigation)
    
    // UI modules
    implementation(projects.ui.auth)
    implementation(projects.ui.common)
    implementation(projects.ui.components)
    implementation(projects.ui.downloader)
    implementation(projects.ui.homepage)
    implementation(projects.ui.item.detail)
    implementation(projects.ui.library)
    implementation(projects.ui.profile)
    implementation(projects.ui.reader.epub)
    implementation(projects.ui.reader.online)
    implementation(projects.ui.reader.pdf)
    implementation(projects.ui.search)
    implementation(projects.ui.theme)
    // ... more UI modules
}

Dependency Flow

Modules follow a strict dependency hierarchy:
app
 ├─► ui:* (UI feature modules)
 │    ├─► domain (business logic)
 │    │    └─► data:repo (repositories)
 │    │         └─► data:database (Room)
 │    ├─► navigation
 │    └─► ui:components (shared UI)
 │         └─► ui:theme
 ├─► core:* (core functionality)
 └─► base:domain (foundation)
Lower layers never depend on higher layers, ensuring clean architecture.

Kotlin Multiplatform Modules

Modules marked with // kmp are shared between Android and Desktop:
  • All data:* modules (database, models, prefs, repo, platform)
  • base:domain
  • domain
  • core:* modules
  • Some ui:* modules (common, components, theme, homepage, reader, etc.)
This allows significant code reuse across platforms while maintaining platform-specific implementations where needed.

Build Configuration

Kafka uses Gradle convention plugins for consistent build configuration:
gradle/build-logic/
├── convention/
│   ├── com.kafka.compose
│   ├── com.kafka.kotlin.android
│   └── com.kafka.kotlin.multiplatform
These plugins are applied to modules to provide consistent:
  • Kotlin/Compose compiler settings
  • Android SDK versions
  • Dependency versions
  • Build optimizations

Build docs developers (and LLMs) love