This episode guides you through creating a new Compose project in Android Studio, understanding build.gradle.kts and the required plugins, writing your first composable with a preview, and running the application on the emulator.

In episode 2 you understood the concepts: composable functions, recomposition, and the composition tree. Now it's time to put those concepts into a real project. Episode 3 guides you from the New Project screen to your first application running on the emulator.
The first project is where many people get lost: the wrong plugin version, mismatched kotlinOptions, or a preview that won't show up. That's why this episode also dissects the Gradle configuration that shapes a Compose project, so you understand rather than just press buttons.
Episode 3 covers creating the project, structure and configuration, your first composable with a preview, and running the application.
Open Android Studio and select New Project. Choose the Empty Activity template — this template already enables Compose and provides one simple composable. Give the project a name, for example BelajarCompose, with the package id.devnull.belajarcompose.
Choose minimum SDK API 24 (Android 7.0) as a reasonable baseline, then click Finish. Android Studio syncs Gradle automatically; wait until the status bar finishes without errors.
A standard Compose project has two build files: build.gradle.kts at the root and app/build.gradle.kts. The root Gradle file declares the plugins used, while the app file contains the module configuration. This configuration is what connects Kotlin, Android, and the Compose compiler.
Starting with the Compose Compiler Gradle Plugin (since Kotlin 2.0), the Compose compiler is configured through a dedicated plugin rather than kotlinOptions in buildFeatures:
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
namespace = "id.devnull.belajarcompose"
compileSdk = 35
defaultConfig {
applicationId = "id.devnull.belajarcompose"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0"
}
buildFeatures {
compose = true
}
}The plugin org.jetbrains.kotlin.plugin.compose ties the compiler version to the Kotlin version, eliminating the version mismatch problems that used to happen often.
The dependencies block includes the Compose BOM, activity-compose, and Material 3 libraries:
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2024.12.01")
implementation(composeBom)
implementation("androidx.activity:activity-compose:1.10.1")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling-preview")
debugImplementation("androidx.compose.ui:ui-tooling")
}With the Compose BOM, you don't need to write version numbers for the ui and material3 libraries — the BOM guarantees they're all compatible. You can see the actual resolved dependencies with the command ./gradlew :app:dependencies.
Replace the contents of MainActivity.kt with a simple screen that uses setContent:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BelajarComposeTheme {
KartuSapa("Dunia")
}
}
}
}
@Composable
fun KartuSapa(nama: String) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = "Halo, $nama!",
modifier = Modifier.padding(24.dp),
style = MaterialTheme.typography.headlineMedium
)
}
}setContent { ... } opens the composition context for the Activity, and BelajarComposeTheme is the theme from the template. Compose turns KartuSapa("Dunia") into a UI tree — the composition tree concept you learned in episode 2.
Preview lets you see the UI without running the emulator. Create a second function annotated with @Preview:
@Preview(showBackground = true, showSystemUi = true)
@Composable
fun KartuSapaPreview() {
BelajarComposeTheme {
KartuSapa("Preview")
}
}@Preview(showBackground = true, showSystemUi = true) displays the composable in the Design editor panel. Preview is an amazing debugging tool — the combination of the editor and real-time preview will be covered further in episode 21.
Make sure the emulator from episode 0 is running, then run the application. From Android Studio, press the Run icon. From the terminal, you can build and install manually:
./gradlew :app:assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n id.devnull.belajarcompose/.MainActivity./gradlew :app:assembleDebug produces the debug APK, adb install ... installs it, and adb shell am start -n id.devnull.belajarcompose/.MainActivity opens the Activity directly from the terminal.
If the build fails, check in this order: the Gradle sync has finished, the SDK Platform matches compileSdk, and the Compose plugin has been added. The error message Unresolved reference: Compose almost always points to a plugin or dependency that hasn't been synced.
Episode 3 took you from the New Project screen to your first running Compose application: understanding the Gradle configuration with the Compose Compiler plugin and BOM, writing your first composable with setContent, creating a preview, and running it on the emulator via Android Studio or the terminal.
Key takeaways:
org.jetbrains.kotlin.plugin.compose manages the compiler since Kotlin 2.0.setContent opens the composition context inside the Activity.@Preview displays a composable directly in the editor../gradlew :app:assembleDebug and adb install run the application from the terminal.In episode 4 we will discuss layouting and UI building blocks — Column, Row, Box, LazyColumn, and LazyRow, Material components like Button and Card, and the Modifier system for spacing, alignment, and responsive layout.