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-ktandsupabase-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 tolocal.properties (never commit this file):
Client Initialization
The Supabase client is initialized using Dagger Hilt dependency injection:Authentication
Google OAuth Setup
Enable Google Provider in Supabase
Navigate to your Supabase project → Authentication → Providers → Google and enable it.
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).Authentication Flow
Divvy supports two authentication methods:- Google OAuth (recommended)
- Phone OTP (SMS verification)
Session Management
The app monitors authentication state using Supabase’ssessionStatus 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 informationgroups- Expense groupsgroup_members- Many-to-many relationship between users and groupsexpenses- Individual expensesexpense_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 memberget_my_groups_summary- Returns all groups for current user with balance infocreate_expense_with_splits- Atomically creates expense with all splitsupdate_expense_splits- Updates expense split amountsdelete_group_cascade- Deletes group and all related dataadd_group_member- Adds a user to a groupget_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
Create Supabase Project
Visit supabase.com and create a new project.
Get API Credentials
Navigate to Project Settings → API and copy:
- Project URL (e.g.,
https://xxxx.supabase.co) - Anon/Public key
Configure Authentication
Go to Authentication → Providers:
- Enable Google OAuth
- Add redirect URL:
com.example.divvy://auth - Optionally enable Phone (SMS) provider
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)
Set Row Level Security (RLS)
Enable RLS on all tables and create policies to ensure users can only access their own data.
Common Operations
Creating a Group
Adding Members to a Group
Observing Real-time Updates
Repositories expose reactiveFlow APIs for UI updates:
Troubleshooting
”SupabaseClient not initialised” Error
This occurs whenSUPABASE_URL or SUPABASE_ANON_KEY are missing from local.properties:
local.properties and rebuild.
Authentication Redirect Not Working
- Verify
com.example.divvy://authis added in Supabase Auth settings - Check that the scheme and host match in
NetworkModule.kt:31-32 - Ensure Custom Tabs are enabled:
defaultExternalAuthAction = ExternalAuthAction.CUSTOM_TABS
Database Query Errors
Enable debug logging by addingignoreUnknownKeys = true to JSON configuration: