Skip to content

arrazyfathan/server-driven-ui

Repository files navigation

Server-Driven UI on Android with Jetpack Compose

This repository is a sample Android application that renders a home/news-style screen from server-provided UI data stored in Firebase Firestore. The goal is to demonstrate a simple Server-Driven UI (SDUI) approach in a modern Android stack using Jetpack Compose, Hilt, Kotlin Flow, and Firestore snapshot listeners.

Slide deck: https://speakerdeck.com/arrazyfathan/building-dynamic-interfaces-implementing-server-driven-ui-on-android

What This Project Demonstrates

  • A Compose screen whose content and presentation values are driven by Firestore documents
  • Real-time UI updates via Firestore listeners and Flow
  • A lightweight layered architecture: presentation -> domain -> data
  • Dependency injection with Hilt
  • A modern Android toolchain based on AGP 9.x, Gradle 9.x, Java 17, and Compose

Tech Stack

  • Kotlin
  • Jetpack Compose
  • Material 3
  • Firebase Firestore
  • Hilt
  • Kotlin Flow / Coroutines
  • Room
  • Coil
  • Navigation Compose
  • KSP

Project Structure

The project currently uses a single app module with the following package layout:

app/src/main/java/com/arrazyfathan/serverdrivenui
├── data
│   ├── datasource
│   └── datasource/remote/firestore
├── di
├── domain
├── presenstation
└── utils

Notes:

  • The package name presenstation is spelled that way in the current codebase and is not a typo in this README.
  • The app uses Hilt entry points from App.kt and MainActivity.kt.

Architecture Overview

The runtime flow is straightforward:

  1. MainActivity sets Compose content and obtains HomeViewModel.
  2. HomeViewModel requests five UI sections from the repository:
    • top app bar
    • featured image
    • article content
    • card links
    • footer
  3. RepositoryImpl bridges Firestore result types into app-level Resources.
  4. FirestoreDatasourceImpl listens to Firestore documents using addSnapshotListener(...).
  5. Compose collects StateFlow values and renders the UI accordingly.

Relevant files:

Firestore Data Model

The app reads from the home_screen collection and expects the following document IDs:

  • top_app_bar
  • featured_image
  • content
  • card_links
  • footer

These constants are defined in Constants.kt.

Each document maps to a Kotlin model under data/datasource/model. The app also includes fallback/default content for some visual sections when server data is absent.

Requirements

To build this project as it exists today, use:

  • Android Studio with recent AGP 9.x support
  • JDK 17
  • Android SDK Platform 37 installed
  • Gradle 9.5.0
  • Android Gradle Plugin 9.2.1

The app module is currently configured with:

  • minSdk = 24
  • targetSdk = 37
  • compileSdk = 37

Setup

1. Clone the repository

git clone <your-repo-url>
cd server-driven-ui

2. Install required Android SDK components

At minimum:

sdkmanager "platforms;android-37" "build-tools;37.0.0"

3. Configure Java 17

Ensure Gradle and Android Studio are using JDK 17.

4. Firebase setup

This project expects Firebase configuration through google-services.json in the app/ directory.

Checklist:

  • Create a Firebase project
  • Add an Android app with package name com.arrazyfathan.serverdrivenui
  • Download google-services.json
  • Place it at: app/google-services.json
  • Enable Cloud Firestore
  • Create the expected home_screen documents

5. Review signing config

The current release signing configuration in app/build.gradle.kts points to a local keystore path and sample credentials. Replace or remove it for your own environment before producing a release build.

Running the App

From Android Studio:

  • Sync Gradle
  • Select a device or emulator
  • Run the app configuration

From the command line:

./gradlew :app:assembleDebug

Install on a connected device:

./gradlew :app:installDebug

Useful Gradle Commands

./gradlew help
./gradlew :app:assembleDebug
./gradlew :app:installDebug
./gradlew build --dry-run

Current Build Notes

  • Configuration cache is enabled in gradle.properties.
  • The project has already been migrated to:
    • Gradle 9.5.0
    • AGP 9.2.1
    • Kotlin Compose plugin 2.3.21
  • Firebase KTX migration has been updated in code to use APIs from the main modules.

UI Behavior

The sample screen includes:

  • a top app bar
  • a featured image and title block
  • author and date metadata
  • expandable article body text
  • a footer that can render either:
    • a card link component
    • a carousel component

The footer behavior is controlled by Firestore data, which makes it the clearest example of the server-driven approach in this sample.

Dependency Injection

Hilt modules are defined in:

They provide:

  • FirebaseFirestore
  • FirestoreDatasource
  • Repository

Limitations

This is a sample project, so a few tradeoffs are intentional or still rough:

  • The SDUI model is section-based rather than a generalized component renderer
  • The project is single-module
  • Some fallback content is hardcoded in the client
  • The current release signing config is sample/local-machine specific
  • There is no formal test suite documenting the server contract yet

Suggested Next Improvements

  • Move dependency versions into a version catalog
  • Add screenshots or a GIF to the README
  • Document the Firestore document schema field-by-field
  • Add tests for repository and ViewModel behavior
  • Extract a more generic server-driven component model
  • Clean up naming inconsistencies such as presenstation

License

No license file is currently included in this repository. If you intend to share or publish it, add an explicit license.

About

Explore the power of Server-Driven UI (SDUI) on Android with Jetpack Compose. This GitHub repository provides a concise example of how to implement dynamic and customizable user interfaces using Composables.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages