Add feature module
Skill komodgn/meta-android/.claude/skills/add-feature-module
Meta Search Android App
npx -y skills add komodgn/meta-android --skill add-feature-moduleAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Creates a new feature module in the MetaSearch Android project using Circuit and Metro. Use this skill when requested to 'add feature module', 'add a new feature' or 'add a new screen'.
SKILL.md
6.9 KB, as published. Nobody here has run it
Feature Module Creation Skill
This skill creates a new feature module in the feature/ package.
Prerequisites & Pre-steps
Before generating the module, confirm:
- Screen Definition (Crucial): Before creating a new feature module, you MUST first add the new
Screendefinition tocom.metasearch.android.feature.screens.Screens.kt.- Ensure the new
Screen(object or data class) is defined and registered in that file.
- Ensure the new
- Module Naming:
{module}: Must be snake_case (e.g.,person_detail).{Module}: Must be PascalCase (e.g.,PersonDetail).
- Module Purpose (What feature/screen this is for)
- Domain Dependencies (Which
domain.*.apimodules are needed)
Implementation Steps
1. Gradle Configuration (build.gradle.kts)
Each feature module must use the standard feature plugins.
Note: All feature modules automatically depend on feature.screens, so you do not need to add it manually.
plugins {
alias(libs.plugins.metasearch.android.feature)
alias(libs.plugins.metasearch.test)
}
android {
namespace = "com.metasearch.android.feature.{module}"
}
dependencies {
// Note: projects.feature.screens is already provided by the feature plugin.
// Add required Domain APIs here
// implementation(projects.domain.{domain}.api)
}
2. File Structure
Create the source directory structure:
feature/{module}/src/main/java/com/metasearch/android/feature/{module}/
Screen Definition
All Screen classes should be defined in the feature.screens module.
Do not define new Screen classes inside the feature module.
Instead, reference the existing Screen from com.metasearch.android.feature.screens.
Screen Definition Example
When adding a new screen to feature/screens/Screens.kt, follow these patterns:
1. For simple screens (No parameters):
@Parcelize
data object {Module}Screen : Screen
2. For screens with parameters:
@Parcelize
data class {Module}Screen(
val id: Long,
) : Screen
Key Files to Create
(using {Module} as PascalCase):
{Module}Presenter.kt: Handles business logic.
package com.metasearch.android.feature.{module}
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import com.metasearch.android.feature.screens.{Module}Screen
import com.slack.circuit.codegen.annotations.CircuitInject
import com.slack.circuit.runtime.Navigator
import com.slack.circuit.runtime.presenter.Presenter
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject
@AssistedInject
class {Module}Presenter(
@Assisted private val navigator: Navigator,
// TODO: Inject UseCases or Repository
) : Presenter<{Module}UiState> {
@CircuitInject({Module}Screen::class, AppScope::class)
@AssistedFactory
fun interface Factory {
fun create(navigator: Navigator): {Module}Presenter
}
@Composable
override fun present(): {Module}UiState {
val scope = rememberCoroutineScope()
// TODO: Define states (remember / rememberRetained)
fun handleEvent(event: {Module}UiEvent) {
when (event) {
// TODO: Handle events
}
}
return {Module}UiState(
eventSink = ::handleEvent,
// TODO: Assign states
)
}
}
{Module}Ui.kt: UI components, annotated with@CircuitInject({Module}Screen::class, AppScope::class).
package com.metasearch.android.feature.{module}
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.metasearch.android.feature.screens.{Module}Screen
import com.slack.circuit.codegen.annotations.CircuitInject
import dev.zacsweers.metro.AppScope
@CircuitInject({Module}Screen::class, AppScope::class)
@Composable
fun {Module}Ui(
state: {Module}UiState,
modifier: Modifier = Modifier,
) {
// TODO: Implement UI using MetaSearchTheme
}
{Module}UiState.kt: UI state data class.
package com.metasearch.android.feature.{module}
import com.slack.circuit.runtime.CircuitUiEvent
import com.slack.circuit.runtime.CircuitUiState
data class {Module}UiState(
val eventSink: ({Module}UiEvent) -> Unit,
// TODO: Add state properties
) : CircuitUiState
sealed interface {Module}UiEvent : CircuitUiEvent {
// TODO: Add events
}
3. Registration
Add the new module to the project and link it to the app module.
settings.gradle.ktsInclude the new module in the feature modules block (maintain alphabetical order):
include(":feature:{module}")
app/build.gradle.ktsAdd the dependency using the type-safe Gradle accessor.
- Note: Gradle automatically generates a
camelCaseaccessor for everysnake_casemodule name you define insettings.gradle.kts. - Mapping Rule:
person_detail(snake_case) →personDetail(camelCase)
// Always use the camelCase accessor (e.g., personDetail)
implementation(projects.feature.{Module})
- Sync & Verify:
./gradlew :feature:{module}:compileDebugKotlin
Naming & Architecture Rules
| Item | Convention | Example(module=person_detail) |
|---|---|---|
| Module Directory | snake_case | person_detail |
| Class Prefix | PascalCase | PersonDetail |
| Namespace | com.metasearch.android.feature.{module} | com.metasearch.android.feature.person_detail |
| Screen Reference | Import from feature.screens | PersonDetailScreen |
| Settings(Gradle) | :feature:{module} | :feature:person_detail |
| Type-safe Accessor | projects.feature.{Module} (camelCase) | projects.feature.personDetail |
Best Practices
- Screen Definition: Always define new
Screenclasses infeature/screens/Screens.ktfirst. Never define them inside feature modules. - Design System: Always use
MetaSearchThemetokens from:core:designsystem. Do not hardcode colors or spacing. - Circuit Inject: Every UI Composable must be annotated with
@CircuitInject. - UI: UI Composables should be stateless and take State and Event lambdas as parameters.