| name | scaffold-android-feature |
| description | Scaffold a new Android feature module for eZansiEdgeAI with standard structure: Activity/Fragment or Composable, ViewModel, Repository interface, DI setup, and test stubs. Use this skill each time a new feature screen is added (chat, topics, profiles, preferences, library).
|
Scaffold Android Feature Module
Creates a new feature module under apps/learner-mobile/ following the eZansiEdgeAI 4-layer architecture and project conventions.
When to Use
Use this skill whenever you need to create a new feature module for the learner mobile app. Each major screen area gets its own feature module:
:feature:chat โ Chat interface
:feature:topics โ Topic browser
:feature:profiles โ Learner profile selection
:feature:preferences โ Preference engine UI
:feature:library โ Content library management
Inputs
Before running this skill, you need:
- Feature name (lowercase, hyphenated) โ e.g.,
chat, topics, profiles
- Package name suffix โ e.g.,
chat, topics, profiles
- Primary screen type โ Fragment (View system) or Composable (Compose)
- Dependencies โ Which core modules it depends on (
:core:ai, :core:data, :core:common)
Output Structure
For a feature named {name} with package com.ezansi.app.feature.{name}:
apps/learner-mobile/feature/{name}/
โโโ build.gradle.kts
โโโ src/
โโโ main/
โ โโโ AndroidManifest.xml
โ โโโ kotlin/com/ezansi/app/feature/{name}/
โ โโโ {Name}Screen.kt # UI (Composable or Fragment)
โ โโโ {Name}ViewModel.kt # Presentation logic
โ โโโ navigation/
โ โโโ {Name}Navigation.kt # Navigation graph contribution
โโโ test/
โโโ kotlin/com/ezansi/app/feature/{name}/
โโโ {Name}ViewModelTest.kt # ViewModel unit test stub
build.gradle.kts Template
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.ezansi.app.feature.{name}"
compileSdk = libs.versions.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
implementation(project(":core:common"))
testImplementation(libs.junit5)
testImplementation(libs.kotlin.test)
}
ViewModel Template
package com.ezansi.app.feature.{name}
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
data class {Name}UiState(
val isLoading: Boolean = false,
)
class {Name}ViewModel : ViewModel() {
private val _uiState = MutableStateFlow({Name}UiState())
val uiState: StateFlow<{Name}UiState> = _uiState.asStateFlow()
}
Conventions
- Feature modules depend on
:core:* modules only โ never on other :feature:* modules
- ViewModels expose
StateFlow<UiState> โ no LiveData
- UI communicates with core layer via repository interfaces injected into ViewModel
- All user-facing strings go in
res/values/strings.xml for localisation
- All colours reference the app theme โ no hardcoded values
- Touch targets โฅ 48ร48 dp (accessibility requirement ACC-02)
- Grade 4 reading level for all UI text (ACC-07)
Post-Scaffold Checklist
After scaffolding, verify: