An iOS-native trash sorting app with on-device AI, Arena gameplay, and community-driven sustainability loops.
Smart Sort is a native iOS app that helps users identify trash categories with on-device AI, then keeps them engaged through Arena challenges, community events, leaderboards, and feedback-driven data improvement.
The project combines:
- On-device classification with CoreML
- A custom SwiftUI design system (
TrashTheme) - Supabase-backed auth, RPC, storage, and realtime flows
- Game loops for repeat engagement
- Community tooling for local sustainability participation
- Uses the camera to identify an item locally
- Runs blur and face checks before feedback upload
- Supports correction flows that feed a quiz-candidate pipeline
- Verify rewards require a linked email or phone
- Classic, Speed Sort, Streak, Daily Challenge, and Duel
- Solo modes use server-verified sessions and server-side answer validation
- Duel uses backend validation plus realtime synchronization
- Quiz images are served from Supabase Storage
- Arena rewards are only credited to linked accounts
- Browse and join communities by location
- Create and join events
- Support community admin tools and moderation flows
- Credits, achievements, badges, and leaderboards
- Friend and community engagement loops
| Layer | Tech |
|---|---|
| App | SwiftUI |
| ML | CoreML (MobileCLIPImage.mlpackage) |
| Backend | Supabase Auth / Postgres / RPC / Storage / Realtime |
| Package manager | Swift Package Manager |
| Design system | TrashTheme + shared primitives |
Smart Sort/
├── App/
├── Models/
├── Services/
├── Theme/
├── Views/
│ ├── Verify/
│ ├── Arena/
│ ├── Community/
│ ├── Leaderboard/
│ ├── Account/
│ ├── Auth/
│ ├── Admin/
│ └── Shared/
└── trash_knowledge.json
supabase/
└── migrations/
scripts/
├── check_backend_contracts.sh
├── manage_app_admin_migration.sh
└── migrate_arena_quiz_images.sh
docs/
├── ARCHITECTURE.md
└── UI_GUIDELINES.md
- Xcode 16+
- A configured Supabase project
- Committed
AppConfig.swiftwith public Supabase client config MobileCLIPImage.mlpackagepresent inSmart Sort/
xcodebuild -project "Smart Sort.xcodeproj" \
-scheme "Smart Sort" \
-destination 'platform=iOS Simulator,name=iPhone 17' \
buildxcodebuild -project "Smart Sort.xcodeproj" \
-scheme "Smart Sort" \
-destination 'generic/platform=iOS' \
buildApply migrations:
supabase db push --linked --yesCheck RPC drift and direct table access:
scripts/check_backend_contracts.shBootstrap the first app reviewer:
scripts/manage_app_admin_migration.sh grant <user_uuid>
supabase db push --linked --include-all --yes- Arena solo modes are server-verified
- Arena and Verify rewards require a linked account
- Duel stale challenges are expired consistently across gameplay RPCs
- Duel ready/finished state is persisted server-side for reconnect recovery
- Recoverable Arena quiz images were migrated off third-party dead links into Supabase Storage
- Correctly confirmed Verify photos can enter
quiz_question_candidates - Face-containing photos are never uploaded as feedback
- Feedback images are now private and served via signed URLs
app_adminscan review and publish quiz candidates through the in-appQuiz Reviewflowscripts/check_backend_contracts.shnow checks both local RPC alignment and linked remote legacy drift when Supabase access is available
The app uses a shared TrashTheme system with tokenized spacing, sizing, and typography roles.
Current baseline metrics:
- Minimum hit target:
44pt - Button/input height:
52pt - Standard row height:
52pt - Compact control height:
32pt - Corner radii:
12 / 16 / 20 / pill - Layout rhythm:
16ptscreen inset,24ptsection spacing,12ptelement spacing - Grid rule:
8ptprimary grid with4ptcompact internal adjustments
Use shared primitives before writing feature-local styling:
TrashButtonTrashPillTrashIconButtonTrashForm*TrashCard/.surfaceCard(...)TrashSegmentedControl
Text hierarchy should use the shared roles from TrashTheme:
displaytitleheadlinesubheadlinebodycaptionbuttonkicker
See UI Guidelines for the full rules.
- App-owned SQL logic lives in
supabase/migrations/ - UI tokens and interaction metrics live in
TrashTheme - Shared component primitives should be extended before creating one-off visual systems
- App shell, state composition, and service boundaries are documented in Architecture
Smart Sort/Services/AppConfig.swiftis intentionally committed because it only contains the public Supabase URL and publishable anon key.- Do not place service-role keys, database passwords, or other private credentials in
AppConfig.swift. MobileCLIPImage.mlpackageis tracked in git and treated as a required app asset.
This work is licensed under CC BY-SA 4.0.