# nowinandroid: the reference Android app, and the parts worth copying

> Google's Kotlin and Compose reference app, fully modularized, with test doubles instead of mocks and screenshot tests that catch layout regressions. Aimed at learning architecture, not features.

**android/nowinandroid** — A fully functional Android app built entirely with Kotlin and Jetpack Compose

- Repository: https://github.com/android/nowinandroid
- Stars: 21,906 · Forks: 4,673
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/android-nowinandroid

## A news reader that exists to demonstrate architecture

Now in Android is a fully functional Android app built entirely with Kotlin and Jetpack Compose, and the README is explicit about its purpose: it is intended to be a useful reference for developers, and as a running app it helps developers keep up with the world of Android development by providing regular news updates. The content comes from the Now in Android article series, with browsing for videos and articles, followed topics, and notifications when new content matches a topic you follow.

So the feature list is deliberately thin and the engineering is the point. The README calls it a work in progress and links three documents as the real content: a design case study, an architecture learning journey and a modularization learning journey.

It is a real app, not a shell. The `prodRelease` variant is on the Play Store, and the two published releases in the repository show it shipping actual user-facing changes. Play release 0.1.1 added search with locally saved recent searches, notifications for followed topics, push based data sync so content arrives without waiting for a network sync, an unread dot on new content and on the affected tabs, and undo for bookmark removal via a SnackBar.

Apache 2.0 licensed, 21.8 thousand stars, 4.6 thousand forks, and 281 open issues. The last push to `main` was on 2026-09-20.

## demoDebug versus prod, and why the demo flavor matters

The build setup is where a reference app earns or loses new readers, and here it is done well. Two product flavors control where content comes from. The `demo` flavor uses static local data so the app builds and is explorable immediately. The `prod` flavor makes real network calls to a backend server, and at present there is no public backend available, which is why the Play Store app is the `prodRelease` variant.

For normal development use `demoDebug`. For UI performance testing use `demoRelease`, because a debug build is not representative. There is also a `benchmark` variant of `app` used to test startup performance and generate a baseline profile, and a second standalone app called `app-nia-catalog` that displays the list of components stylized for Now in Android, which is a small but nice way to see the design system isolated from the app.

Setting up means importing the project into Android Studio with the latest stable version, changing the run configuration to `app`, and pressing play. There is no key to configure, no account to create, and no backend to stand up. For an app whose entire job is to be read by other developers, that matters more than any individual library choice.

## No mocking libraries, on purpose

The testing section is the most opinionated part of the README and the most copied. Dependency injection comes from Hilt, most data layer components are defined as interfaces, and concrete implementations with various dependencies are bound to those interfaces in the app. Then comes the part that surprises people: in tests, the project notably does not use any mocking libraries.

Instead, the production implementations are replaced with test doubles using Hilt's testing APIs, or through manual constructor injection for `ViewModel` tests. Those doubles implement the same interface as the production class and generally give a simplified but still realistic implementation with extra testing hooks.

The stated benefit is less brittle tests that exercise more production code, rather than verifying specific calls against mocks. Two concrete examples make the argument. In instrumentation tests, a temporary folder stores user preferences and is wiped after each test, which lets the tests use the real `DataStore` and exercise all related code rather than mocking a flow of data updates. There are `Test` implementations of each repository that implement the full repository interface plus test-only hooks, so a `ViewModel` test can manipulate the repository state directly and verify the resulting behaviour, instead of asserting that a particular repository method was called.

The second point is about coverage rather than mechanics: the repository interface is the seam, and a fake that honours the whole interface will keep working when the implementation changes. A mock that asserts `repository.getTopic(id) was called` breaks the moment you add caching.

## Screenshot tests for layout, not just logic

Beyond the unit and instrumentation tests there is a screenshot test suite, and it addresses something unit tests cannot see at all. A screenshot test captures a screen or component, renders it, and compares the result against a previously recorded image known to be correct.

Now in Android uses this to verify that navigation displays correctly at different screen sizes, with the known correct screenshots committed in the repository under `app/src/testDemo/screenshots` and the test itself at `NiaAppScreenSizesScreenshotTests.kt` inside the `app` module. Rendering is handled by Roborazzi.

This has a practical consequence worth planning for. The local test task runs against the `demoDebug` variant, and screenshot tests will fail unless the images have been recorded first, so the README tells you to run `recordRoborazziDemoDebug` before running unit tests. That is not a bug, it is the intended workflow, but it does mean the very first `./gradlew` run on a fresh clone produces failures unless you know the order.

The other warning is the one people hit repeatedly. Do not run the bare `test` or `connectedAndroidTest` tasks, because those execute against all build variants and will fail, since only the `demoDebug` variant is supported and no other variants have tests. Use the variant-specific tasks instead:

```bash
./gradlew testDemoDebug
./gradlew connectedDemoDebugAndroidTest
```

## Fully modularized, with the strategy written down

