Skip to main content

Overview

This guide walks you through setting up a complete development environment for Divvy, including building from the command line, configuring Supabase authentication, and understanding the project structure.

Prerequisites

Ensure you have the following installed:
  • Android Studio: Latest stable version (Jellyfish or newer recommended)
  • Java Development Kit (JDK): Version 8 or higher
  • Gradle: Included with Android Studio (no separate installation needed)
  • Git: For cloning the repository
  • Supabase account: For backend and authentication
Divvy targets Android API level 26 (Android 8.0) and above, with a compile SDK of 36.

Installation steps

1

Clone the repository

Clone the Divvy repository and navigate to the project directory:
git clone https://github.com/your-org/divvy.git
cd divvy
2

Configure local.properties

Create a local.properties file in the project root directory:
touch local.properties
Add your Supabase credentials to this file:
local.properties
SUPABASE_URL=https://xxxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
Important: Never commit local.properties to version control. This file should only exist on your local machine and should be added to .gitignore.

How credentials are used

The build system reads these properties and injects them as BuildConfig fields that are accessible at runtime:
app/build.gradle.kts
val localProperties = Properties().apply {
    val propsFile = rootProject.file("local.properties")
    if (propsFile.exists()) {
        propsFile.inputStream().use { load(it) }
    }
}
val supabaseUrl = localProperties.getProperty("SUPABASE_URL", "")
val supabaseAnonKey = localProperties.getProperty("SUPABASE_ANON_KEY", "")

android {
    buildTypes {
        all {
            buildConfigField("String", "SUPABASE_URL", "\"$supabaseUrl\"")
            buildConfigField("String", "SUPABASE_ANON_KEY", "\"$supabaseAnonKey\"")
        }
    }
}
The Supabase client is initialized using these values in the SupabaseClientProvider:
app/src/main/java/com/example/divvy/backend/SupabaseClientProvider.kt
object SupabaseClientProvider {
    @Volatile
    private var clientInstance: SupabaseClient? = null

    val client: SupabaseClient
        get() = clientInstance
            ?: error("SupabaseClient not initialised")

    fun setClient(client: SupabaseClient) {
        clientInstance = client
    }
}
3

Set up Supabase Authentication

Configure Google authentication in your Supabase dashboard:
  1. Go to your Supabase Dashboard
  2. Select your project
  3. Navigate to Authentication > Providers
  4. Enable the Google provider
  5. Add com.example.divvy://auth to the Redirect URLs list

How authentication works

Divvy uses Supabase GoTrue for authentication. The auth flow is handled by AuthActivity:
app/src/main/java/com/example/divvy/AuthActivity.kt
@AndroidEntryPoint
class AuthActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (SupabaseClientProvider.isConfigured()) {
            SupabaseClientProvider.client.handleDeeplinks(intent)
        }
        setContent {
            DivvyTheme {
                AuthNav(
                    onAuthenticated = {
                        startActivity(Intent(this, MainActivity::class.java))
                        finish()
                    }
                )
            }
        }
    }
}
After successful authentication, the user is redirected to MainActivity.
4

Sync Gradle

Open the project in Android Studio:
  1. Launch Android Studio
  2. Click File > Open
  3. Select the divvy directory
  4. Click OK
  5. Wait for Gradle to sync automatically
If Gradle doesn’t sync automatically, click File > Sync Project with Gradle Files.
The first sync may take several minutes as Gradle downloads dependencies including Jetpack Compose, Supabase SDK, CameraX, and Hilt.
5

Build from the command line

You can build the app without Android Studio using Gradle:
./gradlew :app:assembleDebug
This creates a debug APK at:
app/build/outputs/apk/debug/app-debug.apk

Other useful Gradle commands

# Run tests
./gradlew test

# Run lint checks
./gradlew lint

# Clean build artifacts
./gradlew clean

# Build release APK (requires signing configuration)
./gradlew :app:assembleRelease
6

Run the app

Run the app on an emulator or physical device:

From Android Studio

  1. Select the app run configuration from the dropdown
  2. Choose your target device
  3. Click the Run button (or press Shift + F10)

From command line

# Install on connected device
./gradlew installDebug

# Install and launch
./gradlew installDebug
adb shell am start -n com.example.divvy/.AuthActivity

Project structure

Understanding the codebase organization:
divvy/
├── app/
│   ├── src/main/java/com/example/divvy/
│   │   ├── backend/           # Data repositories and Supabase client
│   │   ├── ui/                # Screens and navigation
│   │   │   ├── auth/          # Authentication screens
│   │   │   ├── groups/        # Group management
│   │   │   ├── expenses/      # Expense creation and viewing
│   │   │   ├── splitexpense/  # Expense splitting UI
│   │   │   ├── scanreceipt/   # Receipt scanning with CameraX
│   │   │   ├── home/          # Home feed and dashboard
│   │   │   └── theme/         # Material 3 theme configuration
│   │   ├── models/            # Domain models (Group, Expense, etc.)
│   │   ├── MainActivity.kt    # Main app entry point
│   │   └── AuthActivity.kt    # Authentication entry point
│   └── build.gradle.kts       # App-level build configuration
├── build.gradle.kts           # Project-level build configuration
└── local.properties           # Local environment variables (not committed)

Key files

  • app/build.gradle.kts: Defines dependencies, build types, and BuildConfig fields
  • backend/SupabaseClientProvider.kt: Singleton that provides the configured Supabase client
  • ui/MainScreen.kt: Root composable that sets up navigation and bottom bar
  • ui/navigation/AppNavHost.kt: Navigation graph for the app
  • models/: Data classes for Group, Expense, Split, and other domain objects

Development workflow

Once you have the app running, you can:
  1. Make code changes: Edit Kotlin files in Android Studio
  2. Hot reload: Press Ctrl + Shift + F9 to apply changes without restarting
  3. Debug: Set breakpoints and use Android Studio’s debugger
  4. View logs: Use Logcat to see runtime logs from the app

Dependencies

Divvy uses the following key dependencies:
  • Jetpack Compose: Modern declarative UI framework
  • Supabase Kotlin SDK: Backend and authentication (postgrest-kt, gotrue-kt)
  • Hilt: Dependency injection
  • CameraX: Camera functionality for receipt scanning
  • Coil: Image loading for user avatars
  • Navigation Compose: Type-safe navigation
  • Material 3: Material Design components
View the complete list in app/build.gradle.kts.

Optional configuration

Auth bypass (for testing)

You can bypass authentication during development by adding this to local.properties:
AUTH_BYPASS=true
This skips the login screen and goes directly to the main app:
app/src/main/java/com/example/divvy/AuthActivity.kt
if (FeatureFlags.AUTH_BYPASS) {
    startActivity(Intent(this, MainActivity::class.java))
    finish()
    return
}
Auth bypass should only be used for local development, never in production builds.

Troubleshooting

Gradle sync fails

If Gradle sync fails:
  1. Ensure local.properties exists and contains valid Supabase credentials
  2. Check that you’re using JDK 8 or higher
  3. Try File > Invalidate Caches > Invalidate and Restart
  4. Run ./gradlew clean and sync again

App crashes on launch

If the app crashes immediately:
  1. Check Logcat for error messages
  2. Verify your Supabase URL and anon key are correct
  3. Ensure you’ve enabled Google auth in Supabase dashboard
  4. Check that the redirect URL com.example.divvy://auth is configured

Camera not working

If receipt scanning doesn’t work:
  1. Grant camera permissions when prompted
  2. Test on a physical device (emulator cameras have limitations)
  3. Check that CameraX dependencies are properly installed

Next steps

Now that you have a complete development environment: