PokePedia is a modern, cross-platform Pokémon encyclopedia application built with Kotlin Multiplatform and Compose Multiplatform. It provides a seamless experience for exploring Pokémon data across Android, iOS, and Desktop platforms with offline-first architecture and beautiful Material 3 design.
Powered by PokéAPI, PokePedia offers comprehensive Pokémon information including stats, abilities, types, evolution chains, and more - all with a clean, intuitive interface optimized for different screen sizes.
- 📚 Browse Pokémon: Explore an extensive database of Pokémon with infinite scroll pagination
- 🔎 Smart Search: Real-time search with instant filtering of Pokémon by name
- 📊 Detailed Information: View comprehensive stats, abilities, types, and characteristics
- 🧬 Evolution Chains: Visualize complete evolution paths with methods and requirements
- 🎨 Type Colors: Dynamic theming based on Pokémon types with Material Kolor
- 📈 Stats Visualization: Visual representation of base stats with comparison
| List | Detail |
|---|---|
![]() |
![]() |
| List | Detail |
|---|---|
![]() |
![]() |
| Screenshot |
|---|
![]() |
PokePedia follows Clean Architecture principles with clear separation of concerns, ensuring maintainability, testability, and scalability.
┌────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Android UI │ │ iOS UI │ │ Desktop UI │ │
│ │ (Compose) │ │ (Compose) │ │ (Compose) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ViewModels & State Management │ │
│ │ (PokemonListViewModel, PokemonDetailViewModel) │ │
│ │ │ │
│ │ • StateFlow for reactive state │ │
│ │ • Action-based event handling │ │
│ │ • UI state transformations │ │
│ └────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ DOMAIN LAYER │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Business Logic │ │
│ │ │ │
│ │ • Entities: Pokemon, PokemonType, Stats, Species │ │
│ │ • Interfaces: PokemonRepository │ │
│ │ • Error Handling: Result, DataError │ │
│ │ │ │
│ │ • Pure Kotlin - No framework dependencies │ │
│ │ • Platform-agnostic business rules │ │
│ └────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────┐
│ DATA LAYER │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Repository Implementation │ │
│ │ (DefaultPokemonRepository) │ │
│ │ │ │
│ │ • Coordinates data sources │ │
│ │ • Handles caching strategy │ │
│ │ • Maps DTOs to Domain models │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ Remote Data Source │ │ Local Data Source │ │
│ │ (PokéAPI) │ │ (Room Database) │ │
│ │ │ │ │ │
│ │ • Ktor HTTP Client │ │ • SQLite storage │ │
│ │ • JSON parsing │ │ • DAO operations │ │
│ │ • API endpoints │ │ • Offline cache │ │
│ └──────────────────────┘ └──────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
sequenceDiagram
participant UI as Compose UI
participant VM as PokemonListViewModel
participant Repo as PokemonRepository
participant Remote as RemoteDataSource
participant API as PokéAPI
participant Mapper as Data Mapper
UI->>VM: User opens app
activate VM
VM->>VM: init { loadPokemon() }
VM->>VM: Update state (isLoading = true)
VM->>Repo: getPokemon(limit=20, offset=0)
activate Repo
Repo->>Remote: getPokemonList(20, 0)
activate Remote
Remote->>API: GET /pokemon?limit=20&offset=0
activate API
API-->>Remote: PokemonListResponse (JSON)
deactivate API
Remote-->>Repo: Result.Success(PokemonListDto)
deactivate Remote
Repo->>Mapper: results.map { it.toDomain() }
activate Mapper
Mapper-->>Repo: List<Pokemon>
deactivate Mapper
Repo->>Repo: Create PaginatedPokemon
Repo-->>VM: Result.Success(PaginatedPokemon)
deactivate Repo
VM->>VM: Transform to UI models
VM->>VM: Update state (pokemonList, isLoading = false)
VM-->>UI: StateFlow emission
deactivate VM
UI->>UI: Recompose with new data
sequenceDiagram
participant UI as Detail Screen
participant VM as PokemonDetailViewModel
participant Repo as PokemonRepository
participant Remote as RemoteDataSource
participant API as PokéAPI
participant Mapper as Data Mapper
UI->>VM: User clicks Pokémon
activate VM
VM->>VM: loadPokemonDetail(id)
VM->>VM: Update state (isLoading = true)
VM->>Repo: getPokemonDetails(pokemonId)
activate Repo
Note over Repo,API: Parallel API Calls (async/await)
par Fetch Pokemon Details
Repo->>Remote: getPokemonDetails(id)
activate Remote
Remote->>API: GET /pokemon/{id}
API-->>Remote: PokemonDto
deactivate Remote
and Fetch Species Data
Repo->>Remote: getPokemonSpecies(id)
activate Remote
Remote->>API: GET /pokemon-species/{id}
API-->>Remote: SpeciesDto
deactivate Remote
end
Note over Repo: If species has evolution chain
Repo->>Remote: getEvolutionChain(chainId)
activate Remote
Remote->>API: GET /evolution-chain/{id}
API-->>Remote: EvolutionChainDto
deactivate Remote
Repo->>Mapper: toDomain(pokemon, species, evolution)
activate Mapper
Mapper-->>Repo: Pokemon (with full details)
deactivate Mapper
Repo-->>VM: Result.Success(Pokemon)
deactivate Repo
VM->>VM: Transform to UI model
VM->>VM: Update state (isLoading = false)
VM-->>UI: StateFlow emission
deactivate VM
UI->>UI: Recompose with details
sequenceDiagram
participant UI as Search Bar
participant VM as PokemonListViewModel
participant Memory as In-Memory Cache
UI->>VM: User types "Pika"
activate VM
VM->>VM: Update state (searchQuery = "Pika")
VM->>VM: Debounce (300ms)
VM->>Memory: Filter fullPokemonList
activate Memory
Memory->>Memory: filter { name.contains("Pika") }
Memory-->>VM: Filtered List
deactivate Memory
VM->>VM: Update state (pokemonList = filtered)
VM-->>UI: StateFlow emission
deactivate VM
UI->>UI: Recompose with results
Note over UI,VM: Search is instant - no API calls
sequenceDiagram
participant UI as UI Layer
participant VM as ViewModel
participant Repo as Repository
participant Local as Room Database
participant Remote as Remote API
UI->>VM: Request data
activate VM
VM->>Repo: getData()
activate Repo
alt Data available in cache
Repo->>Local: Query cached data
activate Local
Local-->>Repo: Cached data
deactivate Local
Repo-->>VM: Return cached data
Note over Repo: Optionally refresh in background
else Cache miss or expired
Repo->>Remote: Fetch from API
activate Remote
Remote-->>Repo: Fresh data
deactivate Remote
Repo->>Local: Save to cache
activate Local
Local-->>Repo: Saved
deactivate Local
Repo-->>VM: Return fresh data
end
deactivate Repo
VM-->>UI: Update state
deactivate VM
| Technology | Version | Purpose |
|---|---|---|
| Kotlin | 2.2.20 | Primary programming language |
| Compose Multiplatform | 1.9.0 | Declarative UI framework |
| Kotlin Multiplatform | 2.2.20 | Cross-platform code sharing |
| Technology | Version | Purpose |
|---|---|---|
| Ktor Client | 3.3.0 | HTTP client for API calls |
| Kotlinx Serialization | 1.9.0 | JSON parsing and serialization |
| Technology | Version | Purpose |
|---|---|---|
| Room | 2.8.1 | Local database with type-safe queries |
| SQLite Bundled | 2.6.1 | Embedded database engine |
| Technology | Version | Purpose |
|---|---|---|
| Koin | 4.1.1 | Lightweight dependency injection |
| Technology | Version | Purpose |
|---|---|---|
| AndroidX Lifecycle | 2.9.4 | ViewModel and lifecycle management |
| AndroidX Navigation | 2.9.0 | Type-safe navigation |
| Kotlinx Coroutines | 1.10.2 | Asynchronous programming |
| Technology | Version | Purpose |
|---|---|---|
| Material 3 | Latest | Material Design components |
| Material Icons Extended | 1.7.3 | Comprehensive icon library |
| Material Kolor | 3.0.1 | Dynamic color theming from images |
| Compose Adaptive | 1.2.0-alpha06 | Adaptive layouts for different screens |
| Coil | 3.3.0 | Image loading with caching |
| Technology | Version | Purpose |
|---|---|---|
| KSP | 2.2.20-2.0.3 | Kotlin Symbol Processing |
| BuildConfig | 5.6.8 | Build-time configuration |
| Kermit | 2.0.8 | Multiplatform logging |
| Hot Reload | 1.0.0-beta08 | Fast development iteration |
| Technology | Version | Purpose |
|---|---|---|
| Kotlinx Coroutines Test | 1.10.2 | Coroutine testing utilities |
| Compose UI Test | Latest | UI testing for Compose |
| JUnit 4 | Latest | Unit testing framework |
# Using Gradle
./gradlew :composeApp:installDebug
# Or using Android Studio
# Select "composeApp" configuration and click Run ▶️# Open iOS project in Xcode
open iosApp/iosApp.xcodeproj
# Or run directly from Android Studio
# Select "iosApp" configuration and choose a simulator# Run on current OS
./gradlew :composeApp:run
# Or using Android Studio
# Select "composeApp" → "Desktop" and click Run ▶️./gradlew :composeApp:assembleRelease
# Output: composeApp/build/outputs/apk/release/composeApp-release.apk./gradlew :composeApp:bundleRelease
# Output: composeApp/build/outputs/bundle/release/composeApp-release.aab./gradlew :composeApp:linkDebugFrameworkIosArm64./gradlew :composeApp:linkReleaseFrameworkIosArm64
# Then build in Xcode for App Store submission./gradlew :composeApp:packageDistributionForCurrentOS# macOS DMG
./gradlew :composeApp:packageDmg
# Windows MSI
./gradlew :composeApp:packageMsi
# Linux DEB
./gradlew :composeApp:packageDebOutputs:
- macOS:
composeApp/build/compose/binaries/main/dmg/ - Windows:
composeApp/build/compose/binaries/main/msi/ - Linux:
composeApp/build/compose/binaries/main/deb/
- Write clean, readable, and maintainable code
- Follow the project's architecture patterns (see ARCHITECTURE.md)
- Add appropriate comments and documentation
- Write unit tests for new functionality
- Ensure backward compatibility
- Update the README if you add new features
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2024 Somesh Kumar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
This project wouldn't be possible without these amazing resources:
- PokéAPI - Free and open Pokémon API
- JetBrains - Kotlin and IntelliJ IDEA
- Kotlin Multiplatform - Cross-platform development
- Compose Multiplatform - Modern UI framework
- Material Design - Design system and guidelines
- Android & iOS Communities - For excellent documentation and support
Somesh Kumar
- 🐙 GitHub: @TheSomeshKumar
- 💼 LinkedIn: linkedin.com/in/thesomeshkumar
- 🐦 Twitter: @TheSomeshKumar