The architecture section is one sentence long and points at the official Android architecture guidance, deferring the detail to `docs/ArchitectureLearningJourney.md`. The modularization section is the same shape, pointing at `docs/ModularizationLearningJourney.md`.

Those two documents are the reason to clone this repository, more than the app itself. The tree shows what a fully modularized Compose project looks like in practice: `core/` for shared infrastructure, `feature/` for feature modules, `app/` for the application module, plus `sync/`, `benchmarks/`, `build-logic/`, `lint/`, `spotless/`, `tools/` and a `ui-test-hilt-manifest/`. There is also an `app-nia-catalog/` module as described earlier, and both `AGENT.md` and `AGENTS.md` at the root, which is a sign that the project has been wired up for agent-assisted development.

Modularizing a sample app is a real risk of over-engineering, and it is the criticism that gets levelled at this repository most often. The defence is that the module boundaries here are the argument: a feature module that can be read on its own, with dependencies injected rather than reached for globally, is the thing the project is trying to teach.

The repository also carries `build_android_release.sh` and a `kokoro/` directory, which is what continuous integration for a Google sample project looks like behind the scenes. The two Play releases in the list are old, from 2023, so the release tags are not a useful signal of current activity. The commit activity is: pushed on 2026-09-20.

## Who should read this, and who should not

The case for reading this repository is strongest if you are building an app with more than one screen and more than one person who will touch it, and you want conventions rather than principles. Data layer interfaces bound through Hilt, state holders in the ViewModel with no Android references, unidirectional data flow, a design system module, and tests that use fakes rather than mocks is a coherent position you can adopt wholesale.

It is also the right companion to the ndk-samples repository if your app touches native code. That README points at Now in Android explicitly, calling it an excellent resource for production quality apps in general while noting it does not touch NDK specific issues, so between the two you get the native layer and the app layer covered.

The case against is a single app feature set. There is no account system, no payments, no offline sync conflict resolution, no multi-tenant anything. If your product has hard problems in those areas, Now in Android will not have answers for them, and reading it as an architecture reference rather than a starting point is the right posture.

One more caveat: it follows the official Android architecture guidance closely, which means it will change as that guidance changes. Anyone adopting its patterns should read the current official docs alongside it rather than treating the repository as the authority.

## Conclusion

Now in Android earns its reputation in the parts the Play Store listing never shows: data layer interfaces bound through Hilt, test doubles that exercise real DataStore code instead of asserting mock calls, Roborazzi screenshot tests for navigation at multiple screen sizes, and a module layout described in enough detail in the modularization learning journey that you can copy the strategy rather than the files. The demo flavor building with static local data is the detail that decides whether you will actually read it, since a reference app you cannot run teaches you nothing. Start with `docs/ArchitectureLearningJourney.md`, then the modularization document, and treat the `feature/` and `core/` directories as the worked example.

## FAQ

### Can I run nowinandroid locally without a backend server?

Yes, and you should. The `demo` flavor uses static local data so the app builds and is explorable immediately, and `demoDebug` is the variant to use for normal development. Only the `prod` flavor makes real network calls, and there is no public backend available, so the `prod` variants are not usable as-is.

### Why do nowinandroid tests fail on the first run?

Two reasons documented in the README. Screenshot tests need to be recorded first, so run `recordRoborazziDemoDebug` before the unit tests. And you should not run the bare `test` or `connectedAndroidTest` tasks, because they execute against all build variants when only `demoDebug` has tests. Use `testDemoDebug` and `connectedDemoDebugAndroidTest` instead.

### Does nowinandroid use mocking libraries for testing?

No, and that is deliberate. The README says the project notably does not use any mocking libraries in tests. Instead, production implementations are replaced with test doubles through Hilt's testing APIs or manual constructor injection, and those doubles implement the same interface with extra test-only hooks, so tests exercise real code rather than asserting calls against mocks.

### Where should I start reading the nowinandroid codebase?

With the documents the README links: `docs/ArchitectureLearningJourney.md` for the architecture and `docs/ModularizationLearningJourney.md` for how the app was split into modules, plus the design case study for the visual side. The `feature/` and `core/` directories in the tree are the worked example those documents describe.

### Is nowinandroid a good starting point for a production app?

It is a good reference for architecture rather than a template to fork. The feature set is deliberately narrow, a news reader for the Now in Android article series, so there is nothing about accounts, payments or offline conflict resolution to copy. The parts worth adopting are the module layout, the data layer interfaces bound through Hilt, and the fake-based test approach.

## Sources

- [android/nowinandroid on GitHub](https://github.com/android/nowinandroid)
- [Issues](https://github.com/android/nowinandroid/issues)
- [License: Apache-2.0](https://github.com/android/nowinandroid/blob/main/LICENSE)
- [README](https://github.com/android/nowinandroid/blob/main/README.md)
- [Releases](https://github.com/android/nowinandroid/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/android-nowinandroid
