A modern Android app for discovering, collecting, and sharing inspirational quotes. Built with Jetpack Compose, MVVM architecture, and powered by Supabase.
- Quote Library — Browse quotes across Motivation, Love, Success, Wisdom, and Humor. Includes search and a Quote of the Day.
- Personalization — Save favorites, create collections, and customize theme, font size, and accent color.
- Sharing — Share quotes as text or generate beautiful quote card images for social media.
- Notifications & Widgets — Daily quote notifications and a home screen widget.
- User Account — Secure Supabase Auth with profile support and cross-device sync.
- Offline Support — Local Room database with caching, pagination, and network monitoring.
![]() Home |
![]() Login |
![]() Sign Up |
![]() Forgot Password |
![]() Quotes |
![]() Search |
![]() Favorites |
![]() Added to Favorites |
![]() Collections |
![]() Collection Detail |
![]() Profile |
![]() Settings |
![]() Widget |
| Category | Tools |
|---|---|
| UI | Jetpack Compose, Material 3, Navigation |
| Architecture | MVVM + Clean Architecture, Hilt |
| Backend | Supabase (Auth, DB), Ktor |
| Local | Room, DataStore, Paging 3 |
| Background | WorkManager, Glance (Widgets) |
| Utilities | Coil, Coroutines, Timber |
Clean Architecture with MVVM across three layers:
UI Layer (Screens, ViewModels, Composables)
↓
Domain Layer (Models, Use Cases)
↓
Data Layer (Local, Remote, Repositories)
Navigation:
Welcome → Login / SignUp → Home
↓
Bottom Nav: Home | Search | Favorites | Collections | Profile
- Tool: Stitch — View Design Files
- System: Material Design 3
- Fonts: DM Sans, Lora, Merriweather
- Themes: Full Dark / Light mode with custom accent colors
- Android Studio Hedgehog (2023.1.1)+
- JDK 17+, Android SDK API 34
- Supabase free account
git clone https://github.com/pratish444/QuoteVault
cd QuoteVaultCopy and edit local.properties:
cp local.properties.example local.propertiesSUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key-here
⚠️ Never commitlocal.properties— it's in.gitignore.
Run in Supabase SQL Editor:
create extension if not exists "uuid-ossp";
create table user_profiles (
id uuid primary key references auth.users(id) on delete cascade,
display_name text,
avatar_url text,
created_at timestamp with time zone default timezone('utc'::text, now())
);
create table quotes (
id uuid primary key default uuid_generate_v4(),
text text not null,
author text not null,
category text not null,
source text,
created_at timestamp with time zone default timezone('utc'::text, now())
);
create table user_favorites (
id uuid primary key default uuid_generate_v4(),
user_id uuid references user_profiles(id) on delete cascade,
quote_id uuid references quotes(id) on delete cascade,
created_at timestamp with time zone default timezone('utc'::text, now()),
unique(user_id, quote_id)
);
create table collections (
id uuid primary key default uuid_generate_v4(),
user_id uuid references user_profiles(id) on delete cascade,
name text not null,
description text,
color text not null,
icon text not null,
created_at timestamp with time zone default timezone('utc'::text, now())
);
create table collection_quotes (
collection_id uuid references collections(id) on delete cascade,
quote_id uuid references quotes(id) on delete cascade,
created_at timestamp with time zone default timezone('utc'::text, now()),
primary key (collection_id, quote_id)
);
create table daily_quotes (
date date primary key,
quote_id uuid references quotes(id),
created_at timestamp with time zone default timezone('utc'::text, now())
);
create index idx_quotes_category on quotes(category);
create index idx_quotes_author on quotes(author);
create index idx_favorites_user on user_favorites(user_id);
create index idx_collections_user on collections(user_id);alter table user_profiles enable row level security;
alter table user_favorites enable row level security;
alter table collections enable row level security;
alter table collection_quotes enable row level security;
-- Profiles
create policy "Users can view own profile" on user_profiles for select using (auth.uid() = id);
create policy "Users can update own profile" on user_profiles for update using (auth.uid() = id);
-- Favorites
create policy "Users can view own favorites" on user_favorites for select using (auth.uid() = user_id);
create policy "Users can insert own favorites" on user_favorites for insert with check (auth.uid() = user_id);
create policy "Users can delete own favorites" on user_favorites for delete using (auth.uid() = user_id);
-- Collections
create policy "Users can view own collections" on collections for select using (auth.uid() = user_id);
create policy "Users can insert own collections" on collections for insert with check (auth.uid() = user_id);
create policy "Users can update own collections" on collections for update using (auth.uid() = user_id);
create policy "Users can delete own collections" on collections for delete using (auth.uid() = user_id);
-- Public read
create policy "Public can view quotes" on quotes for select using (true);
create policy "Public can view daily quotes" on daily_quotes for select using (true);
-- Auto-create profile on signup
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.user_profiles (id) values (new.id);
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();./gradlew clean build
./gradlew installDebugOr use Run → Run 'app' in Android Studio.












