Create New Feature Screen

Before you dive in, it may be helpful to get familiar with the companion document Screen Structure and Wiring, which explains how the individual classes fit together. With that context in mind, this guide walks you through creating a new feature screen in the project. You can choose one of three paths:

  1. Using file templates — the recommended, fast and stable way
  2. Ask an AI agent — automated, the fastest way
  3. Manual setup — when you need full control or when templates aren't available

Option 1: Using File Templates (recommended)

  1. Ensure the UI Feature template is installed
    • File → Manage IDE Settings → Import Settings...
    • Import file_teamplates.zip from the baselines-kmp root dir
  2. Right-click the destination package → New → UI Feature
  3. Enter the feature name (e.g., Profile, Settings)
  4. Review generated files and fix missing imports
  5. Done 🎉 — your feature is wired into the app

Option 2: Setup via AI Agent

  1. Open chat with your AI assistant and make sure it's aware of ./AGENTS.md file.
  2. Ask to create new feature screen
  3. Provide all the necessary info requested by the AI agent
  4. Done 🎉 — your feature is wired into the app

Option 3: Manual Setup

  1. Create *UiEvent
kotlin
1sealed interface ProfileUiEvent : UiEvent
  1. Create *UiState
kotlin
1@Immutable
2data class ProfileUiState(
3 override val eventSink: (ProfileUiEvent) -> Unit,
4) : UiState<ProfileUiEvent>
  1. Create *ViewModel
kotlin
1@Inject
2class ProfileViewModel : BaselineViewModel<ProfileUiEvent, ProfileUiState>() {
3
4 @Composable
5 override fun state() = ProfileUiState { /* handle events */ }
6}
  1. Create *Screen
kotlin
1@Composable
2fun ProfileScreen(onLogoutClicked: () -> Unit) { /* UI */
3}
  1. Create *Route
kotlin
1@Composable
2fun ProfileRoute(viewModel: ProfileViewModel) {
3 val state = viewModel.state()
4 val eventSink = state.eventSink
5 ProfileScreen(
6 onLogoutClicked = { eventSink(ProfileUiEvent.PerformLogout) }
7 )
8}
  1. Add DI *Module
kotlin
1@ContributesTo(UiScope::class)
2interface ProfileUiModule {
3
4 @Provides
5 @IntoSet
6 fun provideProfileNavGraphEntry(): NavGraphEntry = NavGraphEntry {
7 composable<AppNavRoutes.Profile> {
8 ProfileRoute(metroViewModel())
9 }
10 }
11}
  1. Ensure the feature module is a dependency of app/compose module
  2. Done 🎉 — your feature is wired into the app