Android Showcase 2.0: a reference Android app that is mostly about the build
💎 Android application following best practices: Kotlin, Coroutines, JetPack, Clean Architecture, Feature Modules, Tests, MVVM, DI, Static Analysis...
At a glance
- What is it?
- A Kotlin music discovery app used as a production-ready template, with Clean Architecture feature modules, convention plugins, Konsist convention tests and a quality stack that starts where most templates stop.
- Who is it for?
- What this repository actually offers is not an app but a build system with an app attached to it, and the two halves should be judged separately. The app itself is deliberately thin: a Last.fm backed album list, an album detail screen, two screens marked work in progress, and little else.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The app is a sample domain, not the product
The application is a music discovery app built with Jetpack Compose that displays album information sourced from the Last.fm API, and the stated purpose is to demonstrate real-world scenarios including network requests, local caching, navigation and state management. That is four capabilities, which is the right size for a template. Anything larger would make the architecture harder to read and anything smaller would not exercise Room.
The feature list is correspondingly short: an album list with search functionality, an album detail view with track listings, a favorites screen marked work in progress, and a profile screen for preferences and settings that is also marked work in progress. The screenshots in the README go a little further than that list, adding a settings screen and an open source libraries screen, so the shipped state is slightly ahead of the documented scope.
This is worth stating plainly because the repository description markets the project on practices rather than on features. The description field promises Kotlin, Coroutines, Jetpack, Clean Architecture, feature modules, tests, MVVM, dependency injection and static analysis, and then trails off. Nothing in the description mentions music. The domain exists to give the architecture something real to hang on.
Module layout: four top level directories that mean something
The repository tree is short and legible, which is the first sign of a deliberate structure: `app/`, `feature/`, `library/`, `build-logic/` and `konsist-test/`, alongside the usual suspects of `gradle/`, `settings.gradle.kts`, `gradle.properties` and `build.gradle.kts`. The README's own table of contents promises a section on module types and dependencies and another on feature module structure, divided into presentation, domain and data layers plus common module components.
The dependency inversion is the point of the arrangement. A feature module owns its presentation, domain and data code, and shared code lives in `library/` rather than in the app module, so the direction of dependency is enforced by the build graph rather than by convention. The repository also carries `DeveloperReadme.md` as a separate document from the main README, which is where deeper developer-facing notes tend to live in projects with this much tooling.
Two smaller entries in the tree are easy to overlook and both say something about how the project is maintained. `renovate.json` means dependency updates are automated across the whole multi-module build, which matters a great deal when a project has dozens of version catalog entries. `detekt.yml` at the repository root means the static analysis thresholds are a checked-in decision rather than a default, and someone can read what the project considers too complex.
The quality stack is five tools that would otherwise be three
Most Android templates list a linter. This one lists a stack, and the interesting part is the ktlint configuration. Formatting is handled by ktlint running three rule sets simultaneously: the ktlint standard rules, the Nlopez Jetpack Compose rules, and Twitter's Jetpack Compose rules. Running two independent Compose rule sets against the same code is a deliberate choice, because the two catch different mistakes, and it means a Compose codebase here is checked against more than one opinion about good Compose.
Alongside that, Detekt handles static analysis and complexity checks with the repository level `detekt.yml`, Android Lint covers the platform specific checks, and Spotless handles code formatting. The README describes the last of these plainly as code formatting, which makes the division of labour slightly redundant with ktlint's own role, and that redundancy is worth knowing about before adopting the whole set.
The testing side is equally layered. JUnit 6 is the framework, Mockk handles mocking in a Kotlin-first way, Kluent provides fluent assertions, and Espresso is listed for UI testing and marked work in progress. Konsist sits above all of it as architecture and code structure convention tests, which is the most distinctive choice in the repository: instead of only testing behaviour, this project tests that its own rules are still true.
A convention test can assert that every screen lives in a feature module, that a data layer class never imports a Compose class, or that a ViewModel exposes a single UI state object. That class of test fails at build time when a developer takes a shortcut, which is exactly when a convention is worth enforcing.
Konsist is the piece worth copying first
If you adopt one thing from this repository, the dedicated `konsist-test/` directory is the highest value per line. Konsist is a library for writing architecture rules as Kotlin test code, and giving it its own top level module means those rules are compiled and run with the rest of the suite rather than living in a separate repository that drifts.
The difference from a comment saying do not import this layer is enforcement. A Konsist rule inspects the parsed Kotlin AST of every file in scope and fails the build when a boundary is crossed, and because it is code, the rule has a name, a message and a place in the test report. Teams migrating an existing Android codebase toward Clean Architecture hit the same wall repeatedly, where the layers exist on paper for three months and then a feature module imports a UI class to reuse a string. A failing convention test turns that into a pull request comment rather than an architecture document nobody opens.
It also makes the module graph self-documenting. If the rule says a domain layer must not depend on the data layer, the rule file is a more accurate description of the architecture than any diagram, because it is checked on every build.
Presentation and data flow, as far as the sources say
The README's table of contents lists a Data Flow section and describes the presentation pattern as MVVM plus MVI, calling it a reactive presentation layer pattern providing common UI state. That combination is not contradictory as much as it is two layers doing different jobs: ViewModel handles lifecycle-aware state for the screen, and the MVI part is what produces a single immutable UI state object that Compose renders directly.
The state flows through Kotlin Flow, with coroutines providing the asynchrony, and KSP handling symbol processing, with Kotlin Serialization doing JSON parsing on the network side. Retrofit covers HTTP, Coil handles Compose aware image loading, Room provides the local SQLite cache that makes the album list usable offline, and Navigation Compose provides type-safe navigation across the single activity.
Dependency injection is Koin, described as lightweight, which is the one significant departure from the most common Android template choice. Hilt and Koin solve the same problem differently, and the practical differences show up in build time, in annotation processing requirements and in how tests replace dependencies. There is no compatibility layer here to reason about, only one choice.
The README table of contents also promises sections on Gradle configuration, dependency management, convention plugins, type-safe project accessors, unified version configuration, the CI pipeline and pre-push hooks. Those sections sit beyond the summary text available here, and the parts worth verifying in the repository itself are the convention plugins in `build-logic/`, the version catalog under `gradle/`, and whatever the GitHub workflows directory actually runs.
Activity, licence and where the documentation stops
The last push to the default branch was in September 2026, and the repository is not archived. The numbers give a picture of a well-used template rather than an abandoned one: around 6800 stars and just over 900 forks, which is a fork ratio higher than most projects, consistent with a codebase people copy rather than only read. There are 15 open issues, which is low relative to that scale.
Licensing is MIT, which is what makes the repository usable as a starting point in a commercial project. The README's table of contents reserves a separate section for an animations license, which is a reminder that a template with bundled Lottie assets can carry asset terms that differ from the code licence. The main README also carries a CODE_OF_CONDUCT.md and a CONTRIBUTING.md, so contributions and community expectations are documented.
The version badges claim Kotlin 2.x, AGP 8.x and Gradle 9.x, while the tech stack section specifies Kotlin 2.2 or later. That is a moving target by nature, and the presence of `renovate.json` is the mechanism that keeps it moving. Anyone cloning this should expect to spend the first build resolving versions rather than reading code, and the branch of interest is `main` rather than a tag.
One practical caveat: the README summary text ends at the code quality list, while its table of contents promises considerably more. The remaining sections, including Architecture, Gradle Config, Code Verification, Project Scope and Limitations, Roadmap, Author and the animations licence, need to be read in the repository or in `DeveloperReadme.md`.
Editorial conclusion
What this repository actually offers is not an app but a build system with an app attached to it, and the two halves should be judged separately. The app itself is deliberately thin: a Last.fm backed album list, an album detail screen, two screens marked work in progress, and little else. The engineering value is in `build-logic/`, the feature module boundaries, the Konsist convention tests and the five separate static analysis layers. Copy the module graph and the quality pipeline if you are starting a team project, and expect to replace the music domain wholesale. Read the README table of contents against what is actually in the repository tree, since the architecture and data flow sections it promises live in `DeveloperReadme.md` and in the module sources rather than in the summary.
Frequently asked questions
What is this Android repository actually for?
It is a reference Android application, not a shipped product. The app itself is a small music discovery client over the Last.fm API with an album list, album details and two work in progress screens. The repository is meant to be used as a starting point or as a worked example of Clean Architecture feature modules, convention plugins, Konsist convention tests and a layered static analysis setup.
What does Konsist add that a normal unit test does not?
Konsist tests structure rather than behaviour. Because it parses Kotlin source, it can assert that every screen lives in a feature module, that a domain layer never imports from a data layer, or that a ViewModel exposes a single UI state object. In this repository the tests have their own top level `konsist-test/` module, so the rules compile and run alongside the rest of the suite and fail the build when a boundary is crossed.
Which static analysis tools does the project run?
Five layers are listed. ktlint handles formatting and issue detection with three rule sets loaded at once: the ktlint standard rules, the Nlopez Jetpack Compose rules and Twitter's Jetpack Compose rules. Detekt handles static analysis and complexity checks using the repository level detekt.yml. Android Lint covers platform specific checks, and Spotless handles code formatting. Running two separate Compose rule sets is the notable choice, since it subjects the same code to two independent opinions about Compose style.
Why Koin instead of Hilt?
The README names Koin as the dependency injection framework and describes it as lightweight, with no Hilt option offered alongside it. The practical consequences are build time, whether annotation processing is required, and how tests substitute dependencies. Clean Architecture with feature modules needs a way to build each feature's dependencies independently, and Koin does that without a code generation step.
Can I use this template for a commercial app?
The repository is MIT licensed, so the code can be used as the basis for a commercial project. One detail to check first is the animations licence, which the README's table of contents lists as its own section: bundled Lottie assets can carry asset terms that are separate from the code licence.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/igorwojda-android-showcase)