Skip to main content

Overview

Divvy uses Supabase as its backend infrastructure, providing both authentication (via GoTrue) and a PostgreSQL database (via Postgrest). This integration handles user authentication with Google OAuth, stores user profiles, manages expense groups, and tracks all financial transactions.

Key Features

  • Authentication: Google OAuth sign-in with custom redirect URLs
  • Database: PostgreSQL with real-time capabilities
  • Client Library: Supabase Kotlin SDK (supabase-postgrest-kt and supabase-gotrue-kt)
  • Type Safety: Serializable Kotlin data classes for all database operations

Dependencies

Divvy uses the Supabase BOM (Bill of Materials) for version management:

Configuration

Environment Variables

Add your Supabase credentials to local.properties (never commit this file):
Never commit local.properties - this file should be in your .gitignore. The Supabase anon key is safe to use in client applications but should still be kept out of version control.
These values are read at build time and injected as BuildConfig fields:

Client Initialization

The Supabase client is initialized using Dagger Hilt dependency injection:

Authentication

Google OAuth Setup

1

Enable Google Provider in Supabase

Navigate to your Supabase project → Authentication → Providers → Google and enable it.
2

Configure Redirect URL

Add com.example.divvy://auth as a redirect URL in your Supabase Auth settings.This custom URL scheme is configured in the Supabase client (see NetworkModule.kt:31-32).
3

Get Google OAuth Credentials

Follow Supabase’s guide to obtain Google OAuth client ID and secret.

Authentication Flow

Divvy supports two authentication methods:
  1. Google OAuth (recommended)
  2. Phone OTP (SMS verification)

Session Management

The app monitors authentication state using Supabase’s sessionStatus flow:

Database Schema

While the SQL schema is managed in your Supabase project, here are the key tables used by Divvy:

Core Tables

  • profiles - User profile information
  • groups - Expense groups
  • group_members - Many-to-many relationship between users and groups
  • expenses - Individual expenses
  • expense_splits - How expenses are split among group members

Views

  • group_expenses_with_splits - Denormalized view of expenses with split information

Stored Procedures (RPC)

Divvy uses several PostgreSQL functions for complex operations:
  • create_group_with_owner - Creates a group and adds creator as first member
  • get_my_groups_summary - Returns all groups for current user with balance info
  • create_expense_with_splits - Atomically creates expense with all splits
  • update_expense_splits - Updates expense split amounts
  • delete_group_cascade - Deletes group and all related data
  • add_group_member - Adds a user to a group
  • get_global_activity_feed - Returns activity feed for user

Repository Pattern

Divvy uses repository classes to abstract database operations:

Data Models

All database models use @Serializable and @SerialName annotations:
The @SerialName annotation maps Kotlin’s camelCase property names to PostgreSQL’s snake_case column names.

Setting Up a New Supabase Project

1

Create Supabase Project

Visit supabase.com and create a new project.
2

Get API Credentials

Navigate to Project Settings → API and copy:
  • Project URL (e.g., https://xxxx.supabase.co)
  • Anon/Public key
3

Configure Authentication

Go to Authentication → Providers:
  • Enable Google OAuth
  • Add redirect URL: com.example.divvy://auth
  • Optionally enable Phone (SMS) provider
4

Create Database Schema

Create the necessary tables, views, and RPC functions. Key tables:
  • profiles (id, first_name, last_name, email, phone, auth_method, phone_verified)
  • groups (id, name, icon, created_by, created_at)
  • group_members (group_id, user_id, joined_at)
  • expenses (id, group_id, merchant, amount_cents, split_method, currency, paid_by_user_id, created_at)
  • expense_splits (id, expense_id, user_id, amount_cents, is_covered_by)
5

Set Row Level Security (RLS)

Enable RLS on all tables and create policies to ensure users can only access their own data.
6

Add to local.properties

Common Operations

Creating a Group

Adding Members to a Group

Observing Real-time Updates

Repositories expose reactive Flow APIs for UI updates:

Troubleshooting

”SupabaseClient not initialised” Error

This occurs when SUPABASE_URL or SUPABASE_ANON_KEY are missing from local.properties:
Solution: Add both variables to local.properties and rebuild.

Authentication Redirect Not Working

  1. Verify com.example.divvy://auth is added in Supabase Auth settings
  2. Check that the scheme and host match in NetworkModule.kt:31-32
  3. Ensure Custom Tabs are enabled: defaultExternalAuthAction = ExternalAuthAction.CUSTOM_TABS

Database Query Errors

Enable debug logging by adding ignoreUnknownKeys = true to JSON configuration: