AnimeThek is a modern SwiftUI application that demonstrates clean architecture, modular networking, structured async/await flows, reusable UI components, and scalable view models.
It fetches data from the Jikan API and displays anime information in a clean, responsive interface.
This project is designed as a sample code showcase for iOS practices.
It focuses on clarity, maintainability, testing readiness, and SwiftUI-first design.
AnimeThek showcases modern iOS engineering practices using SwiftUI, async/await, MVVM, and a modular architecture.
It demonstrates how to build scalable apps with clean state management, testable layers, and reusable UI components.
- 📱 Built with SwiftUI end-to-end
- 🔗 Async/Await networking layer
- 📦 Decoupled modular architecture (Services, Models, ViewModels, UI)
- ♻️ Reusable UI components (Cards, Lists, Loaders)
- 🔍 Anime search with debouncing
- 🎨 Light & Dark Mode support
- 📐 Clean MVVM structure
- 💥 Error handling with user-friendly messaging
- 🔧 Ready for unit testing and dependency injection
AnimeThek follows a clean, layered MVVM architecture:
AnimeThek/
├── Models/
├── Networking/
│ ├── APIClient.swift
│ ├── Endpoint.swift
│ └── Requests/
├── Services/
│ ├── AnimeService.swift
│ └── Protocols/
├── ViewModels/
├── Views/
│ ├── Screens/
│ └── Components/
├── Utils/
└── Resources/- Decoupling between networking and UI
- Dependency injection for testability
- Async/await for clean readability
- One-way data flow with
@StateObjectand@Published - Preview-driven development
- Swift 5.9+
- SwiftUI
- MVVM
- async/await
- SPM
- Jikan API
AnimeThek includes a lightweight reusable networking abstraction:
APIClienthandles all async requestsEndpointprovides type-safe API constructionAnimeServiceexposes high-level domain functions- Swift's
Decodableis used for safe JSON parsing
Each screen has:
- a ViewModel responsible for logic, networking, transforms
- a SwiftUI View focused on rendering
- async/await tasks triggered safely from the UI
- observable state via @Published
Example (simplified):
@MainActor
class AnimeSearchViewModel: ObservableObject {
@Published var query = ""
@Published var results: [Anime] = []
@Published var isLoading = false
private let service: AnimeServiceProtocol
init(service: AnimeServiceProtocol = AnimeService()) {
self.service = service
}
func search() async {
guard !query.isEmpty else { return }
isLoading = true
do {
results = try await service.searchAnime(query)
} catch {
results = []
}
isLoading = false
}
}AnimeThek includes reusable components such as:
- CardCategory
- AsyncImage loader wrapper
- SearchBar
- ErrorStateView
- Loading indicator
- Designed for scalability and reusability across screens.
AnimeThek uses SwiftUI previews to render UI components in isolation, supporting fast iteration and design-system thinking.
Here is an example preview for one of the reusable components:
#Preview(traits: .sizeThatFitsLayout) {
CategoryCard(category: .anime)
.padding(20)
}The architecture is designed for easy testing:
- Services conform to protocols
- ViewModels are independent of SwiftUI
- Networking layer supports mock injection
Example test-ready structure:
final class MockAnimeService: AnimeServiceProtocol {
func searchAnime(_ query: String) async throws -> [Anime] {
return [.mock]
}
}This project is licensed under the MIT License.
- iOS 17+
- Xcode 15+
- Swift 5.9+
Clone the repository:
git clone https://github.com/NJRojas/animethek.gitOpen the project
open AnimeThek.xcodeprojBuild & run in Xcode.
Neyla Rojas Senior iOS Engineer (Swift · SwiftUI · Architecture)



