An Android project organized only into activities, viewmodels, and repositories becomes difficult to navigate as features multiply.
I begin with feature ownership:
feature/
fitness/
nutrition/
home/
vobbinai/
core/
health/
network/
storage/
sync/
ui/
components/
theme/
Feature packages own screens, ViewModels, contracts, and feature-specific clients. Core packages contain stable platform capabilities such as Room, Health Connect, observability, and synchronization.
Compose functions render immutable state and emit user intent. ViewModels coordinate use cases. Repository and platform implementations own I/O. Pure scoring or mapping code stays free of Android dependencies.
Do not create a shared component because two buttons look similar once. Shared UI should encode a stable visual or accessibility contract. Feature-specific composition remains with the feature.
The same rule applies to modules. Packages can establish boundaries before Gradle modules are worth their build cost. Split modules when ownership, build isolation, reuse, or dependency enforcement provides measurable value.
Architecture should make a feature easy to locate and change. The directory tree is useful only when its dependency direction matches the names.