A personal inventory tracker for everyday essentials — groceries, kitchen supplies, and more. Know what you have, what's running low, and what needs restocking at a glance.
Hubs can be shared with others: owners can invite users by searching their username (GitHub-style) and assigning them as editors or viewers.
| Layer | Tech |
|---|---|
| Language | Kotlin |
| UI | Jetpack Compose · Material 3 |
| Navigation | Jetpack Navigation 3 |
| DI | Koin |
| Architecture | MVI · feature modularization |
| Backend / Auth | Supabase (Auth · PostgREST · Realtime · Storage) |
| Networking | Ktor (CIO engine) |
| Local cache | Room · Paging 3 |
| Persistence | DataStore |
| Image loading | Coil 3 |
| CI | GitHub Actions |
:app — entry point, nav host, bottom nav
app/src/main/java/com/skewnexus/trackhub/
├── MainActivity.kt
├── navigation/
│ ├── AppNavHost.kt
│ ├── components/
│ │ ├── BottomDestination.kt
│ │ └── BottomNavigationBar.kt
│ ├── graphs/
│ │ ├── AuthGraph.kt
│ │ ├── OwnedHubsGraph.kt
│ │ ├── SharedHubsGraph.kt
│ │ ├── NotificationsGraph.kt
│ │ └── MenuGraph.kt
│ └── utils/
│ └── SessionDestinationHandler.kt
└── di/
└── AppModule.kt
:core:core-ui — shared Compose components, theme, base ViewModel
core/core-ui/src/main/java/com/greenvenom/core_ui/
├── components/
│ ├── bars/ (TopAppBar, AppBarSearchBar)
│ ├── buttons/ (CustomButton, FilterDropdown, FloatingButton, …)
│ ├── dialogs/ (ErrorDialog, LoadingDialog, SuccessDialog, …)
│ └── text/ (CustomTextField, CustomMultilineTextField)
├── presentation/
│ ├── BaseScreen.kt
│ ├── BaseViewModel.kt
│ └── ScaffoldViewModel.kt
└── theme/ (Color, Type, Theme)
:core:core-util — input validation, locale, phone formatting
core/core-util/src/main/java/com/greenvenom/core_util/
├── input/ (InputValidator, ValidationResult)
├── locale/ (LocaleManager, NormalizeDigits)
├── phone/ (PhoneNumberManager)
└── theme/ (ThemeManager)
:network:core-network — NetworkResult, error types, Supabase call wrappers
network/core-network/src/main/java/com/greenvenom/core_network/
├── data/ (NetworkResult, NetworkError, ErrorType)
├── domain/ (SessionRepository, SessionDestination)
└── supabase/utils/ (SupabaseCall, SupabaseRealtimeCall)
:network:feat-network — Supabase client factory, session repository
network/feat-network/src/main/java/com/trackhub/feat_network/
├── data/
│ ├── ClientFactory.kt
│ └── repository/SupabaseSessionRepository.kt
└── di/NetworkFeatureModule.kt
:navigation:core-navigation — navigation contracts and state
navigation/core-navigation/src/main/java/com/greenvenom/core_navigation/
├── domain/
│ ├── NavigationState.kt
│ └── repos/NavigationRepository.kt
└── routes/ (Destination, DestinationType)
:navigation:feat-navigation — AppNavigator implementation
navigation/feat-navigation/src/main/java/com/trackhub/feat_navigation/
├── data/
│ ├── AppNavigator.kt
│ └── repos/NavigationRepositoryImpl.kt
└── di/NavigationModule.kt
:auth:core-auth — auth DTOs, session state contracts
auth/core-auth/src/main/java/com/greenvenom/core_auth/
├── data/dto/request/ (LoginRequest, RegisterRequest, ResetPasswordRequest, …)
└── data/repository/ (EmailState, EmailStateRepository)
:auth:feat-auth — login, register, OTP, reset password screens
auth/feat-auth/src/main/java/com/greenvenom/feat_auth/
├── data/ (AuthSupabaseDataSource, AuthRepositoryImpl)
├── domain/ (AuthRepository, AuthRemoteDataSource)
└── presentation/
├── login/ (LoginScreen, LoginViewModel)
├── register/ (RegisterScreen, RegisterViewModel)
├── otp/ (OtpScreen, OtpViewModel)
├── reset_password/(VerifyEmailScreen, NewPasswordScreen)
└── splash/ (SplashScreen)
:hub:core-hub — hub/item models, DAOs, remote DTOs, mappers
hub/core-hub/src/main/java/com/trackhub/core_hub/
├── data/
│ ├── cache/ (HubDao, ItemDao, HubEntity, ItemEntity, ItemFts)
│ ├── mappers/ (HubMapper, ItemMapper, HubMemberMapper, …)
│ └── remote/dto/ (request & response DTOs)
└── domain/
├── models/ (Hub, Item, HubMember, UserSearch)
└── enums/ (HubRole, BaseUnit, InvitationStatus, MemberStatus)
:hub:feat-hub — hub list, hub details, invite flow
hub/feat-hub/src/main/java/com/trackhub/feat_hub/
├── data/ (SupabaseHubDataSource, HubRoomDataSource, repos)
├── domain/ (HubRepository, HubInvitationsRepository)
└── presentation/
├── hub_list/ (HubListScreen, HubListViewModel)
├── hub_details/ (HubDetailsScreen, HubDetailsViewModel)
└── components/ (HubListCard, ItemListCard, InviteUserDialog, ItemDetailsDialog, …)
:local:core-local — Room type converters
local/core-local/src/main/java/com/trackhub/core_local/
└── utils/ListStringConverters.kt
:local:feat-local — database definition, DI
local/feat-local/src/main/java/com/trackhub/feat_local/
├── data/db/TrackHubDatabase.kt
└── di/LocalModule.kt
:menu:core-menu — profile model, DAO
menu/core-menu/src/main/java/com/trackhub/core_menu/
├── data/ (ProfileDao, ProfileEntity, ProfileDto)
└── domain/Profile.kt
:menu:feat-menu — settings / menu screen
menu/feat-menu/src/main/java/com/trackhub/feat_menu/
├── data/ (MenuSupabaseDataSource, MenuRoomDataSource, MenuRepositoryImpl)
├── domain/ (MenuRepository)
└── presentation/
├── MenuScreen.kt
├── MenuViewModel.kt
└── components/ (AccountHeader, SettingCard, AppVersionItem)
:notifications:core-notifications — invitation models, mappers
notifications/core-notifications/src/main/java/com/trackhub/core_notifications/
├── data/ (mappers, remote DTOs)
└── domain/models/ (HubInvitation, InvitationAcceptance)
:notifications:feat-notifications — notifications screen, invitation accept/decline
notifications/feat-notifications/src/main/java/com/trackhub/feat_notifications/
├── data/ (SupabaseHubInvitations, NotificationsRepositoryImpl)
├── domain/ (NotificationsRepository, HubInvitationsDataSource)
└── presentation/
├── screens/NotificationsScreen.kt
├── viewmodel/NotificationsViewModel.kt
└── components/HubInvitationItem.kt