You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
✨ Features
🔍 Core Features
📚 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
📸 Screenshots
Android
List
Detail
iOS
List
Detail
Desktop
Screenshot
🏗️ Architecture
PokePedia follows Clean Architecture principles with clear separation of concerns, ensuring maintainability, testability, and scalability.
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
Loading
2. Pokémon Detail Loading Flow
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
Loading
3. Search Flow
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
Loading
4. Offline-First Caching Strategy
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
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
📄 License
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.
🙏 Acknowledgments
This project wouldn't be possible without these amazing resources: