diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts
new file mode 100644
index 0000000..9523466
--- /dev/null
+++ b/core/common/build.gradle.kts
@@ -0,0 +1,3 @@
+plugins {
+ alias(libs.plugins.mcl.kotlin.library)
+}
diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts
new file mode 100644
index 0000000..341bdcb
--- /dev/null
+++ b/core/data/build.gradle.kts
@@ -0,0 +1,16 @@
+plugins {
+ alias(libs.plugins.mcl.android.library)
+ alias(libs.plugins.mcl.android.hilt)
+}
+
+android {
+ namespace = "com.mingyuan.android_client.core.data"
+}
+
+dependencies {
+ implementation(project(":core:domain"))
+ implementation(project(":core:model"))
+ implementation(project(":core:network"))
+ implementation(project(":core:database"))
+ implementation(project(":core:datastore"))
+}
diff --git a/core/data/src/main/AndroidManifest.xml b/core/data/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8072ee0
--- /dev/null
+++ b/core/data/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts
new file mode 100644
index 0000000..eda0ca7
--- /dev/null
+++ b/core/database/build.gradle.kts
@@ -0,0 +1,12 @@
+plugins {
+ alias(libs.plugins.mcl.android.library)
+ alias(libs.plugins.mcl.android.room)
+}
+
+android {
+ namespace = "com.mingyuan.android_client.core.database"
+}
+
+dependencies {
+ implementation(project(":core:model"))
+}
diff --git a/core/database/src/main/AndroidManifest.xml b/core/database/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8072ee0
--- /dev/null
+++ b/core/database/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/core/datastore/build.gradle.kts b/core/datastore/build.gradle.kts
new file mode 100644
index 0000000..a004782
--- /dev/null
+++ b/core/datastore/build.gradle.kts
@@ -0,0 +1,12 @@
+plugins {
+ alias(libs.plugins.mcl.android.library)
+}
+
+android {
+ namespace = "com.mingyuan.android_client.core.datastore"
+}
+
+dependencies {
+ implementation(project(":core:model"))
+ implementation(libs.androidx.datastore.preferences)
+}
diff --git a/core/datastore/src/main/AndroidManifest.xml b/core/datastore/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8072ee0
--- /dev/null
+++ b/core/datastore/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/core/designsystem/build.gradle.kts b/core/designsystem/build.gradle.kts
new file mode 100644
index 0000000..ad7a985
--- /dev/null
+++ b/core/designsystem/build.gradle.kts
@@ -0,0 +1,7 @@
+plugins {
+ alias(libs.plugins.mcl.android.library.compose)
+}
+
+android {
+ namespace = "com.mingyuan.android_client.core.designsystem"
+}
diff --git a/core/designsystem/src/main/AndroidManifest.xml b/core/designsystem/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8072ee0
--- /dev/null
+++ b/core/designsystem/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Color.kt b/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Color.kt
new file mode 100644
index 0000000..97fe81e
--- /dev/null
+++ b/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.mingyuan.android_client.core.designsystem.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val Purple40 = Color(0xFF6650A4)
+val PurpleGrey40 = Color(0xFF625B71)
+val Pink40 = Color(0xFF7D5260)
diff --git a/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Theme.kt b/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Theme.kt
new file mode 100644
index 0000000..8851eb8
--- /dev/null
+++ b/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Theme.kt
@@ -0,0 +1,50 @@
+package com.mingyuan.android_client.core.designsystem.theme
+
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+
+private val DarkColorScheme = darkColorScheme(
+ primary = Purple80,
+ secondary = PurpleGrey80,
+ tertiary = Pink80,
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = Purple40,
+ secondary = PurpleGrey40,
+ tertiary = Pink40,
+)
+
+/**
+ * The app's single Material theme. All UI entry points wrap their content in [MingyuanTheme].
+ */
+@Composable
+fun MingyuanTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+.
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit,
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content,
+ )
+}
diff --git a/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Type.kt b/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Type.kt
new file mode 100644
index 0000000..6715c0f
--- /dev/null
+++ b/core/designsystem/src/main/kotlin/com/mingyuan/android_client/core/designsystem/theme/Type.kt
@@ -0,0 +1,6 @@
+package com.mingyuan.android_client.core.designsystem.theme
+
+import androidx.compose.material3.Typography
+
+// Uses Material 3 defaults; customize typography here as the design system evolves.
+val Typography = Typography()
diff --git a/core/domain/DESIGN_NOTES.md b/core/domain/DESIGN_NOTES.md
new file mode 100644
index 0000000..7337ef1
--- /dev/null
+++ b/core/domain/DESIGN_NOTES.md
@@ -0,0 +1,22 @@
+# DESIGN_NOTES — core:domain
+
+## 为什么纯 Kotlin
+
+`core:domain`(以及 `core:model`、`core:common`)用 `mcl.kotlin.library`(`org.jetbrains.kotlin.jvm`),**不依赖 Android**。这样:
+
+- 业务规则(UseCase)不 import `android.*`,框架解耦,天然可移植。
+- 单元测试直接跑在 JVM 上(`./gradlew test`),快且稳定,无需 Robolectric/设备。
+
+## 如何塑造 UseCase / Repository
+
+- **UseCase**:单一动作的接口,`suspend operator fun invoke(input): Output`(见 `UseCase.kt`)。一个类一个动作,符合单一职责。
+- **Repository 接口**:定义在 `core:domain`(接口),实现在 `core:data`(`XxxRepositoryImpl`)。调用方只依赖接口,不依赖实现,便于用 fake 替换做测试。
+
+## 依赖方向
+
+`core:domain` 只依赖 `core:model` 与 `core:common`(都是纯 Kotlin)。**不要**让 domain 依赖 Android、网络、数据库——那是数据层的职责。
+
+## 约定
+
+- 需要协程时用 `kotlinx-coroutines-core`(`Flow` 等);不要在 domain 里用 Android 的 `LiveData`。
+- 状态/结果优先用 sealed class 表达。
diff --git a/core/domain/build.gradle.kts b/core/domain/build.gradle.kts
new file mode 100644
index 0000000..4b59c5d
--- /dev/null
+++ b/core/domain/build.gradle.kts
@@ -0,0 +1,9 @@
+plugins {
+ alias(libs.plugins.mcl.kotlin.library)
+}
+
+dependencies {
+ implementation(libs.kotlinx.coroutines.core)
+ testImplementation(libs.kotlinx.coroutines.test)
+ testImplementation(libs.truth)
+}
diff --git a/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/UseCase.kt b/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/UseCase.kt
new file mode 100644
index 0000000..27b55f2
--- /dev/null
+++ b/core/domain/src/main/kotlin/com/mingyuan/android_client/core/domain/UseCase.kt
@@ -0,0 +1,11 @@
+package com.mingyuan.android_client.core.domain
+
+/**
+ * Base contract for a single-action use case.
+ *
+ * Keeping use cases as plain interfaces with a `suspend operator invoke` keeps domain logic
+ * framework-agnostic and trivially testable on the JVM (see [com.mingyuan.android_client.core.domain.UseCaseTest]).
+ */
+interface UseCase {
+ suspend operator fun invoke(input: Input): Output
+}
diff --git a/core/domain/src/test/kotlin/com/mingyuan/android_client/core/domain/UseCaseTest.kt b/core/domain/src/test/kotlin/com/mingyuan/android_client/core/domain/UseCaseTest.kt
new file mode 100644
index 0000000..888451b
--- /dev/null
+++ b/core/domain/src/test/kotlin/com/mingyuan/android_client/core/domain/UseCaseTest.kt
@@ -0,0 +1,17 @@
+package com.mingyuan.android_client.core.domain
+
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+class UseCaseTest {
+
+ @Test
+ fun `invoke delegates to the implementation`() = runTest {
+ val double = object : UseCase {
+ override suspend fun invoke(input: Int): Int = input * 2
+ }
+
+ assertThat(double(21)).isEqualTo(42)
+ }
+}
diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts
new file mode 100644
index 0000000..9523466
--- /dev/null
+++ b/core/model/build.gradle.kts
@@ -0,0 +1,3 @@
+plugins {
+ alias(libs.plugins.mcl.kotlin.library)
+}
diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts
new file mode 100644
index 0000000..e38ceda
--- /dev/null
+++ b/core/network/build.gradle.kts
@@ -0,0 +1,18 @@
+plugins {
+ alias(libs.plugins.mcl.android.library)
+ alias(libs.plugins.kotlin.serialization)
+}
+
+android {
+ namespace = "com.mingyuan.android_client.core.network"
+}
+
+dependencies {
+ implementation(project(":core:common"))
+ implementation(project(":core:model"))
+
+ implementation(libs.kotlinx.serialization.json)
+ implementation(libs.retrofit.core)
+ implementation(libs.retrofit.kotlinx.serialization)
+ implementation(libs.okhttp.logging)
+}
diff --git a/core/network/src/main/AndroidManifest.xml b/core/network/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8072ee0
--- /dev/null
+++ b/core/network/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts
new file mode 100644
index 0000000..16a2769
--- /dev/null
+++ b/core/ui/build.gradle.kts
@@ -0,0 +1,13 @@
+plugins {
+ alias(libs.plugins.mcl.android.library.compose)
+ alias(libs.plugins.mcl.android.hilt)
+}
+
+android {
+ namespace = "com.mingyuan.android_client.core.ui"
+}
+
+dependencies {
+ implementation(project(":core:designsystem"))
+ implementation(project(":core:model"))
+}
diff --git a/core/ui/src/main/AndroidManifest.xml b/core/ui/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8072ee0
--- /dev/null
+++ b/core/ui/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+