Skip to content

Sottti/AndroidAppTemplate

Android App Template (AAT)

Android CI API Compose BOM Navigation Kotlin GitHub last commit GitHub repo size License

Modern Kotlin Android app template with Jetpack Compose, Hilt, Navigation 3, Ktor, Room/Paging, Paparazzi, and a modular MVVM/Clean Architecture setup.

⚠️ Disclaimer

This repository intentionally demonstrates a production-ready architecture suited for teams that need to scale quickly and collaborate across multiple features. Elements such as multi-module structure, repository and use-case layers, and other advanced patterns are included to showcase how large, collaborative projects can stay maintainable over time. They may be unnecessary for smaller apps or teams with different preferences. Evaluate each practice against your team's size, project scope, and delivery goals before adopting it wholesale.

🧭 Overview

This project serves as a starter kit for new Android applications. It's designed to save you from the repetitive setup process of configuring dependencies, setting up architecture, and implementing common utilities. Use the template, rename the package and feature placeholders, then start building your app's features.

📷 Screenshots

💡 Light Theme

Characters list screen in light theme Character details screen in light theme

Characters list screen in light theme landscape Character details screen in light theme landscape

Characters list screen in light theme with large font scale

🌙 Dark Theme

Characters list screen in dark theme Character details screen in dark theme

Characters list screen in dark theme landscape Character details screen in dark theme landscape

Characters list screen in dark theme with large font scale

✨ Features

This template is packed with modern libraries and tools from the Android ecosystem:

  • Tech Stack: 100% Kotlin
  • UI: Jetpack Compose for declarative UI.
  • Architecture: Follows Google's official "Guide to app architecture".
    • MVVM (Model-View-ViewModel).
    • UI Layer: State-driven UI with ViewModel, State, and Actions.
    • Domain Layer: (Optional but recommended) for business logic.
    • Data Layer: Repository pattern.
  • Asynchronous work: Kotlin Coroutines & Flows for managing background threads and streams of data.
  • Dependency Injection: Hilt for managing dependencies.
  • Networking: Ktor Client for efficient REST API communication.
  • Serialization: Kotlinx.serialization (used with Ktor) for fast and modern JSON parsing.
  • Build Configuration: Kotlin explicit API mode is enabled across modules to keep public APIs intentional and well-documented.
  • Testing:
    • Unit Tests: JUnit 4
    • Screenshot Tests: Paparazzi
    • UI Tests: Compose Test Rules testing both screen orientations and multiple font scales.
    • Integration Tests: Instrumented Compose flows cover the full stack—from navigation orchestration to feature screens using Hilt-enabled end-to-end journeys and parameterized scenarios that sweep multiple font scales and orientations via the shared BaseUiTest harness.
    • Test Doubles Philosophy: The template deliberately avoids runtime mocking frameworks. Instead, it ships purpose-built fakes that behave like lightweight in-memory implementations of production contracts. This approach keeps tests fast and deterministic, encourages explicit collaboration boundaries, and allows your team to reuse the same fakes across unit, integration, and end-to-end scenarios without the brittleness often introduced by mocks.

▶️ Running the test suites

Execute the following Gradle tasks from the project root to run the automated test suites locally:

ℹ️ Run Gradle with JDK 21 or newer.

Suite Command Description
Local/unit tests ./gradlew testDebug Executes JVM-based tests located under src/test for the debug build variant.
Instrumented Android tests ./gradlew connectedDebugAndroidTest Launches Espresso/Compose instrumentation tests in src/androidTest on a connected emulator or device.

ℹ️ Ensure that an Android emulator or physical device is connected before running the instrumentation suite.

🌟 Additional Highlights

  • Dynamic system theming: The presentation layer streams system theme and contrast updates, maps them through the data/system-features module, and applies them across the Compose UI while synchronizing system bars for a fully adaptive experience.
  • Offline-first paging: The data:characters module layers Room DAOs, Paging 3, and a RemoteMediator on top of the Ktor client so character feeds stay cached and transparently refresh whenever the network is available.
  • Navigation infrastructure: A dedicated Compose Navigation 3 stack coordinates screen changes via a NavigationManager, with Navigator components observing command channels and handling saveable state, back stack pops, and simultaneous navigation requests. All routing code lives in the dedicated presentation:navigation module so feature modules stay navigation-agnostic and decoupled from the implementation details.
  • Snapshot tooling: The presentation module includes a Paparazzi test toolkit featuring a custom Pixel 10 Pro XL device profile and helpers that generate day/night parameter sets for rich screenshot coverage.
  • Preview ergonomics: presentation:previews packages reusable Compose @Preview annotations so feature teams can opt into consistent device sizes, light/dark themes, and dynamic color toggles without re-declaring boilerplate in every screen file.
  • Coroutine utilities: The utils module ships reusable coroutine extensions such as stateInWhileSubscribed and observeConfigurationChanges for concise and lifecycle-aware state management in ViewModels.
  • Build hygiene: Gradle is configured for Kotlin explicit API mode, context receivers, and the Versions Plugin to keep dependencies up to date and compiler flags consistent across modules.
  • Testable system features: The data/system-features module exposes fake managers backed by Turbine-based tests, showcasing how to stub system services when exercising the settings feature.
  • Streamlined startup: A Hilt-enabled Application, splash activity, and edge-to-edge AppShellActivity combine with the navigation manager to launch directly into themed Compose content with minimal boilerplate.
  • Edge-to-edge ready: Compose screens are rendered behind the system bars, with window insets managed centrally so features automatically inherit full-height layouts.

