本文へ移動
cccskills
無料GitHub で公開

jetpack-compose-navigation-expert

Jetpack Compose navigation expert with type-safe routes, Hilt DI, and MVVM/MVI architecture. Activate on: Jetpack Compose navigation, Compose type-safe routes, Hilt dependency injection, MVVM Android, MVI pattern, Compose state management, NavHost, ViewModel. NOT for: XML layouts (use frontend-architect), iOS SwiftUI (use swiftui-data-flow-expert), React Native (use react-native-architect).

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Jetpack Compose Navigation Expert

Expert in Jetpack Compose navigation with type-safe routes, Hilt dependency injection, and clean MVVM/MVI architecture.

Activation Triggers

Activate on: "Jetpack Compose navigation", "Compose type-safe routes", "Hilt DI", "MVVM Android", "MVI pattern", "Compose state management", "NavHost", "ViewModel Compose", "navigation-compose"

NOT for: XML layouts → frontend-architect | iOS SwiftUI → swiftui-data-flow-expert | React Native → react-native-architect

Quick Start

  1. Add Navigation Compose — implementation("androidx.navigation:navigation-compose:2.9.x") with type-safe routes
  2. Define routes as serializable classes — @Serializable data class ProductRoute(val id: String)
  3. Set up Hilt — @HiltViewModel for ViewModels with constructor injection
  4. Implement MVVM — ViewModel holds UI state, composables observe via collectAsStateWithLifecycle
  5. Handle deep links — declarative deep link mapping in NavHost

Core Capabilities

DomainTechnologies
NavigationNavigation Compose 2.9, type-safe routes, nested graphs
DIHilt 2.53, @HiltViewModel, @Inject, module scoping
ArchitectureMVVM, MVI (Circuit, Mavericks), UDF (unidirectional data flow)
StateStateFlow, collectAsStateWithLifecycle, SavedStateHandle
AsyncKotlin Coroutines, Flow, Room with Flow, Retrofit suspend

Architecture Patterns

Type-Safe Navigation (Compose 2.8+)

// Define routes as serializable data classes
@Serializable
data object HomeRoute

@Serializable
data class ProductRoute(val productId: String)

@Serializable
data class OrderRoute(val orderId: String, val showConfirmation: Boolean = false)

// NavHost with type-safe composable destinations
@Composable
fun AppNavHost(navController: NavHostController = rememberNavController()) {
    NavHost(navController = navController, startDestination = HomeRoute) {
        composable<HomeRoute> {
            HomeScreen(
                onProductClick = { id ->
                    navController.navigate(ProductRoute(productId = id))
                }
            )
        }
        composable<ProductRoute> { backStackEntry ->
            val route = backStackEntry.toRoute<ProductRoute>()
            ProductScreen(productId = route.productId)
        }
        composable<OrderRoute> { backStackEntry ->
            val route = backStackEntry.toRoute<OrderRoute>()
            OrderScreen(orderId = route.orderId)
        }
    }
}

MVVM with Hilt and UDF

@HiltViewModel
class ProductViewModel @Inject constructor(
    private val repository: ProductRepository,
    savedStateHandle: SavedStateHandle,
) : ViewModel() {

    private val productId: String = savedStateHandle.toRoute<ProductRoute>().productId

    private val _uiState = MutableStateFlow<ProductUiState>(ProductUiState.Loading)
    val uiState: StateFlow<ProductUiState> = _uiState.asStateFlow()

    init { loadProduct() }

    fun onEvent(event: ProductEvent) {
        when (event) {
            is ProductEvent.AddToCart -> addToCart(event.quantity)
            is ProductEvent.Refresh -> loadProduct()
        }
    }

    private fun loadProduct() {
        viewModelScope.launch {
            _uiState.value = ProductUiState.Loading
            repository.getProduct(productId)
                .onSuccess { _uiState.value = ProductUiState.Success(it) }
                .onFailure { _uiState.value = ProductUiState.Error(it.message) }
        }
    }
}

// Composable observes state
@Composable
fun ProductScreen(viewModel: ProductViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    when (val state = uiState) {
        is ProductUiState.Loading -> LoadingIndicator()
        is ProductUiState.Success -> ProductContent(
            product = state.product,
            onEvent = viewModel::onEvent,
        )
        is ProductUiState.Error -> ErrorMessage(state.message)
    }
}

