Compose Navigation Graph: rendering your Android app flow as a map inside Android Studio
⛵️ Compose Navigation Graph plugin for Android Studio that visualizes your entire app flow as an interactive map of rendered previews, typed arguments, and transitions.
At a glance
- What is it?
- Compose Navigation Graph is an IntelliJ and Android Studio plugin plus a Gradle and KSP toolkit that turns annotated Compose screens into a merged, multi-module navigation map with device-free thumbnails. It fits teams whose navigation has outgrown reading entry lambdas by hand.
- Who is it for?
- Adopt Compose Navigation Graph if your Compose app spans several modules, you already write @Preview functions, and you want navigation changes visible in pull requests through a committed .nav baseline. Skip it if your app has a handful of screens in one module, or if you cannot accept a KSP processor and a Layoutlib rendering step in your build.
- Can I use it commercially?
- Yes. Apache-2.0 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 12 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 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: navigation that only exists as scattered call sites
In a Compose app, the navigation graph is not a file. It is the sum of entry<Route> { } lambdas, backStack.add(...) call sites and NavHost declarations spread across modules. Reading it means holding several files in your head at once, and nothing fails when a destination quietly stops being reachable. The README frames the plugin's purpose exactly this way: instead of reconstructing the flow from those call sites, you get one interactive canvas with every destination, its rendered thumbnail, its typed arguments and the transitions between screens. The audience is Android and Kotlin Multiplatform teams using Navigation 2, Navigation 3, other Compose navigation libraries, or plain Activities. The project does not require you to switch navigation libraries, which is the main reason it is worth a look rather than a rewrite.
Four pieces: annotations, KSP, Gradle plugin, IDE plugin
The toolkit is split into four cooperating parts, and knowing which one does what explains most of its behaviour. Annotations live in com.github.skydoves:compose-nav-graph-annotations: @NavDestination, @NavEdge, @NavPreview and @NavGraphRoot describe the graph in code. A KSP processor, com.github.skydoves:compose-nav-graph-ksp, statically extracts each module's graph into nav-graph.json at compile time. The Gradle plugin, id("com.github.skydoves.navgraph"), does the heavier work: it renders device-free Layoutlib thumbnails, infers the transitions KSP cannot read from your navigation call sites, merges the graph across modules, and exposes the generateNavGraph, navDump, navCheck and export tasks. The IDE plugin, compose-nav-graph-idea, draws the merged result and a preview gallery in the NavGraph Graph tool window. The dependency chain matters: annotations and KSP arrive automatically when you apply the Gradle plugin, so the only coordinate you type by hand is the plugin id and its version.
Installing the IDE plugin and applying the Gradle plugin
The IDE side is a normal marketplace install. Open Android Studio or IntelliJ IDEA, go to Settings, then Plugins, then Marketplace, search for Compose Navigation Graph and install. The README says that once installed you open View, then Tool Windows, then NavGraph Graph, and if you see the Graph, Previews and Author tabs, the plugin is ready.
The build side needs mavenCentral() in your plugin repositories. In settings.gradle.kts the README shows this block:
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}Then apply KSP and the navgraph plugin to the module that holds your screens. The README notes that this is all you need, because the annotations and the KSP processor are added for you:
plugins {
id("com.google.devtools.ksp") version "<matching your Kotlin version>"
id("com.github.skydoves.navgraph") version "0.2.1"
}The version 0.2.1 is the most recent release listed for the project, published on 2026-07-04. The KSP version placeholder is intentional: the README does not pin one, and mismatching it against your Kotlin version is the first thing that will break.
Configuring navgraph { } and what each switch costs you
The navgraph { } block is where the trade-offs live. The README shows five keys with their defaults, and reading them together tells you the plugin is opinionated in a particular direction: it renders, it infers, and it fails builds.
navgraph {
renderThumbnails.set(true) // device free Layoutlib thumbnails (default true)
variant.set("demoDebug") // pin a flavor; blank auto detects the debug KSP variant
inferEdges.set(true) // read transitions from your navigation call sites (default true)
failOnNavChange.set(true) // navCheck fails the build when the graph drifts (default true)
galleryEnabled.set(true) // the preview gallery pipeline (default true)
}renderThumbnails being on by default means every build pays for Layoutlib rendering of your previews, with no emulator involved. That is the feature that makes the map readable, and also the feature most likely to slow a large module down; turning it off leaves you a graph without pictures. failOnNavChange being true by default is the more consequential choice. It means a committed .nav baseline can fail the build when destinations or transitions drift, which is the pull-request validation story the README advertises. Teams that want the graph as a reference rather than a gate should set it to false deliberately, not discover it after a red CI run. The variant key exists because flavor detection is not always reliable; pinning it explicitly is the safer path in a flavored project.
Where it stops helping
The plugin is static analysis plus rendering, and it inherits the limits of both. KSP reads your code at compile time, so transitions built from runtime values, reflection or data-driven routing are outside what it can extract; the Gradle plugin's edge inference from navigation call sites is the mitigation, and the README does not claim it covers everything. Layoutlib thumbnails are not emulator screenshots: they render your @Preview functions, so a screen without a preview has no picture in the map, and previews that depend on runtime state will not represent what the user sees. This is a development-time tool, not a runtime monitor. It will not tell you which screens real users reach, in what order, or how often. If your question is about production navigation behaviour rather than source structure, this is the wrong tool. There is also a build-time cost and a new failure surface: a KSP processor in the compile path and a rendering step that can break independently of your app code.
Alternatives and how the approach differs
The obvious comparison is the Android Studio Navigation Editor that ships with the Navigation Component. It gives you a visual graph too, but it is XML-based and oriented around the navigation XML resource rather than Kotlin call sites. In a Compose codebase where routes are types and destinations are composable functions, the editor's model does not line up with the code you actually write. Compose Navigation Graph inverts that: the code is the source of truth, annotations mark it, and the graph is derived. The second comparison is doing nothing and reading entry<Route> { } lambdas by hand. That works fine in a single-module app with a dozen screens, and costs nothing in build time. The plugin earns its place when the graph crosses module boundaries and when you want a diffable artifact in review. Its distinguishing mechanism is the committed .nav baseline: the README states it lets you validate navigation changes in pull requests so no destination or transition changes unreviewed. That review-time gate, not the picture, is the part other approaches do not offer.
Licence, release cadence and upgrade cost
The project is Apache-2.0, with a NOTICE file in the repository alongside the LICENSE, which is the standard arrangement for that licence and worth reading if you redistribute. The last push to the default branch was on 2026-09-06, and the most recent release is 0.2.1 from 2026-07-04, preceded by 0.2.0 on 2026-06-24 and 0.1.2 on 2026-06-17. That is a young version line: three releases inside a month, then a quiet gap to the current date. A renovate.json file at the repository root suggests dependency updates are automated, and the presence of CHANGELOG.md means release notes are the place to check before upgrading. Practically, the upgrade cost is concentrated in two places: the plugin version in your build script and the KSP version you pair with it. Since the annotations and processor are pulled in automatically, a plugin bump moves all three at once, so pin the plugin version rather than tracking a range. The repository also ships samples (sample, sample-kotlinconf, sample-nowinandroid) that show the intended setup in a real project layout.
Editorial conclusion
Adopt Compose Navigation Graph if your Compose app spans several modules, you already write @Preview functions, and you want navigation changes visible in pull requests through a committed .nav baseline. Skip it if your app has a handful of screens in one module, or if you cannot accept a KSP processor and a Layoutlib rendering step in your build. Before rolling it out, verify three things on a branch: that the plugin version you pin resolves on Maven Central, that navDump output matches the graph you expect for one module, and what navCheck reports on a deliberately renamed route. The last one tells you whether the baseline gates your CI the way the README describes.
Frequently asked questions
How do you use Compose in Android?
The README does not teach Compose itself; it assumes you already write composable screens. What it adds is a way to describe those screens' navigation: you annotate destinations with @NavDestination and related annotations, apply the navgraph Gradle plugin, and the KSP processor extracts the graph into nav-graph.json at compile time.
Why do we use Jetpack Compose?
The README does not argue for Compose over other UI toolkits. It targets Compose codebases specifically, and its value proposition is that the navigation graph is derived from the composable code you already write rather than from a separate resource file.
Is Android Compose stable?
The README does not make a claim about Compose's stability. It does state that Compose Navigation Graph works with Navigation 3, Navigation 2, other Compose navigation libraries and plain Activities, so it does not depend on one navigation API being final.
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/skydoves-compose-nav-graph)