🔭 Incoming Features

  • Multipane large-screen layouts: Adaptive list-detail experiences that keep the character catalog and the selected detail visible side by side on tablets, foldables, and landscape desktops.

🏛️ Architecture (MVVM + Clean)

This template uses a state-driven MVVM (Model-View-ViewModel) architecture combined with principles from Clean Architecture.

  • UI (Compose): Observes State from the ViewModel and sends Actions (user actions) to it. It is passive and dumb.
  • ViewModel: Follows a declarative state holder approach. Handles business logic for the screen. It consumes Actions, interacts with UseCases/Repositories, and exposes a single State Flow for the UI to observe.
  • UseCases (Domain Layer): (Optional) Encapsulates a single piece of business logic (e.g., GetCharacter). This makes logic reusable and easier to test.
  • Repository (Data Layer): The single source of truth for data. It abstracts away the data source (network or local database) and provides a clean API for the ViewModel or UseCases to consume.

🏗️ Project Structure

The repository is laid out as a layered, multi-module Gradle project. Each directory below maps to a distinct slice of the architecture so teams can develop features independently while keeping dependencies explicit.

├── app/                     # Android entry point and app-level configuration
├── data/                    # Repository implementations, remote clients, and system services
├── domain/                  # Business rules, models, and use cases shared by features
├── di/                      # Centralized Hilt bindings that wire modules together
├── presentation/            # Compose UI, navigation stack, previews, and design system
├── utils/                   # Cross-cutting helpers (coroutines, lifecycle, etc.)
├── buildSrc/                # Gradle convention plugins and dependency catalogs
└── gradle/, *.gradle.kts    # Build logic, settings, and version configuration

🗺️ Module Overview

Every Gradle module has a single responsibility. Use the table below to find the code you need:

  • Application shell
    • app: Hosts the Application, activities, and wires the dependency graph at runtime.
  • Presentation layer
    • presentation:design-system: Shared Compose theming, typography, and reusable components.
    • presentation:app-shell: Owns the app shell and top-level screen composition.
    • presentation:features:: Feature-specific screens such as characters-list and character-details.
    • presentation:navigation & presentation:navigation-impl: Navigation contracts and their Compose Navigation 3 implementation.
    • presentation:paparazzi, presentation:previews, presentation:utils, presentation:fixtures: Tooling for previews, snapshot tests, and sample data.
  • Domain layer
    • domain:core-models: Canonical models exchanged between layers.
    • domain:characters, domain:settings, domain:system-features: Use cases and business logic per feature area.
  • Data layer
    • data:characters: Paging, Room cache, and remote mediator for list and detail flows.
    • data:network: Ktor client configuration and API definitions.
    • data:settings: Persistence for user preferences and configuration toggles.
    • data:system-features: Abstractions over device capabilities with test fakes.
  • Dependency injection
    • di: Shared Hilt modules and component wiring consumed across the app.
  • Shared utilities
    • utils:lifecycle: Lifecycle-aware coroutine helpers and Flow extensions reused in ViewModels.

🚀 How to Use This Template

  1. Create Your Repository: Click the "Use this template" button on the GitHub repository page. This will create a new repository in your account with the same file structure.

  2. Clone Your New Repository:

    git clone https://github.com/<your-github-user>/<your-repo>.git
    cd <your-repo>
  3. Rename Package Name: The current package name is com.sottti.android.app.template. To rename it:

    • In Android Studio, right-click the root com.sottti.android.app.template package in the kotlin directory.
    • Select Refactor > Rename.
    • In the dialog, choose Rename package.
    • Enter your new package name (e.g., com.mycompany.myapp).
    • Click Do Refactor.
    • Manually update the applicationId in app/build.gradle.kts to match your new package name.
  4. Sync & Build: Sync the Gradle files and build the project to ensure everything is set up correctly.

  5. Start Coding! You're all set. Start building your app's unique features.

🤝 Contributing

This is a template for your projects, but if you have ideas on how to improve the template itself, contributions are welcome!

See CONTRIBUTING.md for the contribution workflow and pull request expectations.

📜 License

This project is licensed under the MIT License - see the LICENSE file for details.

👋 Contact

If you feel like saying hi, have any comments, suggestions or questions, open an issue or say hi 👋 on X.

About

Modern Kotlin Android app template with Jetpack Compose, Hilt, Navigation 3, Ktor, Room/Paging, Paparazzi, and modular MVVM/Clean Architecture.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages