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:
- Using file templates — the recommended, fast and stable way
- Ask an AI agent — automated, the fastest way
- Manual setup — when you need full control or when templates aren't available
Option 1: Using File Templates (recommended)
- Ensure the UI Feature template is installed
- File → Manage IDE Settings → Import Settings...
- Import
file_teamplates.zipfrom the baselines-kmp root dir
- Right-click the destination package → New → UI Feature
- Enter the feature name (e.g., Profile, Settings)
- Review generated files and fix missing imports
- Done 🎉 — your feature is wired into the app
Option 2: Setup via AI Agent
- Open chat with your AI assistant and make sure it's aware of
./AGENTS.mdfile. - Ask to create new feature screen
- Provide all the necessary info requested by the AI agent
- Done 🎉 — your feature is wired into the app
Option 3: Manual Setup
- Create
*UiEvent
kotlin1sealed interface ProfileUiEvent : UiEvent
- Create
*UiState
kotlin1@Immutable2data class ProfileUiState(3 override val eventSink: (ProfileUiEvent) -> Unit,4) : UiState<ProfileUiEvent>
- Create
*ViewModel
kotlin1@Inject2class ProfileViewModel : BaselineViewModel<ProfileUiEvent, ProfileUiState>() {34 @Composable5 override fun state() = ProfileUiState { /* handle events */ }6}
- Create
*Screen
kotlin1@Composable2fun ProfileScreen(onLogoutClicked: () -> Unit) { /* UI */3}
- Create
*Route
kotlin1@Composable2fun ProfileRoute(viewModel: ProfileViewModel) {3 val state = viewModel.state()4 val eventSink = state.eventSink5 ProfileScreen(6 onLogoutClicked = { eventSink(ProfileUiEvent.PerformLogout) }7 )8}
- Add DI
*Module
kotlin1@ContributesTo(UiScope::class)2interface ProfileUiModule {34 @Provides5 @IntoSet6 fun provideProfileNavGraphEntry(): NavGraphEntry = NavGraphEntry {7 composable<AppNavRoutes.Profile> {8 ProfileRoute(metroViewModel())9 }10 }11}
- Ensure the feature module is a dependency of app/compose module
- Done 🎉 — your feature is wired into the app