diff --git a/README.md b/README.md
index 29e3098..9b0fa8a 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,54 @@
-# starter-for-android
-Appwrite's starter kit for Android 🤖
\ No newline at end of file
+# Android Starter Kit with Appwrite
+
+Kickstart your Android development with this ready-to-use starter project integrated
+with [Appwrite](https://appwrite.io).
+
+This guide will help you quickly set up, customize, and build your Android app using **Jetpack
+Compose**.
+
+---
+
+## 🚀 Getting Started
+
+### Clone the Project
+
+Clone this repository to your local machine using Git or directly from `Android Studio`:
+
+```bash
+git clone https://github.com/appwrite/starter-for-android
+```
+
+Alternatively, open the repository URL in `Android Studio` to clone it directly.
+
+---
+
+## 🛠️ Development Guide
+
+1. **Configure Appwrite**  
+   Navigate to `constants/AppwriteConfig.kt` and update the values to match your Appwrite project
+   credentials.
+
+2. **Customize as Needed**  
+   Modify the starter kit to suit your app's requirements. Adjust UI, features, or backend
+   integrations as per your needs.
+
+3. **Run the App**  
+   Select a target device (emulator or connected physical Android device) in `Android Studio`, and
+   click **Run** to start the app.
+
+---
+
+## 📦 Building for Production
+
+To create a production build of your app:
+
+1. Open **Build variants** > **app** in the menu bar.
+2. Choose **release**
+3. Build and deploy your app in release mode.
+
+---
+
+## 💡 Additional Notes
+
+- This starter project is designed to streamline your Android development with Appwrite.
+- Refer to the [Appwrite Documentation](https://appwrite.io/docs) for detailed integration guidance.
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..26a084f
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1,10 @@
+*.iml
+.gradle
+.idea
+build
+gradle
+local.properties
+.externalNativeBuild
+
+/captures
+.DS_Store
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..3b91603
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,68 @@
+plugins {
+    alias(libs.plugins.android.application)
+    alias(libs.plugins.kotlin.android)
+    alias(libs.plugins.kotlin.compose)
+}
+
+android {
+    namespace = "io.appwrite.starterkit"
+    compileSdk = 35
+
+    defaultConfig {
+        minSdk = 21
+        targetSdk = 35
+        versionCode = 1
+        versionName = "1.0"
+        applicationId = "io.appwrite.starterkit"
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(
+                getDefaultProguardFile("proguard-android-optimize.txt"),
+                "proguard-rules.pro"
+            )
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_11
+        targetCompatibility = JavaVersion.VERSION_11
+    }
+
+    kotlinOptions {
+        jvmTarget = "11"
+    }
+
+    buildFeatures {
+        compose = true
+    }
+}
+
+dependencies {
+    // appwrite
+    implementation(libs.appwrite)
+
+    // splashscreen
+    implementation(libs.androidx.core.splashscreen)
+
+    // core, compose and runtime
+    implementation(libs.androidx.core.ktx)
+    implementation(libs.androidx.activity.compose)
+    implementation(libs.androidx.lifecycle.runtime.ktx)
+    implementation(libs.androidx.lifecycle.viewmodel.compose)
+
+    // ui, preview & material
+    implementation(libs.androidx.ui)
+    implementation(libs.androidx.material3)
+    implementation(libs.androidx.ui.graphics)
+    implementation(libs.androidx.ui.tooling.preview)
+
+    // compose platform
+    implementation(platform(libs.androidx.compose.bom))
+
+    // debug libraries
+    debugImplementation(libs.androidx.ui.tooling)
+    debugImplementation(libs.androidx.ui.test.manifest)
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..193fe94
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="AppwriteStarterKit"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AppwriteStarterKit.SplashTheme"
+        tools:targetApi="31">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true"
+            android:windowSoftInputMode="adjustResize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/MainActivity.kt b/app/src/main/java/io/appwrite/starterkit/MainActivity.kt
new file mode 100644
index 0000000..d13eade
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/MainActivity.kt
@@ -0,0 +1,138 @@
+package io.appwrite.starterkit
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.annotation.RestrictTo
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBars
+import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.core.view.WindowCompat
+import androidx.lifecycle.viewmodel.compose.viewModel
+import io.appwrite.starterkit.data.models.Status
+import io.appwrite.starterkit.data.models.mockProjectInfo
+import io.appwrite.starterkit.extensions.copy
+import io.appwrite.starterkit.extensions.edgeToEdgeWithStyle
+import io.appwrite.starterkit.ui.components.CollapsibleBottomSheet
+import io.appwrite.starterkit.ui.components.ConnectionStatusView
+import io.appwrite.starterkit.ui.components.GettingStartedCards
+import io.appwrite.starterkit.ui.components.TopPlatformView
+import io.appwrite.starterkit.ui.components.addCheckeredBackground
+import io.appwrite.starterkit.ui.theme.AppwriteStarterKitTheme
+import io.appwrite.starterkit.viewmodels.AppwriteViewModel
+import kotlinx.coroutines.delay
+
+/**
+ * MainActivity serves as the entry point for the application.
+ * It configures the system's edge-to-edge settings, splash screen, and initializes the composable layout.
+ */
+class MainActivity : ComponentActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        installSplashScreen()
+        super.onCreate(savedInstanceState)
+
+        edgeToEdgeWithStyle()
+        WindowCompat.setDecorFitsSystemWindows(window, false)
+
+        setContent { AppwriteStarter() }
+    }
+}
+
+/**
+ * AppwriteStarter is the root composable function that sets up the main UI layout.
+ * It manages the logs, status, and project information using the provided [AppwriteViewModel].
+ */
+@Composable
+fun AppwriteStarter(
+    viewModel: AppwriteViewModel = viewModel(),
+) {
+    val logs by viewModel.logs.collectAsState()
+    val status by viewModel.status.collectAsState()
+
+    // data doesn't change, so no `remember`.
+    val projectInfo = viewModel.getProjectInfo()
+
+    AppwriteStarterKitTheme {
+        Scaffold(bottomBar = {
+            CollapsibleBottomSheet(
+                logs = logs,
+                projectInfo = projectInfo
+            )
+        }) { innerPadding ->
+            Column(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .addCheckeredBackground()
+                    .padding(innerPadding.copy(top = 16.dp, bottom = 0.dp))
+                    .windowInsetsPadding(WindowInsets.systemBars)
+                    .verticalScroll(rememberScrollState()),
+                verticalArrangement = Arrangement.spacedBy(16.dp)
+            ) {
+                TopPlatformView(
+                    status = status
+                )
+
+                ConnectionStatusView(status) {
+                    viewModel.ping()
+                }
+
+                GettingStartedCards()
+            }
+        }
+    }
+}
+
+@Preview
+@Composable
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun AppwriteStarterPreview() {
+    val status = remember { mutableStateOf<Status>(Status.Idle) }
+
+    AppwriteStarterKitTheme {
+        Scaffold(bottomBar = {
+            CollapsibleBottomSheet(
+                logs = emptyList(),
+                projectInfo = mockProjectInfo
+            )
+        }) { innerPadding ->
+            Column(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .addCheckeredBackground()
+                    .padding(innerPadding.copy(top = 16.dp, bottom = 0.dp))
+                    .windowInsetsPadding(WindowInsets.systemBars)
+                    .verticalScroll(rememberScrollState()),
+                verticalArrangement = Arrangement.spacedBy(16.dp)
+            ) {
+                TopPlatformView(
+                    status = status.value
+                )
+
+                ConnectionStatusView(status.value) {
+                    // simulate a success ping
+                    status.value = Status.Loading
+                    delay(1000)
+                    status.value = Status.Success
+                }
+
+                GettingStartedCards()
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/constants/AppwriteConfig.kt b/app/src/main/java/io/appwrite/starterkit/constants/AppwriteConfig.kt
new file mode 100644
index 0000000..313927b
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/constants/AppwriteConfig.kt
@@ -0,0 +1,29 @@
+package io.appwrite.starterkit.constants
+
+/**
+ * Appwrite integration constants.
+ *
+ * This object holds values related to the Appwrite server setup,
+ * including version, project details, and API endpoint.
+ */
+object AppwriteConfig {
+    /**
+     * Appwrite Server version.
+     */
+    const val APPWRITE_VERSION = "1.6.0"
+
+    /**
+     * Appwrite project id.
+     */
+    const val APPWRITE_PROJECT_ID = "my-project-id"
+
+    /**
+     * Appwrite project name.
+     */
+    const val APPWRITE_PROJECT_NAME = "My project"
+
+    /**
+     * Appwrite server endpoint url.
+     */
+    const val APPWRITE_PUBLIC_ENDPOINT = "https://cloud.appwrite.io/v1"
+}
diff --git a/app/src/main/java/io/appwrite/starterkit/data/models/Log.kt b/app/src/main/java/io/appwrite/starterkit/data/models/Log.kt
new file mode 100644
index 0000000..022fc55
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/data/models/Log.kt
@@ -0,0 +1,12 @@
+package io.appwrite.starterkit.data.models
+
+/**
+ * A data model for holding log entries.
+ */
+data class Log(
+    val date: String,
+    val status: String,
+    val method: String,
+    val path: String,
+    val response: String,
+)
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/data/models/ProjectInfo.kt b/app/src/main/java/io/appwrite/starterkit/data/models/ProjectInfo.kt
new file mode 100644
index 0000000..327206e
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/data/models/ProjectInfo.kt
@@ -0,0 +1,24 @@
+package io.appwrite.starterkit.data.models
+
+import androidx.annotation.RestrictTo
+
+/**
+ * A data model for holding appwrite project information.
+ */
+data class ProjectInfo(
+    val endpoint: String,
+    val projectId: String,
+    val projectName: String,
+    val version: String,
+)
+
+/**
+ * A mock `ProjectInfo` model, just for **previews**.
+ */
+@RestrictTo(RestrictTo.Scope.TESTS)
+internal val mockProjectInfo = ProjectInfo(
+    endpoint = "https://mock.api/v1",
+    projectId = "sample-project-id",
+    projectName = "AppwriteStarter",
+    version = "1.6.0",
+)
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/data/models/Status.kt b/app/src/main/java/io/appwrite/starterkit/data/models/Status.kt
new file mode 100644
index 0000000..e4e72e6
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/data/models/Status.kt
@@ -0,0 +1,27 @@
+package io.appwrite.starterkit.data.models
+
+/**
+ * Represents the various states of a process or operation.
+ * This sealed class ensures that only predefined statuses are used.
+ */
+sealed class Status {
+    /**
+     * Represents the idle state.
+     */
+    data object Idle : Status()
+
+    /**
+     * Represents a loading state.
+     */
+    data object Loading : Status()
+
+    /**
+     * Represents a successful operation.
+     */
+    data object Success : Status()
+
+    /**
+     * Represents an error state.
+     */
+    data object Error : Status()
+}
diff --git a/app/src/main/java/io/appwrite/starterkit/data/repository/AppwriteRepository.kt b/app/src/main/java/io/appwrite/starterkit/data/repository/AppwriteRepository.kt
new file mode 100644
index 0000000..cff35dd
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/data/repository/AppwriteRepository.kt
@@ -0,0 +1,88 @@
+package io.appwrite.starterkit.data.repository
+
+import android.content.Context
+import io.appwrite.Client
+import io.appwrite.exceptions.AppwriteException
+import io.appwrite.services.Account
+import io.appwrite.services.Databases
+import io.appwrite.starterkit.constants.AppwriteConfig
+import io.appwrite.starterkit.data.models.Log
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+
+/**
+ * [AppwriteRepository] is responsible for handling network interactions with the Appwrite server.
+ *
+ * It provides a helper method to ping the server.
+ *
+ * **NOTE: This repository will be removed once the Appwrite SDK includes a native `client.ping()` method.**\
+ * TODO: remove this repository once sdk has `client.ping()`
+ */
+class AppwriteRepository private constructor(context: Context) {
+
+    // Appwrite Client and Services
+    private val client = Client(context.applicationContext)
+        .setProject(AppwriteConfig.APPWRITE_PROJECT_ID)
+        .setEndpoint(AppwriteConfig.APPWRITE_PUBLIC_ENDPOINT)
+
+    private val account: Account = Account(client)
+    private val databases: Databases = Databases(client)
+
+    /**
+     * Pings the Appwrite server.
+     * Captures the response or any errors encountered during the request.
+     *
+     * @return [Log] A log object containing details of the request and response.
+     */
+    suspend fun fetchPingLog(): Log {
+        val date = getCurrentDate()
+
+        return try {
+            val response = withContext(Dispatchers.IO) { client.ping() }
+
+            Log(
+                date = date,
+                status = "200",
+                method = "GET",
+                path = "/ping",
+                response = response
+            )
+        } catch (exception: AppwriteException) {
+            Log(
+                date = date,
+                method = "GET",
+                path = "/ping",
+                status = "${exception.code}",
+                response = "${exception.message}"
+            )
+        }
+    }
+
+    /**
+     * Retrieves the current date in the format "MMM dd, HH:mm".
+     *
+     * @return [String] A formatted date.
+     */
+    private fun getCurrentDate(): String {
+        val formatter = SimpleDateFormat("MMM dd, HH:mm", Locale.getDefault())
+        return formatter.format(Date())
+    }
+
+    companion object {
+        @Volatile
+        private var INSTANCE: AppwriteRepository? = null
+
+        /**
+         * Singleton factory method to get the instance of AppwriteRepository.
+         * Ensures thread safety
+         */
+        fun getInstance(context: Context): AppwriteRepository {
+            return INSTANCE ?: synchronized(this) {
+                INSTANCE ?: AppwriteRepository(context).also { INSTANCE = it }
+            }
+        }
+    }
+}
diff --git a/app/src/main/java/io/appwrite/starterkit/extensions/EdgeToEdge.kt b/app/src/main/java/io/appwrite/starterkit/extensions/EdgeToEdge.kt
new file mode 100644
index 0000000..4c8276d
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/extensions/EdgeToEdge.kt
@@ -0,0 +1,20 @@
+package io.appwrite.starterkit.extensions
+
+import androidx.activity.ComponentActivity
+import androidx.activity.SystemBarStyle
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+
+/**
+ * Enables edge-to-edge display with a custom status bar style .
+ * This sets the status bar to a light style with a semi-transparent black scrim.
+ */
+fun ComponentActivity.edgeToEdgeWithStyle() {
+    enableEdgeToEdge(
+        statusBarStyle = SystemBarStyle.light(
+            scrim = Color.Black.copy(alpha = 0.15f).toArgb(),
+            darkScrim = Color.Black.copy(alpha = 0.15f).toArgb()
+        )
+    )
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/extensions/PaddingValues.kt b/app/src/main/java/io/appwrite/starterkit/extensions/PaddingValues.kt
new file mode 100644
index 0000000..08e2db9
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/extensions/PaddingValues.kt
@@ -0,0 +1,37 @@
+package io.appwrite.starterkit.extensions
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.calculateEndPadding
+import androidx.compose.foundation.layout.calculateStartPadding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.unit.Dp
+
+/**
+ * A utility function to create a copy of the current [PaddingValues] with the option to override
+ * specific padding values for start, top, end, or bottom.
+ *
+ * This is useful to modify only certain padding values while retaining the rest.
+ *
+ * @param start The new start padding value, or `null` to retain the existing start padding.
+ * @param top The new top padding value, or `null` to retain the existing top padding.
+ * @param end The new end padding value, or `null` to retain the existing end padding.
+ * @param bottom The new bottom padding value, or `null` to retain the existing bottom padding.
+ *
+ * @return [PaddingValues] A new instance with the specified padding overrides applied.
+ */
+@Composable
+fun PaddingValues.copy(
+    start: Dp? = null,
+    top: Dp? = null,
+    end: Dp? = null,
+    bottom: Dp? = null,
+): PaddingValues {
+    val layoutDirection = LocalLayoutDirection.current
+    return PaddingValues(
+        top = top ?: this.calculateTopPadding(),
+        bottom = bottom ?: this.calculateBottomPadding(),
+        end = end ?: this.calculateEndPadding(layoutDirection),
+        start = start ?: this.calculateStartPadding(layoutDirection),
+    )
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/components/CheckeredBackground.kt b/app/src/main/java/io/appwrite/starterkit/ui/components/CheckeredBackground.kt
new file mode 100644
index 0000000..2f86f2e
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/components/CheckeredBackground.kt
@@ -0,0 +1,110 @@
+package io.appwrite.starterkit.ui.components
+
+import androidx.annotation.RestrictTo
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.drawscope.Fill
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import kotlin.math.min
+
+// Background color for gradients, blur, etc.
+val checkeredBackgroundColor = Color(0xFFFAFAFB)
+
+// Max height factor for  background.
+const val heightConstraintFactor = 0.5f
+
+/**
+ * A custom view modifier that adds a checkered background pattern with a gradient effect
+ * and a radial gradient overlay. The checkered pattern consists of gray vertical and horizontal lines
+ * drawn over the view's background. The modifier also includes a mask and a radial gradient
+ * to create a layered visual effect.
+ */
+fun Modifier.addCheckeredBackground() = this.drawBehind { drawCheckeredBackground() }
+
+/**
+ * Draws a checkered background pattern on the canvas with vertical and horizontal grid lines.
+ * Also applies linear and radial gradient overlays for additional visual effects.
+ */
+fun DrawScope.drawCheckeredBackground() {
+    val lineThickness = 0.75f
+    val gridSize = min(size.width * 0.1f, 64.dp.toPx())
+    val heightConstraint = size.height * heightConstraintFactor
+
+    // Draw vertical lines
+    for (x in generateSequence(0f) { it + gridSize }.takeWhile { it <= size.width }) {
+        drawRect(
+            color = Color.Gray.copy(alpha = 0.3f),
+            topLeft = Offset(x, 0f),
+            size = Size(lineThickness, heightConstraint),
+            style = Fill
+        )
+    }
+
+    // Draw horizontal lines
+    for (y in generateSequence(0f) { it + gridSize }.takeWhile { it <= heightConstraint }) {
+        drawRect(
+            color = Color.Gray.copy(alpha = 0.3f),
+            topLeft = Offset(0f, y),
+            size = Size(size.width, lineThickness),
+            style = Fill
+        )
+    }
+
+    drawRadialGradientOverlay()
+
+    drawLinearGradientOverlay()
+}
+
+/**
+ * Draws a vertical gradient overlay over the canvas to enhance the checkered background's appearance.
+ */
+fun DrawScope.drawLinearGradientOverlay() {
+    val heightConstraint = size.height * heightConstraintFactor
+    drawRect(
+        brush = Brush.verticalGradient(
+            colors = listOf(
+                checkeredBackgroundColor,
+                checkeredBackgroundColor.copy(alpha = 0.3f),
+                checkeredBackgroundColor.copy(alpha = 0.5f),
+                checkeredBackgroundColor.copy(alpha = 0.7f),
+                checkeredBackgroundColor,
+            ), endY = heightConstraint
+        ),
+    )
+}
+
+/**
+ * Draws a radial gradient overlay over the canvas to create a smooth blend effect from the center outward.
+ */
+fun DrawScope.drawRadialGradientOverlay() {
+    drawRect(
+        brush = Brush.radialGradient(
+            colors = listOf(
+                checkeredBackgroundColor.copy(alpha = 0f),
+                checkeredBackgroundColor.copy(alpha = 0.4f),
+                checkeredBackgroundColor.copy(alpha = 0.2f),
+                Color.Transparent
+            ), center = center, radius = maxOf(size.width, size.height) * 2
+        ),
+    )
+}
+
+@Composable
+@Preview(showBackground = true)
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun CheckeredBackgroundPreview() {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .addCheckeredBackground()
+    )
+}
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/components/CollapsibleBottomSheet.kt b/app/src/main/java/io/appwrite/starterkit/ui/components/CollapsibleBottomSheet.kt
new file mode 100644
index 0000000..f68674c
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/components/CollapsibleBottomSheet.kt
@@ -0,0 +1,588 @@
+package io.appwrite.starterkit.ui.components
+
+import androidx.annotation.RestrictTo
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.animateContentSize
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkVertically
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.horizontalScroll
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.KeyboardArrowDown
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.ripple
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.appwrite.starterkit.data.models.Log
+import io.appwrite.starterkit.data.models.ProjectInfo
+import io.appwrite.starterkit.data.models.mockProjectInfo
+
+/**
+ * Column widths for the custom response table.
+ */
+val columns = listOf(
+    "Date" to 150f, "Status" to 80f,
+    "Method" to 100f, "Path" to 125f, "Response" to 125f
+)
+
+/**
+ * A view that displays a collapsible bottom sheet showing logs. It includes a header with a
+ * title and a count of logs, and the content of the bottom sheet can be expanded or collapsed
+ * based on user interaction.
+ *
+ * @param title The title displayed at the top of the bottom sheet.
+ * @param logs The list of logs to be displayed in the bottom sheet.
+ * @param projectInfo Contains project details like endpoint, project ID, project name, and version.
+ */
+@Composable
+fun CollapsibleBottomSheet(
+    title: String = "Logs",
+    logs: List<Log> = emptyList(),
+    projectInfo: ProjectInfo,
+) {
+    val isExpanded = remember { mutableStateOf(false) }
+    val rotateAnimation = animateFloatAsState(
+        label = "",
+        animationSpec = tween(durationMillis = 250),
+        targetValue = if (isExpanded.value) 180f else 0f,
+    )
+
+    BoxWithConstraints {
+        Box(
+            modifier = Modifier
+                .fillMaxWidth()
+                .background(Color.White)
+                .heightIn(0.dp, maxHeight * 0.575f)
+        ) {
+            Column(
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .drawBehind {
+                        drawLine(
+                            color = Color(0xffEDEDF0),
+                            start = Offset(0f, 0f),
+                            end = Offset(size.width, 0f),
+                            strokeWidth = 1.dp.toPx()
+                        )
+                    },
+                verticalArrangement = Arrangement.spacedBy(0.dp)
+            ) {
+                Row(
+                    modifier = Modifier
+                        .fillMaxWidth()
+                        .clickable(
+                            indication = ripple(bounded = true),
+                            interactionSource = remember { MutableInteractionSource() }
+                        ) {
+                            isExpanded.value = !isExpanded.value
+                        }
+                        .padding(16.dp),
+                    verticalAlignment = Alignment.CenterVertically,
+                    horizontalArrangement = Arrangement.SpaceBetween
+                ) {
+                    Row(
+                        verticalAlignment = Alignment.CenterVertically,
+                        horizontalArrangement = Arrangement.spacedBy(8.dp)
+                    ) {
+                        Text(
+                            text = title,
+                            style = TextStyle(
+                                fontSize = 14.sp,
+                                color = Color(0xFF56565C),
+                                fontWeight = FontWeight.SemiBold,
+                            )
+                        )
+
+                        Text(
+                            text = logs.size.toString(),
+                            style = TextStyle(
+                                fontSize = 14.sp,
+                                fontWeight = FontWeight.SemiBold,
+                                color = Color(0xFF56565C),
+                                textAlign = TextAlign.Center
+                            ),
+                            modifier = Modifier
+                                .defaultMinSize(minWidth = 20.dp, minHeight = 20.dp)
+                                .background(
+                                    shape = RoundedCornerShape(6.dp),
+                                    color = Color.Black.copy(alpha = 0.1f),
+                                )
+                                .padding(
+                                    vertical = 2.dp,
+                                    horizontal = when {
+                                        logs.size > 99 -> 5.dp
+                                        logs.size > 9 -> 3.dp
+                                        else -> 2.dp
+                                    },
+                                )
+                        )
+                    }
+
+                    Spacer(modifier = Modifier.weight(1f))
+
+                    // Chevron Icon
+                    Icon(
+                        tint = Color(0xff97979B),
+                        contentDescription = null,
+                        imageVector = Icons.Default.KeyboardArrowDown,
+                        modifier = Modifier.rotate(rotateAnimation.value),
+                    )
+                }
+
+                LogsBottomSheet(
+                    logs = logs,
+                    projectInfo = projectInfo,
+                    isExpanded = isExpanded.value,
+                )
+            }
+        }
+    }
+}
+
+/**
+ * A view to display project information like endpoint, project ID, name, and version.
+ *
+ * @param projectInfo Contains project details like endpoint, project ID, project name, and version.
+ */
+@Composable
+fun ProjectSection(
+    projectInfo: ProjectInfo,
+) {
+    Column(
+        modifier = Modifier.fillMaxWidth()
+    ) {
+        Text(
+            fontSize = 14.sp,
+            text = "Project",
+            color = Color(0xFF97979B),
+            modifier = Modifier
+                .fillMaxWidth()
+                .background(Color(0xFFFAFAFB))
+                .drawBehind {
+                    drawLine(
+                        color = Color(0xFFEDEDF0),
+                        start = Offset(0f, 0f),
+                        end = Offset(size.width, 0f),
+                        strokeWidth = 1.dp.toPx()
+                    )
+                    drawLine(
+                        color = Color(0xFFEDEDF0),
+                        start = Offset(0f, size.height),
+                        end = Offset(size.width, size.height),
+                        strokeWidth = 1.dp.toPx()
+                    )
+                }
+                .padding(vertical = 12.dp, horizontal = 16.dp)
+        )
+
+        Box(
+            modifier = Modifier
+                .fillMaxWidth()
+                .heightIn(min = 0.dp, max = 200.dp)
+        ) {
+            LazyVerticalGrid(
+                columns = GridCells.Fixed(2),
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .padding(horizontal = 16.dp, vertical = 8.dp),
+                horizontalArrangement = Arrangement.spacedBy(20.dp),
+                verticalArrangement = Arrangement.spacedBy(16.dp)
+            ) {
+                items(
+                    items = listOf(
+                        "Endpoint" to projectInfo.endpoint,
+                        "Project ID" to projectInfo.projectId,
+                        "Project name" to projectInfo.projectName,
+                        "Version" to projectInfo.version
+                    )
+                ) { (title, value) ->
+                    ProjectRow(title = title, value = value)
+                }
+            }
+        }
+    }
+}
+
+/**
+ * A reusable component to display individual project details like endpoint, project ID, etc.
+ *
+ * @param title The title of the project row.
+ * @param value The value corresponding to the project row.
+ */
+@Composable
+fun ProjectRow(
+    title: String,
+    value: String,
+) {
+    Column(
+        horizontalAlignment = Alignment.Start,
+        verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.Top),
+    ) {
+        Text(
+            text = title,
+            fontSize = 12.sp,
+            lineHeight = 18.sp,
+            color = Color(0xFF97979B),
+        )
+
+        Text(
+            text = value,
+            maxLines = 1,
+            fontSize = 14.sp,
+            lineHeight = 21.sp,
+            color = Color(0xFF56565C),
+            overflow = TextOverflow.Ellipsis
+        )
+    }
+}
+
+/**
+ * A composable that displays a placeholder section when there are no logs available.
+ */
+@Composable
+fun EmptyLogsSection() {
+    Column {
+        Text(
+            fontSize = 14.sp,
+            text = "Logs",
+            color = Color(0xFF97979B),
+            modifier = Modifier
+                .fillMaxWidth()
+                .background(Color(0xFFFAFAFB))
+                .drawBehind {
+                    drawLine(
+                        color = Color(0xFFEDEDF0),
+                        start = Offset(0f, 0f),
+                        end = Offset(size.width, 0f),
+                        strokeWidth = 1.dp.toPx()
+                    )
+                    drawLine(
+                        color = Color(0xFFEDEDF0),
+                        start = Offset(0f, size.height),
+                        end = Offset(size.width, size.height),
+                        strokeWidth = 1.dp.toPx()
+                    )
+                }
+                .padding(vertical = 12.dp, horizontal = 16.dp)
+        )
+
+        Text(
+            fontSize = 14.sp,
+            color = Color(0xFF56565C),
+            text = "There are no logs to show",
+            fontFamily = FontFamily.Monospace,
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(16.dp)
+        )
+    }
+}
+
+/**
+ * A view displaying logs in a table format, including a project section and a list of logs.
+ * If there are no logs, a placeholder message is shown.
+ *
+ * @param logs The list of logs to be displayed in the bottom sheet.
+ * @param isExpanded Boolean to indicate if the bottom sheet is expanded or collapsed.
+ * @param projectInfo Contains project details like endpoint, project ID, project name, and version.
+ */
+@Composable
+fun LogsBottomSheet(
+    logs: List<Log>,
+    isExpanded: Boolean,
+    projectInfo: ProjectInfo,
+) {
+    AnimatedVisibility(
+        visible = isExpanded,
+        enter = fadeIn() + expandVertically(
+            animationSpec = tween(durationMillis = 500)
+        ),
+        exit = fadeOut() + shrinkVertically(
+            animationSpec = tween(durationMillis = 500)
+        )
+    ) {
+        Column(
+            modifier = Modifier
+                .padding(bottom = 16.dp)
+                .animateContentSize()
+                .verticalScroll(rememberScrollState()),
+            verticalArrangement = Arrangement.spacedBy(16.dp)
+        ) {
+            ProjectSection(projectInfo = projectInfo)
+
+            if (logs.isEmpty()) {
+                EmptyLogsSection()
+            } else {
+                Column(
+                    modifier = Modifier
+                        .horizontalScroll(rememberScrollState())
+                ) {
+                    LogsTableHeader()
+                    LazyColumn(
+                        modifier = Modifier
+                            .animateContentSize()
+                            .heightIn(max = 300.dp)
+                    ) {
+                        items(logs) { log ->
+                            LogsTableRow(log = log)
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+/**
+ * A view to display the header of the logs table, with column names as headers.
+ */
+@Composable
+fun LogsTableHeader() {
+    Row(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(Color(0xFFFAFAFB))
+            .drawBehind {
+                drawLine(
+                    color = Color(0xFFEDEDF0),
+                    start = Offset(0f, 0f),
+                    end = Offset(size.width, 0f),
+                    strokeWidth = 1.dp.toPx()
+                )
+                drawLine(
+                    color = Color(0xFFEDEDF0),
+                    start = Offset(0f, size.height),
+                    end = Offset(size.width, size.height),
+                    strokeWidth = 1.dp.toPx()
+                )
+            }
+            .padding(horizontal = 16.dp, vertical = 12.dp),
+        horizontalArrangement = Arrangement.Start
+    ) {
+        columns.forEach { (name, width) ->
+            Text(
+                text = name,
+                fontSize = 14.sp,
+                color = Color(0xFF97979B),
+                maxLines = 1,
+                overflow = TextOverflow.Ellipsis,
+                modifier = Modifier
+                    .width(width.dp)
+                    .background(Color(0xFFF9F9FA))
+            )
+        }
+    }
+
+}
+
+/**
+ * A component that displays a log row in the table, with dynamic content based on the column name.
+ *
+ * @param log The log entry containing details like date, status, method, path, and response.
+ *
+ */
+@Composable
+fun LogsTableRow(log: Log) {
+    Row(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(Color.White)
+            .drawBehind {
+                drawLine(
+                    color = Color(0xFFEDEDF0),
+                    start = Offset(0f, size.height),
+                    end = Offset(size.width, size.height),
+                    strokeWidth = 0.5.dp.toPx()
+                )
+            }
+            .padding(horizontal = 16.dp, vertical = 10.dp),
+        horizontalArrangement = Arrangement.Start,
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        columns.forEach { (name, width) ->
+            when (name) {
+                "Date" -> Text(
+                    text = log.date,
+                    fontSize = 14.sp,
+                    color = Color(0xFF56565C),
+                    fontFamily = FontFamily.Monospace,
+                    modifier = Modifier.width(width.dp)
+                )
+
+                "Status" -> StatusTag(
+                    status = log.status,
+                    modifier = Modifier.width(width.dp)
+                )
+
+                "Method" -> Text(
+                    text = log.method,
+                    fontSize = 14.sp,
+                    fontFamily = FontFamily.Monospace,
+                    color = Color(0xFF56565C),
+                    modifier = Modifier.width(width.dp)
+                )
+
+                "Path" -> Text(
+                    text = log.path,
+                    fontSize = 14.sp,
+                    fontFamily = FontFamily.Monospace,
+                    color = Color(0xFF56565C),
+                    modifier = Modifier.width(width.dp)
+                )
+
+                "Response" ->
+                    Box(modifier = Modifier.width(width.dp)) {
+                        Text(
+                            maxLines = 1,
+                            fontSize = 12.sp,
+                            text = log.response,
+                            color = Color(0xFF56565C),
+                            fontFamily = FontFamily.Monospace,
+                            overflow = TextOverflow.Ellipsis,
+                            modifier = Modifier
+                                .background(
+                                    Color.Gray.copy(alpha = 0.25f),
+                                    RoundedCornerShape(6.dp)
+                                )
+                                .padding(horizontal = 5.dp, vertical = 2.dp)
+                        )
+                    }
+
+                else -> Spacer(modifier = Modifier.width(width.dp))
+            }
+        }
+    }
+    HorizontalDivider(color = Color(0xFFEDEDF0), thickness = 1.dp)
+}
+
+/**
+ * A view to display a status tag with conditional styling based on the status value.
+ *
+ * @param status The status value to display.
+ * @param modifier Modifier to style or adjust the layout of the status tag.
+ */
+@Composable
+fun StatusTag(
+    status: String,
+    modifier: Modifier = Modifier,
+) {
+    val isSuccessful = status.toIntOrNull() in 200..399
+    val textColor = if (isSuccessful) Color(0xFF0A714F) else Color(0xFFB31212)
+    val backgroundColor = if (isSuccessful) Color(0x4010B981) else Color(0x40FF453A)
+
+    Box(modifier = modifier) {
+        Text(
+            text = status,
+            style = TextStyle(
+                fontSize = 12.sp,
+                color = textColor,
+                textAlign = TextAlign.Center,
+                fontWeight = FontWeight.SemiBold,
+            ),
+            modifier = Modifier
+                .background(
+                    shape = RoundedCornerShape(6.dp),
+                    color = backgroundColor.copy(alpha = 0.1f),
+                )
+                .padding(
+                    vertical = 2.dp,
+                    horizontal = 5.dp,
+                )
+        )
+    }
+}
+
+@Composable
+@Preview(showBackground = true)
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun CollapsibleBottomSheetPreview() {
+    val isEmptyState = remember { mutableStateOf(false) }
+    val logItems = List(10) {
+        listOf(
+            Log(
+                date = "Dec 10, 02:51",
+                status = "200",
+                method = "GET",
+                path = "/v1/ping",
+                response = "Success"
+            ),
+        )
+    }.flatten()
+
+    Scaffold(
+        bottomBar = {
+            CollapsibleBottomSheet(
+                logs = if (isEmptyState.value) listOf() else logItems,
+                projectInfo = mockProjectInfo
+            )
+        }
+    ) { innerPadding ->
+        Column(
+            modifier = Modifier
+                .padding(innerPadding)
+                .fillMaxSize(),
+            verticalArrangement = Arrangement.Center,
+            horizontalAlignment = Alignment.CenterHorizontally
+        ) {
+            Button(
+                border = BorderStroke(1.dp, Color(0xFFFD366E)),
+                colors = ButtonDefaults.buttonColors().copy(containerColor = Color.Transparent),
+                onClick = {
+                    isEmptyState.value = !isEmptyState.value
+                }) {
+                Text(
+                    fontSize = 16.sp,
+                    color = Color.Black,
+                    text = "Logs state: ${if (isEmptyState.value) "Empty" else "Full"}",
+                )
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/components/ConnectionLine.kt b/app/src/main/java/io/appwrite/starterkit/ui/components/ConnectionLine.kt
new file mode 100644
index 0000000..b59b632
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/components/ConnectionLine.kt
@@ -0,0 +1,182 @@
+package io.appwrite.starterkit.ui.components
+
+import androidx.annotation.RestrictTo
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.FastOutSlowInEasing
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.expandHorizontally
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkHorizontally
+import androidx.compose.animation.slideInHorizontally
+import androidx.compose.animation.slideOutHorizontally
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+/**
+ * A view that animates a connection line with a checkmark in the middle. The left and right
+ * lines expand and contract based on the `show` state, with a tick appearing after a delay.
+ *
+ * @param show Controls whether the connection line animation and the tick are visible.
+ *
+ */
+@Composable
+fun ConnectionLine(show: Boolean) {
+    val tickAlpha by animateFloatAsState(
+        targetValue = if (show) 1f else 0f,
+        animationSpec = tween(
+            durationMillis = if (show) 500 else 50,
+            easing = FastOutSlowInEasing
+        ), label = "TickAlpha"
+    )
+
+    Row(
+        horizontalArrangement = Arrangement.Center,
+        verticalAlignment = Alignment.CenterVertically,
+    ) {
+        // Left line
+        Sidelines(left = true, show = show)
+
+        // Tick icon
+        Box(
+            modifier = Modifier
+                .padding(2.dp)
+                .size(30.dp)
+                .alpha(tickAlpha)
+                .clip(CircleShape)
+                .background(Color(0x14F02E65))
+                .border(width = 1.8.dp, color = Color(0x80F02E65), shape = CircleShape),
+            contentAlignment = Alignment.Center
+        ) {
+            Icon(
+                imageVector = Icons.Default.Check,
+                contentDescription = "Checkmark",
+                tint = Color(0xFFFD366E),
+                modifier = Modifier.size(15.dp)
+            )
+        }
+
+        // Right line
+        Sidelines(left = false, show = show)
+    }
+}
+
+/**
+ * A composable function that animates horizontal sidelines with a gradient effect.
+ *
+ * @param left Indicates whether the sideline is on the left side (true) or right side (false).
+ * @param show Controls the visibility and animation of the sideline.
+ */
+@Composable
+fun RowScope.Sidelines(
+    left: Boolean,
+    show: Boolean,
+) {
+    val delay = if (show) 500 else 0
+    val duration = if (show) 1250 else 0
+
+    AnimatedVisibility(
+        visible = show,
+        enter = slideInHorizontally(
+            initialOffsetX = { fullWidth ->
+                if (left) fullWidth / 2 else -fullWidth / 2
+            },
+            animationSpec = tween(durationMillis = duration, delayMillis = delay)
+        ) + expandHorizontally(
+            expandFrom = Alignment.CenterHorizontally,
+            animationSpec = tween(durationMillis = duration, delayMillis = delay)
+        ) + fadeIn(
+            animationSpec = tween(durationMillis = duration, delayMillis = delay)
+        ),
+        exit = slideOutHorizontally(
+            targetOffsetX = { fullWidth ->
+                if (left) fullWidth / 2 else -fullWidth / 2
+            },
+            animationSpec = tween(durationMillis = duration)
+        ) + shrinkHorizontally(
+            shrinkTowards = Alignment.CenterHorizontally,
+            animationSpec = tween(durationMillis = duration)
+        ) + fadeOut(
+            animationSpec = tween(delayMillis = delay, durationMillis = duration)
+        ),
+        modifier = Modifier.weight(1f)
+    ) {
+        Box(
+            modifier = Modifier
+                .height(1.5.dp)
+                .background(
+                    Brush.horizontalGradient(
+                        colors = if (!left) {
+                            listOf(Color(0xFFF02E65), Color(0x26FE9567))
+                        } else {
+                            listOf(Color(0x26FE9567), Color(0xFFF02E65))
+                        }
+                    )
+                )
+        )
+    }
+}
+
+
+@Composable
+@Preview(showBackground = true)
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun AnimatedConnectionLinePreview() {
+    var showConnection by remember { mutableStateOf(false) }
+
+    Column(
+        verticalArrangement = Arrangement.Center,
+        horizontalAlignment = Alignment.CenterHorizontally,
+        modifier = Modifier.fillMaxSize()
+    ) {
+        // Title
+        Button(
+            colors = ButtonDefaults.buttonColors().copy(containerColor = Color.Transparent),
+            border = BorderStroke(1.dp, Color(0xFFFD366E)),
+            onClick = {
+                showConnection = !showConnection
+            }) {
+            Text(
+                text = "Connection Line Animation",
+                color = Color.Black, fontSize = 16.sp
+            )
+        }
+
+        Spacer(modifier = Modifier.height(20.dp))
+
+        ConnectionLine(show = showConnection)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/components/ConnectionStatusView.kt b/app/src/main/java/io/appwrite/starterkit/ui/components/ConnectionStatusView.kt
new file mode 100644
index 0000000..1986470
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/components/ConnectionStatusView.kt
@@ -0,0 +1,177 @@
+package io.appwrite.starterkit.ui.components
+
+import androidx.annotation.RestrictTo
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.animateContentSize
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.togetherWith
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeContentPadding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.hapticfeedback.HapticFeedbackType
+import androidx.compose.ui.platform.LocalHapticFeedback
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.appwrite.starterkit.data.models.Status
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/**
+ * A view that displays the current connection status and allows the user to send a ping
+ * to verify the connection. It shows different messages based on the connection status.
+ *
+ * @param status The current status of the connection, represented by the [Status].
+ * @param onSendPingClick A suspend function that is triggered when the "Send a ping" button is clicked.
+ */
+@Composable
+fun ConnectionStatusView(
+    status: Status,
+    onSendPingClick: suspend () -> Unit,
+) {
+    val coroutineScope = rememberCoroutineScope()
+
+    Column(
+        modifier = Modifier
+            .padding(16.dp)
+            .animateContentSize(),
+        horizontalAlignment = Alignment.CenterHorizontally,
+    ) {
+        AnimatedContent(
+            label = "",
+            targetState = status,
+            transitionSpec = { fadeIn() togetherWith fadeOut() }
+        ) { statusValue ->
+            Column(
+                modifier = Modifier.fillMaxWidth(),
+                verticalArrangement = Arrangement.spacedBy(8.dp),
+                horizontalAlignment = Alignment.CenterHorizontally,
+            ) {
+                when (statusValue) {
+                    Status.Loading -> {
+                        Row(
+                            verticalAlignment = Alignment.CenterVertically,
+                            horizontalArrangement = Arrangement.spacedBy(16.dp)
+                        ) {
+                            CircularProgressIndicator(
+                                modifier = Modifier.size(24.dp),
+                                color = Color.Gray,
+                                strokeWidth = 2.dp
+                            )
+                            Text(
+                                text = "Waiting for connection...",
+                                fontSize = 14.sp,
+                                lineHeight = 19.6.sp,
+                                fontWeight = FontWeight(400),
+                                color = Color(0xFF2D2D31)
+                            )
+                        }
+                    }
+
+                    Status.Success -> {
+                        // header
+                        Text(
+                            fontSize = 24.sp,
+                            text = "Congratulations!",
+                            color = Color(0xFF2D2D31),
+                            fontWeight = FontWeight(400),
+                        )
+
+                        Text(
+                            fontSize = 14.sp,
+                            lineHeight = 19.6.sp,
+                            color = Color(0xFF56565C),
+                            text = "You connected your app successfully.",
+                        )
+                    }
+
+                    Status.Error, Status.Idle -> {
+                        // header
+                        Text(
+                            text = "Check connection",
+                            fontSize = 24.sp,
+                            lineHeight = 28.8.sp,
+                            fontWeight = FontWeight(400),
+                            color = Color(0xFF2D2D31)
+                        )
+                        Text(
+                            text = "Send a ping to verify the connection.",
+                            fontSize = 14.sp,
+                            lineHeight = 19.6.sp,
+                            color = Color(0xFF56565C)
+                        )
+                    }
+                }
+            }
+        }
+
+        // Ping Button
+        AnimatedVisibility(
+            exit = fadeOut(),
+            enter = fadeIn(),
+            modifier = Modifier.padding(top = 24.dp),
+            visible = status != Status.Loading,
+        ) {
+            val haptic = LocalHapticFeedback.current
+
+            Button(
+                onClick = {
+                    haptic.performHapticFeedback(HapticFeedbackType.LongPress)
+                    coroutineScope.launch { onSendPingClick() }
+                },
+                shape = RoundedCornerShape(12.dp),
+                colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFFD366E)),
+            ) {
+                Text(
+                    fontSize = 14.sp,
+                    color = Color.White,
+                    text = "Send a ping",
+                    fontWeight = FontWeight.Medium,
+                )
+            }
+        }
+    }
+}
+
+@Composable
+@Preview(showBackground = true)
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun ConnectionStatusViewPreview() {
+    val status = remember { mutableStateOf<Status>(Status.Idle) }
+
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .safeContentPadding()
+    ) {
+        ConnectionStatusView(
+            status = status.value,
+            onSendPingClick = {
+                status.value = Status.Loading
+                delay(2500)
+                status.value = Status.Success
+            }
+        )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/components/GettingStartedCards.kt b/app/src/main/java/io/appwrite/starterkit/ui/components/GettingStartedCards.kt
new file mode 100644
index 0000000..d23ea44
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/components/GettingStartedCards.kt
@@ -0,0 +1,190 @@
+package io.appwrite.starterkit.ui.components
+
+import androidx.annotation.RestrictTo
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+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.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ArrowForward
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.material3.ripple
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalUriHandler
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.withStyle
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+
+/**
+ * A view that contains a list of informational cards displayed vertically.
+ */
+@Composable
+fun GettingStartedCards() {
+    Column(
+        modifier = Modifier
+            .fillMaxSize()
+            .padding(16.dp)
+            .padding(horizontal = 16.dp),
+        verticalArrangement = Arrangement.spacedBy(16.dp)
+    ) {
+        GeneralInfoCard(
+            title = "Edit your app",
+            link = null,
+            subtitle = {
+                HighlightedText()
+            }
+        )
+
+        // Second Card: Head to Appwrite Cloud
+        GeneralInfoCard(
+            title = "Head to Appwrite Cloud",
+            link = "https://cloud.appwrite.io",
+            subtitle = {
+                Text(
+                    fontSize = 14.sp,
+                    color = Color(0xFF56565C),
+                    fontWeight = FontWeight(400),
+                    text = "Start managing your project from the Appwrite console",
+                )
+            }
+        )
+
+        // Third Card: Explore docs
+        GeneralInfoCard(
+            title = "Explore docs",
+            link = "https://appwrite.io/docs",
+            subtitle = {
+                Text(
+                    fontSize = 14.sp,
+                    color = Color(0xFF56565C),
+                    fontWeight = FontWeight(400),
+                    text = "Discover the full power of Appwrite by diving into our documentation",
+                )
+            }
+        )
+    }
+}
+
+/**
+ * A reusable card component that displays a title and subtitle with optional link functionality.
+ * The card becomes clickable if a link is provided and opens the destination URL when clicked.
+ *
+ * @param title The title text displayed at the top of the card.
+ * @param link An optional URL; if provided, the card becomes clickable.
+ * @param subtitle A composable lambda that defines the subtitle content of the card.
+ */
+@Composable
+fun GeneralInfoCard(
+    title: String,
+    link: String?,
+    subtitle: @Composable () -> Unit,
+) {
+    val indication = ripple(bounded = true)
+    val uriHandler = LocalUriHandler.current
+    val interactionSource = remember { MutableInteractionSource() }
+
+    Card(
+        shape = RoundedCornerShape(8.dp),
+        border = BorderStroke(1.dp, Color(0xFFEDEDF0)),
+        modifier = Modifier
+            .fillMaxWidth()
+            .clip(RoundedCornerShape(8.dp))
+            .background(
+                color = Color.White,
+                shape = RoundedCornerShape(size = 8.dp)
+            )
+            .clickable(
+                enabled = link != null,
+                indication = indication,
+                interactionSource = interactionSource,
+            ) {
+                uriHandler.openUri(link.toString())
+            },
+        colors = CardDefaults.cardColors(containerColor = Color.White)
+    ) {
+        Column(
+            modifier = Modifier
+                .fillMaxWidth()
+                .padding(16.dp),
+            verticalArrangement = Arrangement.spacedBy(8.dp)
+        ) {
+            Row(
+                verticalAlignment = Alignment.CenterVertically,
+                modifier = Modifier.fillMaxWidth()
+            ) {
+                Text(
+                    text = title,
+                    style = TextStyle(
+                        fontSize = 20.sp,
+                        lineHeight = 26.sp,
+                        fontWeight = FontWeight(400),
+                    )
+                )
+                if (link != null) {
+                    Spacer(modifier = Modifier.weight(1f))
+                    Icon(
+                        tint = Color(0xFFD8D8DB),
+                        contentDescription = null,
+                        modifier = Modifier.size(18.dp),
+                        imageVector = Icons.AutoMirrored.Default.ArrowForward,
+                    )
+                }
+            }
+            subtitle()
+        }
+    }
+}
+
+/**
+ * A composable function that displays highlighted text with a specific word or phrase styled differently.
+ * Useful for drawing attention to specific content in a sentence.
+ */
+@Composable
+fun HighlightedText() {
+    val text = buildAnnotatedString {
+        append("Edit ")
+        withStyle(
+            style = SpanStyle(
+                background = Color(0xFFEDEDF0),
+                fontWeight = FontWeight(500)
+            )
+        ) { append(" MainActivity.kt ") }
+        append(" to get started with building your app")
+    }
+
+    Text(
+        text = text,
+        fontSize = 14.sp,
+        color = Color(0xFF56565C),
+        fontWeight = FontWeight(400),
+    )
+}
+
+@Composable
+@Preview(showBackground = true)
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun GettingStartedCardsPreview() {
+    GettingStartedCards()
+}
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/components/TopPlatformView.kt b/app/src/main/java/io/appwrite/starterkit/ui/components/TopPlatformView.kt
new file mode 100644
index 0000000..8ec0c24
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/components/TopPlatformView.kt
@@ -0,0 +1,174 @@
+package io.appwrite.starterkit.ui.components
+
+import androidx.annotation.RestrictTo
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Icon
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import io.appwrite.starterkit.data.models.Status
+import io.appwrite.starterkit.ui.icons.AndroidIcon
+import io.appwrite.starterkit.ui.icons.AppwriteIcon
+import kotlinx.coroutines.delay
+
+/**
+ * A composable function that displays a row containing platform icons and a connection line between them.
+ * The connection line indicates the status of the platform connection.
+ *
+ * @param status A [Status] indicating the current connection status.
+ */
+@Composable
+fun TopPlatformView(status: Status) {
+    Row(
+        verticalAlignment = Alignment.CenterVertically,
+        horizontalArrangement = Arrangement.Center,
+        modifier = Modifier
+            .fillMaxWidth()
+            .padding(8.dp)
+            .padding(horizontal = 40.dp)
+    ) {
+        // First Platform Icon
+        Box(
+            contentAlignment = Alignment.Center
+        ) {
+            PlatformIcon {
+                Icon(
+                    tint = Color(0xff3ddc84),
+                    modifier = Modifier
+                        .width(45.86047.dp)
+                        .height(45.86047.dp),
+                    painter = rememberVectorPainter(AndroidIcon),
+                    contentDescription = "Android Icon"
+                )
+            }
+        }
+
+        // ConnectionLine
+        Box(
+            modifier = Modifier.weight(1f),
+            contentAlignment = Alignment.Center
+        ) {
+            ConnectionLine(show = status == Status.Success)
+        }
+
+        // Second Platform Icon
+        Box(
+            contentAlignment = Alignment.Center
+        ) {
+            PlatformIcon {
+                Icon(
+                    tint = Color(0xffFD366E),
+                    modifier = Modifier
+                        .width(35.86047.dp)
+                        .height(35.86047.dp),
+                    painter = rememberVectorPainter(AppwriteIcon),
+                    contentDescription = "Appwrite Icon"
+                )
+            }
+        }
+    }
+}
+
+/**
+ * A composable function that displays a stylized platform icon with a customizable content block.
+ * The icon is rendered with shadows, rounded corners, and a layered background.
+ *
+ * @param modifier Modifier for additional customizations like size and padding.
+ * @param content A composable lambda that defines the inner content of the icon (e.g., an image or vector asset).
+ */
+@Composable
+fun PlatformIcon(
+    modifier: Modifier = Modifier,
+    content: @Composable BoxScope.() -> Unit,
+) {
+    Box {
+        Box(
+            modifier = Modifier
+                .shadow(
+                    elevation = 9.360000610351562.dp,
+                    spotColor = Color(0x08000000),
+                    ambientColor = Color(0x08000000)
+                )
+                .border(
+                    width = 1.dp,
+                    color = Color(0x0A19191C),
+                    shape = RoundedCornerShape(size = 24.dp)
+                )
+                .width(100.dp)
+                .height(100.dp)
+                .background(color = Color(0xFFFAFAFD), shape = RoundedCornerShape(size = 24.dp))
+        ) {
+            Box(
+                modifier = Modifier
+                    .shadow(
+                        elevation = 8.dp,
+                        spotColor = Color(0x05000000),
+                        ambientColor = Color(0x05000000)
+                    )
+                    .shadow(
+                        elevation = 12.dp,
+                        spotColor = Color(0x05000000),
+                        ambientColor = Color(0x05000000)
+                    )
+                    .border(
+                        width = 1.dp,
+                        color = Color(0xFFFAFAFB),
+                        shape = RoundedCornerShape(size = 16.dp)
+                    )
+                    .width(86.04652.dp)
+                    .height(86.04652.dp)
+                    .align(Alignment.Center)
+                    .background(color = Color.White, shape = RoundedCornerShape(size = 16.dp))
+            ) {
+                // Content
+                Box(
+                    modifier = Modifier.align(Alignment.Center),
+                    content = content
+                )
+            }
+        }
+    }
+}
+
+@Composable
+@Preview(showBackground = true)
+@RestrictTo(RestrictTo.Scope.TESTS)
+private fun PlatformIconPreview() {
+    val status = remember { mutableStateOf<Status>(Status.Idle) }
+
+    Column(
+        modifier = Modifier
+            .fillMaxSize()
+            .addCheckeredBackground(),
+    ) {
+        TopPlatformView(status = status.value)
+
+        ConnectionStatusView(
+            status = status.value,
+            onSendPingClick = {
+                status.value = Status.Loading
+                delay(500)
+                status.value = Status.Success
+            }
+        )
+    }
+}
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/icons/AndroidIcon.kt b/app/src/main/java/io/appwrite/starterkit/ui/icons/AndroidIcon.kt
new file mode 100644
index 0000000..bae4896
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/icons/AndroidIcon.kt
@@ -0,0 +1,78 @@
+package io.appwrite.starterkit.ui.icons
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.PathFillType
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.graphics.StrokeJoin
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+
+val AndroidIcon: ImageVector
+    get() {
+        if (_Android != null) {
+            return _Android!!
+        }
+        _Android = ImageVector.Builder(
+            name = "Android",
+            defaultWidth = 24.dp,
+            defaultHeight = 24.dp,
+            viewportWidth = 960f,
+            viewportHeight = 960f
+        ).apply {
+            path(
+                fill = SolidColor(Color.Black),
+                fillAlpha = 1.0f,
+                stroke = null,
+                strokeAlpha = 1.0f,
+                strokeLineWidth = 1.0f,
+                strokeLineCap = StrokeCap.Butt,
+                strokeLineJoin = StrokeJoin.Miter,
+                strokeLineMiter = 1.0f,
+                pathFillType = PathFillType.NonZero
+            ) {
+                moveTo(40f, 720f)
+                quadToRelative(9f, -107f, 65.5f, -197f)
+                reflectiveQuadTo(256f, 380f)
+                lineToRelative(-74f, -128f)
+                quadToRelative(-6f, -9f, -3f, -19f)
+                reflectiveQuadToRelative(13f, -15f)
+                quadToRelative(8f, -5f, 18f, -2f)
+                reflectiveQuadToRelative(16f, 12f)
+                lineToRelative(74f, 128f)
+                quadToRelative(86f, -36f, 180f, -36f)
+                reflectiveQuadToRelative(180f, 36f)
+                lineToRelative(74f, -128f)
+                quadToRelative(6f, -9f, 16f, -12f)
+                reflectiveQuadToRelative(18f, 2f)
+                quadToRelative(10f, 5f, 13f, 15f)
+                reflectiveQuadToRelative(-3f, 19f)
+                lineToRelative(-74f, 128f)
+                quadToRelative(94f, 53f, 150.5f, 143f)
+                reflectiveQuadTo(920f, 720f)
+                close()
+                moveToRelative(240f, -110f)
+                quadToRelative(21f, 0f, 35.5f, -14.5f)
+                reflectiveQuadTo(330f, 560f)
+                reflectiveQuadToRelative(-14.5f, -35.5f)
+                reflectiveQuadTo(280f, 510f)
+                reflectiveQuadToRelative(-35.5f, 14.5f)
+                reflectiveQuadTo(230f, 560f)
+                reflectiveQuadToRelative(14.5f, 35.5f)
+                reflectiveQuadTo(280f, 610f)
+                moveToRelative(400f, 0f)
+                quadToRelative(21f, 0f, 35.5f, -14.5f)
+                reflectiveQuadTo(730f, 560f)
+                reflectiveQuadToRelative(-14.5f, -35.5f)
+                reflectiveQuadTo(680f, 510f)
+                reflectiveQuadToRelative(-35.5f, 14.5f)
+                reflectiveQuadTo(630f, 560f)
+                reflectiveQuadToRelative(14.5f, 35.5f)
+                reflectiveQuadTo(680f, 610f)
+            }
+        }.build()
+        return _Android!!
+    }
+
+private var _Android: ImageVector? = null
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/icons/AppwriteIcon.kt b/app/src/main/java/io/appwrite/starterkit/ui/icons/AppwriteIcon.kt
new file mode 100644
index 0000000..9da4836
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/icons/AppwriteIcon.kt
@@ -0,0 +1,79 @@
+package io.appwrite.starterkit.ui.icons
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.PathFillType
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.StrokeCap
+import androidx.compose.ui.graphics.StrokeJoin
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+
+val AppwriteIcon: ImageVector
+    get() {
+        if (_Appwrite != null) {
+            return _Appwrite!!
+        }
+        _Appwrite = ImageVector.Builder(
+            name = "Logo",
+            defaultWidth = 112.dp,
+            defaultHeight = 98.dp,
+            viewportWidth = 112f,
+            viewportHeight = 98f
+        ).apply {
+            path(
+                fill = SolidColor(Color(0xFFFD366E)),
+                fillAlpha = 1.0f,
+                stroke = null,
+                strokeAlpha = 1.0f,
+                strokeLineWidth = 1.0f,
+                strokeLineCap = StrokeCap.Butt,
+                strokeLineJoin = StrokeJoin.Miter,
+                strokeLineMiter = 1.0f,
+                pathFillType = PathFillType.NonZero
+            ) {
+                moveTo(111.1f, 73.4729f)
+                verticalLineTo(97.9638f)
+                horizontalLineTo(48.8706f)
+                curveTo(30.74060f, 97.96380f, 14.91050f, 88.1140f, 6.44110f, 73.47290f)
+                curveTo(5.20990f, 71.34440f, 4.13230f, 69.11130f, 3.22830f, 66.79350f)
+                curveTo(1.45390f, 62.25160f, 0.33840f, 57.37790f, 00f, 52.29260f)
+                verticalLineTo(45.6712f)
+                curveTo(0.07350f, 44.53790f, 0.18920f, 43.41350f, 0.34060f, 42.30250f)
+                curveTo(0.65010f, 40.02270f, 1.11770f, 37.79180f, 1.73220f, 35.62320f)
+                curveTo(7.54540f, 15.06410f, 26.4480f, 00f, 48.87060f, 00f)
+                curveTo(71.29320f, 00f, 90.19350f, 15.06410f, 96.00680f, 35.62320f)
+                horizontalLineTo(69.3985f)
+                curveTo(65.03020f, 28.92160f, 57.46920f, 24.4910f, 48.87060f, 24.4910f)
+                curveTo(40.2720f, 24.4910f, 32.7110f, 28.92160f, 28.34270f, 35.62320f)
+                curveTo(27.01130f, 37.66040f, 25.97820f, 39.90690f, 25.30140f, 42.30250f)
+                curveTo(24.70020f, 44.42660f, 24.37960f, 46.66640f, 24.37960f, 48.98190f)
+                curveTo(24.37960f, 56.00190f, 27.33190f, 62.32950f, 32.06530f, 66.79350f)
+                curveTo(36.45150f, 70.93690f, 42.36490f, 73.47290f, 48.87060f, 73.47290f)
+                horizontalLineTo(111.1f)
+                close()
+            }
+            path(
+                fill = SolidColor(Color(0xFFFD366E)),
+                fillAlpha = 1.0f,
+                stroke = null,
+                strokeAlpha = 1.0f,
+                strokeLineWidth = 1.0f,
+                strokeLineCap = StrokeCap.Butt,
+                strokeLineJoin = StrokeJoin.Miter,
+                strokeLineMiter = 1.0f,
+                pathFillType = PathFillType.NonZero
+            ) {
+                moveTo(111.1f, 42.3027f)
+                verticalLineTo(66.7937f)
+                horizontalLineTo(65.6759f)
+                curveTo(70.40940f, 62.32970f, 73.36160f, 56.00210f, 73.36160f, 48.98210f)
+                curveTo(73.36160f, 46.66660f, 73.0410f, 44.42680f, 72.43990f, 42.30270f)
+                horizontalLineTo(111.1f)
+                close()
+            }
+        }.build()
+        return _Appwrite!!
+    }
+
+private var _Appwrite: ImageVector? = null
diff --git a/app/src/main/java/io/appwrite/starterkit/ui/theme/Theme.kt b/app/src/main/java/io/appwrite/starterkit/ui/theme/Theme.kt
new file mode 100644
index 0000000..96585c1
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/ui/theme/Theme.kt
@@ -0,0 +1,49 @@
+package io.appwrite.starterkit.ui.theme
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Typography
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Light color scheme
+private val LightColorScheme = lightColorScheme(
+    primary = Color(0xFF6650a4), // Purple40
+    secondary = Color(0xFF625b71), // PurpleGrey40
+    tertiary = Color(0xFF7D5260) // Pink40
+)
+
+// Typography
+private val Typography = Typography(
+    bodyLarge = TextStyle(
+        fontFamily = FontFamily.Default,
+        fontWeight = FontWeight.Normal,
+        fontSize = 16.sp,
+        lineHeight = 24.sp,
+        letterSpacing = 0.5.sp
+    )
+)
+
+/**
+ * A custom theme composable for the Appwrite Starter Kit application.
+ *
+ * This function sets the app's overall typography, color scheme, and material theme,
+ * providing consistent styling throughout the app. The `content` composable
+ * is wrapped within the custom [MaterialTheme].
+ *
+ * @param content The composable content to be styled with the Appwrite Starter Kit theme.
+ */
+@Composable
+fun AppwriteStarterKitTheme(
+    content: @Composable () -> Unit,
+) {
+    MaterialTheme(
+        content = content,
+        typography = Typography,
+        colorScheme = LightColorScheme,
+    )
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/appwrite/starterkit/viewmodels/AppwriteViewModel.kt b/app/src/main/java/io/appwrite/starterkit/viewmodels/AppwriteViewModel.kt
new file mode 100644
index 0000000..636ed3b
--- /dev/null
+++ b/app/src/main/java/io/appwrite/starterkit/viewmodels/AppwriteViewModel.kt
@@ -0,0 +1,63 @@
+package io.appwrite.starterkit.viewmodels
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import io.appwrite.starterkit.constants.AppwriteConfig
+import io.appwrite.starterkit.data.models.Log
+import io.appwrite.starterkit.data.models.ProjectInfo
+import io.appwrite.starterkit.data.models.Status
+import io.appwrite.starterkit.data.repository.AppwriteRepository
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/**
+ * A ViewModel class that serves as the central hub for managing and storing the state
+ * related to Appwrite operations, such as project information, connection status, and logs.
+ */
+class AppwriteViewModel(application: Application) : AndroidViewModel(application) {
+
+    private val repository = AppwriteRepository.getInstance(application)
+
+    private val _status = MutableStateFlow<Status>(Status.Idle)
+    private val _logs = MutableStateFlow<List<Log>>(emptyList())
+
+    val logs: StateFlow<List<Log>> = _logs.asStateFlow()
+    val status: StateFlow<Status> = _status.asStateFlow()
+
+    /**
+     * Retrieves project information such as version, project ID, endpoint, and project name.
+     *
+     * @return [ProjectInfo] An object containing project details.
+     */
+    fun getProjectInfo(): ProjectInfo {
+        return ProjectInfo(
+            version = AppwriteConfig.APPWRITE_VERSION,
+            projectId = AppwriteConfig.APPWRITE_PROJECT_ID,
+            endpoint = AppwriteConfig.APPWRITE_PUBLIC_ENDPOINT,
+            projectName = AppwriteConfig.APPWRITE_PROJECT_NAME
+        )
+    }
+
+    /**
+     * Executes a ping operation to verify connectivity and logs the result.
+     *
+     * Updates the [status] to [Status.Loading] during the operation and then updates it
+     * based on the success or failure of the ping. Appends the result to [logs].
+     */
+    suspend fun ping() {
+        _status.value = Status.Loading
+        val log = repository.fetchPingLog()
+
+        _logs.value += log
+
+        delay(1000)
+
+        _status.value = if (log.status.toIntOrNull() in 200..399) {
+            Status.Success
+        } else {
+            Status.Error
+        }
+    }
+}
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..af0f523
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..5d0c4f2
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..2700fd7
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..20d38d4
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..374c756
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..1283042
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <style name="Theme.AppwriteStarterKit" parent="android:Theme.Material.Light.NoActionBar">
+        <item name="android:windowTranslucentStatus">true</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
+        <item name="windowSplashScreenIconBackgroundColor">@android:color/black</item>
+    </style>
+
+    <style name="Theme.AppwriteStarterKit.SplashTheme" parent="Theme.SplashScreen.IconBackground">
+        <item name="windowSplashScreenBackground">#FFF</item>
+        <item name="postSplashScreenTheme">@style/Theme.AppwriteStarterKit</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..952b930
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,6 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+    alias(libs.plugins.android.application) apply false
+    alias(libs.plugins.kotlin.android) apply false
+    alias(libs.plugins.kotlin.compose) apply false
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..deab996
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,4 @@
+android.useAndroidX=true
+kotlin.code.style=official
+android.nonTransitiveRClass=true
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000..b5e6ee3
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,30 @@
+[versions]
+agp = "8.7.3"
+kotlin = "2.0.0"
+coreKtx = "1.15.0"
+splashScreen = "1.2.0-alpha02"
+lifecycleRuntimeKtx = "2.8.7"
+activityCompose = "1.10.0"
+composeBom = "2025.01.01"
+appwrite = "7.0.0"
+
+[libraries]
+appwrite = { group = "io.appwrite", name = "sdk-for-android", version.ref = "appwrite" }
+androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "splashScreen" }
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
+androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" }
+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-material3 = { group = "androidx.compose.material3", name = "material3" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..f0a7fbc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 18 13:34:27 IST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=`expr $i + 1`
+    done
+    case $i in
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 0000000..0c94d46
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1,25 @@
+pluginManagement {
+    repositories {
+        google {
+            content {
+                includeGroupByRegex("com\\.android.*")
+                includeGroupByRegex("com\\.google.*")
+                includeGroupByRegex("androidx.*")
+            }
+        }
+        mavenCentral()
+        gradlePluginPortal()
+    }
+}
+
+@Suppress("UnstableApiUsage")
+dependencyResolutionManagement {
+    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+rootProject.name = "AppwriteStarterKit"
+include(":app")