This is a Flutter app I built to demonstrate how I structure mobile projects. It features a complete authentication flow — extracted from a project I'm currently working on — following Clean Architecture principles with Riverpod and Supabase.
The app has two screens accessible via bottom navigation:
- Home — shows login status. When logged out, a button opens the auth modal. When logged in, it displays the user's email and a logout button.
- Profile — a theme toggle with an animated sun/moon widget to switch between light and dark mode.
All authentication happens inside a Wolt Modal Sheet bottom sheet with multiple pages:
- Login — email & password
- Sign-Up — username, email, password with an animated real-time password rules checklist
- Email Verification — 6-digit OTP input (via Pinput)
- Password Reset — request reset, verify token, set new password
The project follows Clean Architecture with a feature-first folder structure:
lib/
├── core/ # Themes, error handling, utilities
│ ├── errors/ # Failure types, Supabase error mapper, user-facing messages
│ ├── theme/ # Light/Dark themes, color schemes, theme extensions
│ └── utils/ # Either type, spacing widget, delayed notifier mixin
├── features/
│ ├── auth/
│ │ ├── data/ # Supabase data source, repository implementation, user model
│ │ ├── domain/ # User entity, repository interface, 8 use cases, validators
│ │ └── presentation/ # Modal sheet pages, forms, providers & auth notifier
│ ├── home/ # Home screen
│ └── profile/ # Profile screen with theme toggle
└── routing/ # GoRouter with bottom navigation (StatefulShellRoute)
Each auth operation (login, sign-up, verify email, reset password, etc.) has its own use case class. State is managed through a central AuthNotifier with sealed state classes, and UI events (errors, info messages) flow through a separate event provider.
- Functional error handling with a custom
Eithertype — no thrown exceptions in the domain layer - Animated password checklist that shows/hides validation rules in real-time as you type
- Rate-limit handling for verification code resends, with cooldown extracted from error responses
- Delayed state transitions via a mixin that ensures loading indicators are visible for a minimum duration
- Custom theme extensions for Wolt Modal Sheet and Pinput styling
- Flutter & Dart
- Riverpod 3 — state management
- Supabase — authentication backend
- GoRouter — routing & bottom navigation
- Wolt Modal Sheet — multi-page auth bottom sheet
- Pinput — OTP verification input
Flutter SDK required.
flutter pub get
flutter runCreate a .env file in the project root with your Supabase credentials:
SUPABASE_URL=your_supabase_url
SUPABASE_KEY=your_supabase_anon_key
For the email verification and password reset flows to work, you'll need to configure an SMTP server in your Supabase project under Authentication → Email → SMTP Settings.
Created by Jan Pfrommer


