diff --git a/code/aepcomposeui/.gitignore b/code/aepcomposeui/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/code/aepcomposeui/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/code/aepcomposeui/build.gradle.kts b/code/aepcomposeui/build.gradle.kts
new file mode 100644
index 00000000..4778aa0d
--- /dev/null
+++ b/code/aepcomposeui/build.gradle.kts
@@ -0,0 +1,42 @@
+plugins {
+ id("aep-library")
+}
+
+val mavenCoreVersion: String by project
+val aepComposeUiModuleName: String by project
+val aepComposeUiVersion: String by project
+val aepComposeUiMavenRepoName: String by project
+val aepComposeUiMavenRepoDescription: String by project
+
+aepLibrary {
+ namespace = "com.adobe.marketing.mobile.aepcomposeui"
+
+ moduleName = aepComposeUiModuleName
+ moduleVersion = aepComposeUiVersion
+ enableSpotless = true
+ enableCheckStyle = true
+ enableDokkaDoc = true
+
+ publishing {
+ mavenRepoName = aepComposeUiMavenRepoName
+ mavenRepoDescription = aepComposeUiMavenRepoDescription
+ gitRepoName = "aepsdk-ui-android"
+ addCoreDependency(mavenCoreVersion)
+ }
+}
+
+dependencies {
+ implementation("com.adobe.marketing.mobile:core:$mavenCoreVersion")
+ testImplementation("org.robolectric:robolectric:4.7")
+ testImplementation("io.mockk:mockk:1.13.11")
+ api(project(":aepuitemplates"))
+ implementation(platform(libs.androidx.compose.bom))
+ implementation(libs.androidx.ui)
+ implementation(libs.androidx.ui.graphics)
+ implementation(libs.androidx.ui.tooling.preview)
+ implementation(libs.androidx.material3)
+ implementation(libs.androidx.lifecycle.viewmodel.compose)
+ implementation(libs.androidx.lifecycle.runtime.compose)
+}
+
+
diff --git a/code/aepcomposeui/src/androidTest/java/com/adobe/marketing/mobile/aepcomposeui/ExampleInstrumentedTest.kt b/code/aepcomposeui/src/androidTest/java/com/adobe/marketing/mobile/aepcomposeui/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..dfe5e3a5
--- /dev/null
+++ b/code/aepcomposeui/src/androidTest/java/com/adobe/marketing/mobile/aepcomposeui/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.adobe.marketing.mobile.aepcomposeui
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.adobe.marketing.mobile.aepcomposeui.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/code/aepcomposeui/src/main/AndroidManifest.xml b/code/aepcomposeui/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..a5918e68
--- /dev/null
+++ b/code/aepcomposeui/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/AepUi.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/AepUi.kt
new file mode 100644
index 00000000..4c5c6cc9
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/AepUi.kt
@@ -0,0 +1,42 @@
+package com.adobe.marketing.mobile.aepcomposeui.aepui
+
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
+import com.adobe.marketing.mobile.aepuitemplates.AepUiTemplate
+import com.adobe.marketing.mobile.aepuitemplates.SmallImageTemplate
+import com.adobe.marketing.mobile.aepcomposeui.aepui.state.AepUiState
+import com.adobe.marketing.mobile.aepcomposeui.aepui.state.SmallImageUIState
+
+
+/**
+ * Represents a UI component that can be rendered in the AepUI Engine. Binds a template data with a tracking observer.
+ * This is a sealed interface that can be implemented by different UI components like [SmallImageAepUi], [LargeImageAepUi], etc.
+ * This allows restricting the type of template and observer that can be associated with a UI component, which can be later
+ * used in the app to render the UI component via UIComposeExtensions.
+ * @param T The type of the template associated with the UI component.
+ * @param S The type of the state associated with the UI component.
+ */
+sealed interface AepUI {
+ fun getTemplate(): T
+ fun getState(): S
+ fun updateState(newState: S)
+}
+
+
+class SmallImageAepUi(
+ private val template: SmallImageTemplate,
+ state: SmallImageUIState
+) : AepUI {
+ private val _state = mutableStateOf(state)
+ override fun updateState(newState: SmallImageUIState) {
+ _state.value = newState
+ }
+
+ override fun getTemplate(): SmallImageTemplate {
+ return template
+ }
+
+ override fun getState(): SmallImageUIState {
+ return _state.value
+ }
+}
\ No newline at end of file
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/components/AepList.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/components/AepList.kt
new file mode 100644
index 00000000..8eb29e7c
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/components/AepList.kt
@@ -0,0 +1,139 @@
+package com.adobe.marketing.mobile.aepcomposeui.aepui.components
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.Button
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.viewModelScope
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.adobe.marketing.mobile.aepuitemplates.SmallImageTemplate
+import com.adobe.marketing.mobile.aepcomposeui.aepui.AepUI
+import com.adobe.marketing.mobile.aepcomposeui.aepui.SmallImageAepUi
+import com.adobe.marketing.mobile.aepcomposeui.contentprovider.AepUiContentProvider
+import com.adobe.marketing.mobile.aepcomposeui.observers.AepUiEventObserver
+import com.adobe.marketing.mobile.aepcomposeui.aepui.state.SmallImageUIState
+import com.adobe.marketing.mobile.aepcomposeui.aepui.style.AepUiStyle
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+
+/**
+ * Composable for rendering a list of AEP UI components.
+ * Maintains a list of AEP UI components and renders them using the provided container.
+ */
+@Composable
+fun AepList(
+ contentProvider: AepUiContentProvider,
+ aepUiEventObserver: AepUiEventObserver,
+ aepUiStyle: AepUiStyle,
+ viewModelKey: String,
+ container: @Composable (@Composable () -> Unit) -> Unit = { content ->
+ // Default to a Column if no container is provided
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(8.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ item {
+ content()
+ }
+ }
+ }
+) {
+ val viewModel: AepListViewModel = viewModel(
+ factory = AepComposableViewModelFactory(
+ contentProvider
+ ),
+ key = viewModelKey
+ )
+ val uiList = viewModel.uiList.collectAsStateWithLifecycle()
+
+ container {
+ uiList.value.forEach { ui ->
+ val uiAsComposable = asComposable(ui, aepUiEventObserver, aepUiStyle)
+ uiAsComposable.invoke()
+ }
+
+ Button(onClick = { viewModel.loadMore() }, Modifier.fillMaxWidth()) {
+ Text(text = "Load More")
+ }
+ }
+}
+
+
+private fun asComposable(
+ aepUI: AepUI<*, *>,
+ observer: AepUiEventObserver,
+ aepUiStyle: AepUiStyle
+): @Composable () -> Unit {
+ return when (aepUI) {
+ is SmallImageAepUi -> {
+ {
+ val state = aepUI.getState()
+ if (!state.dismissed) {
+ SmallImageCard(
+ ui = aepUI,
+ style = aepUiStyle.smallImageAepUiStyle,
+ observer = observer
+ )
+ }
+ }
+ }
+
+ else -> throw IllegalArgumentException("Unknown template type")
+ }
+}
+
+
+private class AepListViewModel(
+ private val contentProvider: AepUiContentProvider,
+) : ViewModel() {
+
+ private val _uiList = MutableStateFlow(listOf>())
+ val uiList: StateFlow>> = _uiList
+
+ init {
+ viewModelScope.launch {
+ contentProvider.getContent().collect { templates ->
+ val uiList = templates.map { template ->
+
+ val aepUiState: AepUI<*, *> = when (template) {
+ is SmallImageTemplate -> SmallImageAepUi(
+ template,
+ SmallImageUIState(title = template.title)
+ )
+ else -> throw IllegalArgumentException("Unknown template type")
+ }
+
+ aepUiState
+ }
+ _uiList.value = uiList
+ }
+ }
+ }
+
+ fun loadMore() {
+ viewModelScope.launch {
+ contentProvider.refreshContent()
+ }
+ }
+}
+
+private class AepComposableViewModelFactory(
+ private val contentProvider: AepUiContentProvider
+) : ViewModelProvider.Factory {
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(AepListViewModel::class.java)) {
+ @Suppress("UNCHECKED_CAST")
+ return AepListViewModel(contentProvider) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/components/SmallImageCard.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/components/SmallImageCard.kt
new file mode 100644
index 00000000..fa571043
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/components/SmallImageCard.kt
@@ -0,0 +1,80 @@
+package com.adobe.marketing.mobile.aepcomposeui.aepui.components
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import com.adobe.marketing.mobile.aepcomposeui.aepui.SmallImageAepUi
+import com.adobe.marketing.mobile.aepcomposeui.aepui.style.SmallImageAepUiStyle
+import com.adobe.marketing.mobile.aepcomposeui.interactions.UIEvent
+import com.adobe.marketing.mobile.aepcomposeui.observers.AepUiEventObserver
+
+/**
+ * Composable for rendering a Small Image Card
+ */
+@Composable
+internal fun SmallImageCard(
+ ui: SmallImageAepUi,
+ style: SmallImageAepUiStyle,
+ observer: AepUiEventObserver?,
+) {
+
+ LaunchedEffect(key1 = Unit) {
+ observer?.onEvent(UIEvent.Display(ui))
+ }
+
+ DisposableEffect(key1 = Unit) {
+ onDispose {
+ observer?.onEvent(UIEvent.Dismiss(ui))
+ }
+ }
+
+ Card(
+ shape = RoundedCornerShape(8.dp),
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ .clickable {
+ observer?.onEvent(UIEvent.Click(ui))
+ },
+ elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
+ ) {
+ Row(
+ modifier = Modifier.padding(16.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // TODO - Add image support
+ Spacer(modifier = Modifier.width(16.dp))
+
+ Column(
+ verticalArrangement = Arrangement.Center
+ ) {
+ ui.getState().title?.let {
+ Text(
+ text = it,
+ style = style.getTitleTextStyle(ui.getTemplate()),
+ )
+ }
+ Text(
+ text = ui.getTemplate().description,
+ style = MaterialTheme.typography.bodyMedium
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/state/AepUiState.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/state/AepUiState.kt
new file mode 100644
index 00000000..b6dc6b4a
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/state/AepUiState.kt
@@ -0,0 +1,6 @@
+package com.adobe.marketing.mobile.aepcomposeui.aepui.state
+
+sealed interface AepUiState
+
+data class SmallImageUIState(val title: String?, val dismissed: Boolean = false) : AepUiState
+data class LargeImageUIState(val dismissed: Boolean = false) : AepUiState
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/style/AEPTextExt.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/style/AEPTextExt.kt
new file mode 100644
index 00000000..c503f7ec
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/style/AEPTextExt.kt
@@ -0,0 +1,24 @@
+package com.adobe.marketing.mobile.aepcomposeui.aepui.style
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.style.TextAlign
+
+// only needed when we support server side styling
+fun AEPText.getComposeTextStyle(): TextStyle {
+ var textStyle = TextStyle()
+ if (color != null) {
+ textStyle = textStyle.merge(Color(android.graphics.Color.parseColor(color)))
+ }
+ if (align != null) {
+ textStyle = textStyle.merge(textAlign = when (align) {
+ "center" -> TextAlign.Center
+ "left" -> TextAlign.Left
+ "right" -> TextAlign.Right
+ "start" -> TextAlign.Start
+ "end" -> TextAlign.End
+ else -> TextAlign.Unspecified
+ })
+ }
+ return textStyle
+}
\ No newline at end of file
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/style/AepUiStyle.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/style/AepUiStyle.kt
new file mode 100644
index 00000000..fdc088a3
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/aepui/style/AepUiStyle.kt
@@ -0,0 +1,27 @@
+package com.adobe.marketing.mobile.aepcomposeui.aepui.style
+
+import androidx.compose.material.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import com.adobe.marketing.mobile.aepuitemplates.SmallImageTemplate
+
+// class containing style for all UI types supported by the UI Engine
+class AepUiStyle(
+ val smallImageAepUiStyle: SmallImageAepUiStyle = SmallImageAepUiStyle()
+)
+
+class SmallImageAepUiStyle(
+ private val titleTextStyle: TextStyle? = null
+) {
+ private var defaultTitleColor = Color.Red
+
+ // order of merging is important here
+ // App style > Server style > Default style
+ @Composable
+ fun getTitleTextStyle(template: SmallImageTemplate): TextStyle {
+ return MaterialTheme.typography.h5.copy(defaultTitleColor)
+ .merge(template.title?.getComposeTextStyle())
+ .merge(titleTextStyle)
+ }
+}
\ No newline at end of file
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/contentprovider/AepUiContentProvider.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/contentprovider/AepUiContentProvider.kt
new file mode 100644
index 00000000..6f8f8b0b
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/contentprovider/AepUiContentProvider.kt
@@ -0,0 +1,21 @@
+package com.adobe.marketing.mobile.aepcomposeui.contentprovider
+
+import com.adobe.marketing.mobile.aepuitemplates.AepUiTemplate
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Interface to provide content for the UI and a backing tracker for analytics.
+ * This can be treated as a strategy to provide content and tracking for the UI.
+ * Allows components like extensions which provide content to expose an implementation
+ * for the app to use.
+ */
+interface AepUiContentProvider {
+ /**
+ * Retrieves the content for the UI.
+ * @return The content for the UI as a flow of [AepTemplate]s.
+ */
+ suspend fun getContent(): Flow>
+
+ suspend fun refreshContent()
+}
+
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/interactions/UiEvent.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/interactions/UiEvent.kt
new file mode 100644
index 00000000..d03e85d7
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/interactions/UiEvent.kt
@@ -0,0 +1,12 @@
+package com.adobe.marketing.mobile.aepcomposeui.interactions
+
+import com.adobe.marketing.mobile.aepuitemplates.AepUiTemplate
+import com.adobe.marketing.mobile.aepcomposeui.aepui.AepUI
+import com.adobe.marketing.mobile.aepcomposeui.aepui.state.AepUiState
+
+sealed interface UIEvent {
+ data class Display(val _aepui: AepUI) : UIEvent
+ data class Click(val _aepui: AepUI) : UIEvent
+ data class Dismiss(val _aepui: AepUI) : UIEvent
+ data class Expand(val _aepui: AepUI) : UIEvent
+}
diff --git a/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/observers/AepUiEventObserver.kt b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/observers/AepUiEventObserver.kt
new file mode 100644
index 00000000..6e31e29f
--- /dev/null
+++ b/code/aepcomposeui/src/main/java/com/adobe/marketing/mobile/aepcomposeui/observers/AepUiEventObserver.kt
@@ -0,0 +1,7 @@
+package com.adobe.marketing.mobile.aepcomposeui.observers
+
+import com.adobe.marketing.mobile.aepcomposeui.interactions.UIEvent
+
+interface AepUiEventObserver {
+ fun onEvent(event: UIEvent<*, *>)
+}
\ No newline at end of file
diff --git a/code/aepcomposeui/src/test/java/com/adobe/marketing/mobile/aepcomposeui/ExampleUnitTest.kt b/code/aepcomposeui/src/test/java/com/adobe/marketing/mobile/aepcomposeui/ExampleUnitTest.kt
new file mode 100644
index 00000000..6c65e748
--- /dev/null
+++ b/code/aepcomposeui/src/test/java/com/adobe/marketing/mobile/aepcomposeui/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.adobe.marketing.mobile.aepcomposeui
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/code/aepuitemplates/.gitignore b/code/aepuitemplates/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/code/aepuitemplates/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/code/aepuitemplates/build.gradle.kts b/code/aepuitemplates/build.gradle.kts
new file mode 100644
index 00000000..d429da20
--- /dev/null
+++ b/code/aepuitemplates/build.gradle.kts
@@ -0,0 +1,32 @@
+plugins {
+ id("aep-library")
+}
+
+val mavenCoreVersion: String by project
+val aepUiTemplatesModuleName: String by project
+val aepUiTemplatesVersion: String by project
+val aepUiTemplatesMavenRepoName: String by project
+val aepUiTemplatesMavenRepoDescription: String by project
+
+aepLibrary {
+ namespace = "com.adobe.marketing.mobile.aepcomposeui"
+
+ moduleName = aepUiTemplatesModuleName
+ moduleVersion = aepUiTemplatesVersion
+ enableSpotless = true
+ enableCheckStyle = true
+ enableDokkaDoc = true
+
+ publishing {
+ mavenRepoName = aepUiTemplatesMavenRepoName
+ mavenRepoDescription = aepUiTemplatesMavenRepoDescription
+ gitRepoName = "aepsdk-ui-android"
+ addCoreDependency(mavenCoreVersion)
+ }
+}
+
+dependencies {
+ implementation("com.adobe.marketing.mobile:core:$mavenCoreVersion")
+ testImplementation("org.robolectric:robolectric:4.7")
+ testImplementation("io.mockk:mockk:1.13.11")
+}
\ No newline at end of file
diff --git a/code/aepuitemplates/src/androidTest/java/com/adobe/marketing/mobile/aepuitemplates/ExampleInstrumentedTest.kt b/code/aepuitemplates/src/androidTest/java/com/adobe/marketing/mobile/aepuitemplates/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..5ade8ab0
--- /dev/null
+++ b/code/aepuitemplates/src/androidTest/java/com/adobe/marketing/mobile/aepuitemplates/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.adobe.marketing.mobile.aepuitemplates
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.adobe.marketing.mobile.aepuitemplates.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/code/aepuitemplates/src/main/AndroidManifest.xml b/code/aepuitemplates/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..a5918e68
--- /dev/null
+++ b/code/aepuitemplates/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/AepUiTemplate.kt b/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/AepUiTemplate.kt
new file mode 100644
index 00000000..1a84e2fd
--- /dev/null
+++ b/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/AepUiTemplate.kt
@@ -0,0 +1,5 @@
+package com.adobe.marketing.mobile.aepuitemplates
+
+interface AepUiTemplate {
+ fun getType(): String
+}
\ No newline at end of file
diff --git a/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/SmallImageTemplate.kt b/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/SmallImageTemplate.kt
new file mode 100644
index 00000000..81bfceb9
--- /dev/null
+++ b/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/SmallImageTemplate.kt
@@ -0,0 +1,10 @@
+package com.adobe.marketing.mobile.aepuitemplates
+
+import com.adobe.marketing.mobile.aepuitemplates.utils.AepUiTemplateType
+
+class SmallImageTemplate() : AepUiTemplate {
+ val imageUrl: String = ""
+ val title: String = ""
+ val description: String = ""
+ override fun getType() = AepUiTemplateType.SMALL_IMAGE.typeName
+}
diff --git a/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/utils/AepUiTemplateType.kt b/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/utils/AepUiTemplateType.kt
new file mode 100644
index 00000000..4633a826
--- /dev/null
+++ b/code/aepuitemplates/src/main/java/com/adobe/marketing/mobile/aepuitemplates/utils/AepUiTemplateType.kt
@@ -0,0 +1,8 @@
+package com.adobe.marketing.mobile.aepuitemplates.utils
+
+enum class AepUiTemplateType(val typeName: String) {
+
+ SMALL_IMAGE("SmallImage"),
+ LARGE_IMAGE("LargeImage")
+
+}
\ No newline at end of file
diff --git a/code/aepuitemplates/src/test/java/com/adobe/marketing/mobile/aepuitemplates/ExampleUnitTest.kt b/code/aepuitemplates/src/test/java/com/adobe/marketing/mobile/aepuitemplates/ExampleUnitTest.kt
new file mode 100644
index 00000000..d0069d2a
--- /dev/null
+++ b/code/aepuitemplates/src/test/java/com/adobe/marketing/mobile/aepuitemplates/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.adobe.marketing.mobile.aepuitemplates
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/code/gradle.properties b/code/gradle.properties
index f87e7936..770464ee 100644
--- a/code/gradle.properties
+++ b/code/gradle.properties
@@ -22,6 +22,16 @@ notificationbuilderVersion=3.0.0
notificationbuilderMavenRepoName=AdobeMobileNotificationBuilderSdk
notificationbuilderMavenRepoDescription=Android Notification Builder library for Adobe Mobile Marketing
+aepComposeUiModuleName = aepcomposeui
+aepComposeUiVersion=1.0.1
+aepComposeUiMavenRepoName = AdobeMobileAEPComposeUiSdk
+aepComposeUiMavenRepoDescription = Android AEP Compose UI library for Adobe Mobile Marketing
+
+aepUiTemplatesModuleName = aepuitemplates
+aepUiTemplatesVersion=1.0.1
+aepUiTemplatesMavenRepoName = AdobeMobileAEPUiTemplates
+aepUiTemplatesMavenRepoDescription = Android AEP UI templates library for Adobe Mobile Marketing
+
mavenCoreVersion=3.0.0
diff --git a/code/gradle/libs.versions.toml b/code/gradle/libs.versions.toml
new file mode 100644
index 00000000..84d5d098
--- /dev/null
+++ b/code/gradle/libs.versions.toml
@@ -0,0 +1,40 @@
+[versions]
+agp = "8.5.1"
+kotlin = "1.9.0"
+coreKtx = "1.13.1"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+espressoCore = "3.6.1"
+lifecycleRuntimeKtx = "2.8.4"
+activityCompose = "1.9.1"
+composeBom = "2024.04.01"
+appcompat = "1.7.0"
+lifecycleViewModelCompose = "2.8.1"
+lifecycleRuntimeCompose = "2.8.1"
+material = "1.12.0"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
+androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" }
+androidx-lifecycle-viewmodel-compose = {group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleViewModelCompose"}
+androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
+androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
+androidx-ui = { group = "androidx.compose.ui", name = "ui" }
+androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
+androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
+androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
+androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
+androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
+androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
+androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+android-library = { id = "com.android.library", version.ref = "agp" }
+
diff --git a/code/settings.gradle.kts b/code/settings.gradle.kts
index 5c9ab072..f4e67753 100755
--- a/code/settings.gradle.kts
+++ b/code/settings.gradle.kts
@@ -30,7 +30,9 @@ dependencyResolutionManagement {
}
rootProject.name = "aepsdk-ui-android"
-include (
- ":notificationbuilder",
- ":testapp"
+include(
+ ":notificationbuilder",
+ ":testapp",
+ ":aepcomposeui",
+ ":aepuitemplates"
)
\ No newline at end of file