Nested Navigation Graphs

Root NavHost
  ├─ Auth Graph (unauthenticated)
  │   ├─ Login
  │   ├─ Register
  │   └─ ForgotPassword
  ├─ Main Graph (authenticated)
  │   ├─ Home Tab
  │   │   ├─ Feed
  │   │   └─ Product Detail
  │   ├─ Search Tab
  │   │   ├─ Search
  │   │   └─ Category
  │   └─ Profile Tab
  │       ├─ Profile
  │       └─ Settings
  └─ Fullscreen overlays (shared)
      ├─ ImageViewer
      └─ VideoPlayer

Anti-Patterns

  1. String-based routes — navController.navigate("product/123") is error-prone. Use type-safe route classes (@Serializable data class ProductRoute(val id: String)).
  2. ViewModel in composable — creating ViewModel instances inside composables. Use hiltViewModel() which handles scoping to the NavBackStackEntry.
  3. Collecting Flow without lifecycle — collectAsState() keeps collecting when the app is backgrounded. Use collectAsStateWithLifecycle() to respect lifecycle.
  4. God ViewModel — single ViewModel for an entire feature with 20+ state fields. Split into smaller ViewModels or use MVI with sealed state classes.
  5. Navigation in ViewModel — calling navController.navigate() from ViewModel. Instead, expose navigation events via SharedFlow or callback lambdas; let the composable handle navigation.

Quality Checklist

[ ] Type-safe navigation routes using @Serializable classes
[ ] Hilt configured with @HiltViewModel for all ViewModels
[ ] UI state collected with collectAsStateWithLifecycle
[ ] Unidirectional data flow: events up, state down
[ ] Deep links configured in NavHost
[ ] Navigation tested with TestNavHostController
[ ] SavedStateHandle used for process death restoration
[ ] Nested graphs for auth, main, and feature flows
[ ] No navigation logic in ViewModels (events/callbacks instead)
[ ] Compose previews with mock data for all screens
[ ] ProGuard/R8 rules configured for serializable routes
[ ] Screen transitions animated with shared element transitions

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Expert in 2000s-era music visualization (Milkdrop, AVS, Geiss) and modern WebGL implementations. Specializes in Butterchurn integration, Web Audio API AnalyserNode FFT data, GLSL shaders for audio-reactive visuals, and psychedelic generative art. Activate on "Milkdrop", "music visualization", "WebGL visualizer", "Butterchurn", "audio reactive", "FFT visualization", "spectrum analyzer". NOT for simple bar charts/waveforms (use basic canvas), video editing, or non-audio visuals.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Expert legal research agent for finding and scraping expungement data state by state. Knows authoritative sources, URL patterns, Firecrawl configuration, and 2026 legal landscape.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Expert in 3D computer vision labeling tools, workflows, and AI-assisted annotation for LiDAR, point clouds, and sensor fusion. Covers SAM4D/Point-SAM, human-in-the-loop architectures, and vertical-specific training strategies. Activate on '3D labeling', 'point cloud annotation', 'LiDAR labeling', 'SAM 3D', 'SAM4D', 'sensor fusion annotation', '3D bounding box', 'semantic segmentation point cloud'. NOT for 2D image labeling (use clip-aware-embeddings), general ML training (use ml-engineer), video annotation without 3D (use computer-vision-pipeline), or VLM prompt engineering (use prompt-engineer).

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Apply crisis decision-making research to agent routing, uncertainty triage, and coordination failure analysis in time-pressured systems. Use when diagnosing handoff failures, analytical paralysis, or expert judgment under incomplete information. NOT for routine coding, simple CRUD design, or static single-agent tasks with complete information.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Use for insight, reframing, contradiction, impasse, and anomaly-driven problem solving when execution effort no longer helps. NOT for routine optimization, error correction, or well-specified tasks with known solution paths.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

Apply normative BDI reasoning to agents that must detect norms, choose which commitments to internalize, and resolve conflicts by comparing consequences. Use when obligations, prohibitions, or policies collide in autonomous systems. NOT for simple fixed-priority rules, pure constraint satisfaction, or domains where no real normative conflict exists.

日本語の概要は準備中です。原文の説明を表示しています。

curiositech/windags-skills132026年10月12日 更新

curiositech のスキルをすべて見る

このスキルの問題を報告する