Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/skydoves/server-driven-compose

πŸ§™ Server Driven Compose showcases server-driven UI approaches in Jetpack Compose with Firebase.
https://github.com/skydoves/server-driven-compose

android compose firebase kotlin realtime-database server-driven-ui skydoves

Last synced: 9 days ago
JSON representation

πŸ§™ Server Driven Compose showcases server-driven UI approaches in Jetpack Compose with Firebase.

Awesome Lists containing this project

README

        

Server Driven Compose


License
API
Build Status
Profile


πŸ§™ Server Driven Compose showcases server-driven UI approaches in Jetpack Compose with Firebase.



The purpose of this repository is to demonstrate the following:

- Implementing server-driven UI using Jetpack Compose and Firebase Realtime Database.
- Defining rendering protocols (such as layout nodes, action handlers, and versioning) and consuming them as composable functions in Jetpack Compose.
- Establishing component design systems for consuming rendering protocols on the client side, along with versioning systems for these design components.
- Gaining a deeper understanding of the Firebase Realtime Database system.

## ✍️ Technical Content

If you're interested in the overall design systems and the implementation details of this project, check out the blog post below:

- [Design Server-Driven UI with Jetpack Compose and Firebase](https://getstream.io/blog/server-driven-compose-firebase/)

## Tech stack & Open-source libraries

- Minimum SDK level 21.
- [Kotlin](https://kotlinlang.org/) based, utilizing [Coroutines](https://github.com/Kotlin/kotlinx.coroutines) + [Flow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/) for asynchronous operations.
- Jetpack Libraries:
- Jetpack Compose: Android’s modern toolkit for declarative UI development.
- Lifecycle: Observes Android lifecycles and manages UI states upon lifecycle changes.
- ViewModel: Manages UI-related data and is lifecycle-aware, ensuring data survival through configuration changes.
- Navigation: Facilitates screen navigation, complemented by [Hilt Navigation Compose](https://developer.android.com/jetpack/compose/libraries#hilt) for dependency injection.
- [Hilt](https://dagger.dev/hilt/): Facilitates dependency injection.
- Architecture:
- MVVM Architecture (View - ViewModel - Model): Facilitates separation of concerns and promotes maintainability.
- Repository Pattern: Acts as a mediator between different data sources and the application's business logic.
- [Firebase Android KTX](https://github.com/skydoves/firebase-android-ktx): Kotlin & Compose-friendly Firebase extensions designed to help you focus on your business logic.
- [Retrofit2 & OkHttp3](https://github.com/square/retrofit): Constructs REST APIs and facilitates paging network data retrieval.
- [ksp](https://github.com/google/ksp): Kotlin Symbol Processing API for code generation and analysis.
- [Landscapist Glide](https://github.com/skydoves/landscapist#glide), [animation](https://github.com/skydoves/landscapist#animation), [placeholder](https://github.com/skydoves/landscapist#placeholder): A pluggable, highly optimized Jetpack Compose and Kotlin Multiplatform image loading library that fetches and displays network images with Glide, Coil, and Fresco.

## Runing This Project on Your Side

You can run this project on your side following the guidelines below:

1. First things first, download the following JSON file on your local PC: [Gist: JSON demo for Timeline UI](https://gist.github.com/skydoves/16267ebe987c6246d917814440f03aac).

2. Following the [Firebase setup guidelines](https://firebase.google.com/docs/android/setup), download the **google-services.json** and place it into the `app` directory on this project.

3. Next, set up the [Firebase Realtime Database](https://firebase.google.com/docs/database) in your Firebase dashboard. Once that's done, you can import the JSON file like the image below:

![import](figure/import-json.png)

4. Next, create a file named `secrets.properties` in the root directory of this project, and copy & paste your Realtime Database URL into it, as shown in the example below:

![import](figure/db-url.png)

```
REALTIME_DATABASE_URL=https://server-driven-compose-default-rtdb.asia-southeast1.firebasedatabase.app/
```

5. Build the project.

## Architecture

**Server Driven Compose** fetches data from Firebase Realtime Database and makes it an observable flow in the data layer. The presentation layer then takes this data and assembles it into components, which are formatted to be consumed by UIs as composable functions.

![architecture](figure/arch.png)

### Component Design System

**Server Driven Compose** retrieves all rendering information from the backend (Firebase Realtime Database), allowing the client to focus solely on consuming the layout details. This approach lets you concentrate on "how to do (rendering)" rather than "what to do," a decision typically made by the product manager.

The code below shows how the main (timeline) screen is implemented in Jetpack Compose, showcasing its simplicity. It observes the UI component information from the backend server and consumes it according to the pre-built component design system. This makes the screen implementation very passive, allowing you to focus on how each component is rendered rather than deciding what to render.

```kotlin
Column(
modifier = Modifier
.background(ServerDrivenTheme.colors.background)
.fillMaxSize()
.padding(12.dp)
.verticalScroll(state = rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
timelineUi.components.forEach { uiComponent ->
uiComponent.Consume(
version = timelineUi.version,
navigator = { clickedComponent ->
navigateToDetails.invoke(clickedComponent, timelineUi.version)
}
)
}
}
```

### Component Versioning

**Server Driven Compose** demonstrates a versioning system for each component and how to synchronize them with the application in real-time.

### Design Patterns

**Server Driven Compose** adheres to the MVVM architecture and implements the Repository pattern, aligning with [Google's official architecture guidance](https://developer.android.com/topic/architecture).

The architecture of **Server Driven Compose** is structured into two distinct layers: the UI layer and the data layer. Each layer fulfills specific roles and responsibilities, outlined as follows:

**Server Driven Compose** follows the principles outlined in the [Guide to app architecture](https://developer.android.com/topic/architecture), making it an exemplary demonstration of architectural concepts in practical application.

### Architecture Overview

![architecture](figure/figure1.png)

- Each layer adheres to the principles of [unidirectional event/data flow](https://developer.android.com/topic/architecture/ui-layer#udf): the UI layer sends user events to the data layer, and the data layer provides data streams to other layers.
- The data layer operates autonomously from other layers, maintaining purity without dependencies on external layers.

This loosely coupled architecture enhances component reusability and app scalability, facilitating seamless development and maintenance.

### UI Layer

![architecture](figure/figure2.png)

The UI layer encompasses UI elements responsible for configuring screens for user interaction, alongside the [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel), which manages app states and restores data during configuration changes.
- UI elements observe the data flow, ensuring synchronization with the underlying data layer.

## Modularization

**Server Driven Compose** adopted modularization strategies below:

- **Reusability**: Modulizing reusable codes properly enable opportunities for code sharing and limits code accessibility in other modules at the same time.
- **Parallel Building**: Each module can be run in parallel and it reduces the build time.
- **Strict visibility control**: Modules restrict to expose dedicated components and access to other layers, so it prevents they're being used outside the module
- **Decentralized focusing**: Each developer team can assign their dedicated module and they can focus on their own modules.

For more information, check out the [Guide to Android app modularization](https://developer.android.com/topic/modularization).

## Find this repository useful? :heart:
Support it by joining __[stargazers](https://github.com/skydoves/server-driven-compose/stargazers)__ for this repository. :star:

Also, __[follow me](https://github.com/skydoves)__ on GitHub for my next creations! 🀩

# License
```xml
Designed and developed by 2024 skydoves (Jaewoong Eum)

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

http://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.
```