
Explore a scalable flutter community board app with supabase powered authentication, real-time posts, comments, likes, and notifications; learn event bus synchronization, debounce search, and infinite scrolling.
Explore event bus architecture for feature communication and a loose coupled state synchronization that reflects post creation, modification, deletion and profile updates, with a monorepo to boost reusable logic.
Identify the target audience and prerequisites for mastering scalable Flutter apps with Riverpod and Supabase, and outline the course structure around clean architecture, monorepo, and backend integration.
Learn to rapidly create data classes in Dart with the Dart Data Class Generator extension for VS Code, covering constructors, toString, copyWith, fromJSON, toJSON, and equality.
Explore flutter riverpod snippets and the freezed extension in VS Code, focusing on widget templates, provider creation, and pts and fromJson snippets for json_serializable templates.
Learn how Dart function types expose a call method, making functions and objects callable; use nullable functions with null checks, and implement callable classes to simplify clean architecture use cases.
Apply clean architecture to the three-tier design by separating UI, business logic, and repository with well-defined interfaces. See how entities and use cases define the domain layer for loose coupling.
Explore a 3-tier architecture that separates domain, use cases, and presentation, and see how Riverpod handles controller and presenter via input and output ports.
Learn how clean architecture separates the business domain from data access using a domain repository and data layer, with abstract data source interfaces for Postgres or MongoDB.
Discover how a monorepo enables scalable Flutter apps with clean architecture, Riverpod, and Supabase, and examine the community board's core, domain, and data layers.
Build a flutter monorepo with riverpod by creating core, domain, and data_supabase packages, structuring with barrel files, and defining a generic use case interface for consistent business logic.
Set up domain and data_supabase packages, configure local core dependencies, and enable json serialization with json_annotation and code generation via build_runner, plus static analysis and linting rules.
Configure analysis_options.yaml to enforce flutter lint rules, exclude generated and build files, tailor rules like ignore invalid_annotation_target, and enable prefer const constructors, final fields, and relative imports.
Set up riverpod_app by adding pubspec.yaml dependencies (flutter_riverpod, go_router, supabase_flutter, flutter_dotenv) and enable code generation with build_runner and riverpod_generator; use local core, domain, and data_supabase packages and configure .env.
Build a robust backend with Postgres and supabase by creating profiles, posts, comments, and likes, linking profiles to auth.users and using the SQL editor.
Learn why separating auth.users from public.profiles enhances security, data integrity, and flexibility, using a foreign-key cascade and row-level security to manage safe public profile data.
Design posts, comments, and likes schema with uuid keys and cascade deletes, and enforce security with grants and row-level security including author_id references to profiles and a unique like constraint.
Learn why store only avatar_url and image_url in the database, and use supabase storage for avatars and post-images to boost performance, cost, and scalability, with public buckets and rls.
Enable row level security for profiles; allow authenticated users to read all profiles and update only their own, using a performance-friendly auth.uid() check; insert and delete stay blocked by default.
Define who can view, create, modify, and delete posts using row level security (rls) policies on the posts table, with admin and user roles, and helper functions get_user_role and is_admin.
Implement row-level security for comments and likes tables, with select, insert, update, delete policies that allow authenticated users to act on their own records, while admins can delete any comment.
Create and wire the handle_new_user trigger function to automatically populate new user profiles when signups occur, using a security definer function and on_auth_user_created trigger in Postgres.
Implement a generic trigger_set_timestamp function and before update triggers on profiles, posts, and comments to auto-update updated_at, with notes on grants and before vs after triggers.
Create the update_comments_count function and the on_comment_change_update_post_comments_count trigger to auto adjust posts.comments_count when comments are inserted or deleted, using security definer and after trigger return null.
Implement the update_likes_count trigger and trigger function to auto-update posts.likes_count on likes changes. Build handle_like to toggle likes, returning a json object with the new like status and current count.
Define and use the update_user_profile function to update user profiles across public.profiles and auth.users, returns setof public.profiles, and enforce security with SECURITY DEFINER and per-user safeguards.
Grant service_role permissions by issuing sql statements to grant all on all tables and routines in the public schema, preparing for edge functions and server-side operations while supporting future scalability.
Develop a Riverpod-based todo app by implementing update and delete operations, handling transient failures with clearTransientFailure, and exposing derived providers for completed counts and filtered views.
Test and refine a scalable flutter todo app using riverpod and mutations, with add, edit, delete flows, state management, error handling, and responsive UI feedback.
Refactor the todo app to use Riverpod mutation for add, update, and delete operations, wiring three top-level mutations and syncing the UI with AsyncValue changes.
Refactor the todo list to use deleteTodoMutation with per-item id handling and tsx.get in the run function. Listen to MutationState changes to show snackbars on success or error.
Test the todo_mutation app by adding, editing, and deleting todos via AddTodoPage, and verify per-item mutation behavior. Observe error handling with mutation.run, ignore, and catchError, and observe Riverpod per-item listeners.
Explore safely showing a snack bar after unmount in a todo mutation app by handling the optimistic UI with a messenger before async delete, using try-catch and await in onPressed.
Explore why providers represent app state while mutations manage action lifecycles, using todoListProvider and addTodoMutation, updateTodoMutation, deleteTodoMutation to separate state from task life cycle.
Learn to build a login legacy app using riverpod and mutation, simulate remote login with an in-memory mock db, and refactor from a notifier to mutations.
Refactor the login flow into a login_mutation that directly calls AuthRepository via a mutation transaction, bypassing notifier and loginProvider. Explain mutation-driven design and clean architecture implications.
Explore non-void mutation types in riverpod, using type T to provide UI feedback via MutationState and MutationSuccess, with patterns like ref.listen and run function results.
Explore the authentication feature with signup, login, and logout, how the supabase backend issues JWTs for secure, persistent sessions, and how on_auth_user_created links auth.users to public.profiles.
Define core rules and tools in the core package to separate exceptions from failures for stable, user-friendly error handling in clean architecture, and establish a UseCase interface and NoParams.
craft a pure domain authentication layer with UserEntity, an AuthRepository interface, and signup, login, and logout use cases, decoupled from external technologies.
Learn how barrel files simplify imports while avoiding circular dependencies by importing specific files within a package, exporting only for external use, and following safe import practices to prevent crashes.
Implement the data layer by creating UserModel that extends UserEntity, converting Supabase user data and json into Dart objects via fromSupabaseUser and fromJson.
Define an abstract auth remote data source and implement it with Supabase. Expose signup, login, logout, and onAuthStateChanged while applying dependency inversion to allow swapping data sources and error handling.
Establish auth dependency injection in a Riverpod Flutter app by wiring a composition root with auth remote data source, repository, and use case providers through abstraction.
Explains how to implement login and signup using Riverpod 3 mutations, distinguishing action-centric mutations from state-centric auth controllers, and wiring them to use cases with presentation failure handling.
Build a routing backbone with the GoRouter package to display splash, login, signup, and authenticated pages, including post, post detail, post form, profile, and search pages.
Configure GoRouter with routes for splash, login, signup, post create, user detail, post detail, and post edit; implement bottom navigation with StatefulShellRoute indexedStack and error handling.
Connects login user interface to logic with a _submit function, autovalidate always, and runLogin via loginMutation, while handling loading and errors with Riverpod and snackbars.
Convert the login page into a consumer stateful signup page, add username and confirm password fields with validation, and wire the signup mutation and navigation between login and signup views.
Explore signup and login testing with Supabase authentication, configure email provider and confirm options, implement logout in my profile, and validate role changes via auth.users and raw_user_meta_data updates.
Implement the data layer's post retrieval by building a PostDisplayModel that parses json from Supabase into PostDisplay, using json_serializable and the Liskov substitution principle to keep domain logic clean.
Define a post remote data source interface and implement it with a supabase data source, wired via a repository through dependency inversion for paginated getPosts and uniform error handling.
Registers and injects PostRemoteDataSource, PostRepository, and GetPostsUseCase via riverpod providers to enable flexible implementation swaps (Supabase or Firebase) and wires the presentation layer to display posts.
Explore three architecture patterns in Riverpod: controller, mutation, and controller plus mutation, to build scalable post lists with pagination, optimistic updates, and clean separation of concerns.
Define PostListState and PostListStatus in post_list_state.dart to manage states (initial, loaded, failure, fetchingNextPage, refreshing, refilling) for paginated posts, including AsyncLoading, posts, hasReachedMax, failures, and scroll-to-top handling, then implement PostListController.
Learn to implement a riverpod async notifier to fetch posts with pagination, add infinite scrolling, and robust error handling using a GetPostsUseCase, PostListState, and a utility for unexpected failures.
Master robust post list user interface by handling state with PostListState and PostListStatus, showing async errors, transient failures, and retry logic, while implementing pull-to-refresh and a reusable PostCard.
Standardize scroll physics across iOS, Android, and web by injecting BouncingScrollPhysics with AlwaysScrollableScrollPhysics for lists and blank screens, and enable mouse drag via global dragDevices.
Develop post creation by applying clean architecture: implement domain and data layers, a post repository, and use cases for creating posts and uploading images, with dto handling image upload results.
Explore how the data layer implements post creation and image upload with Supabase, using rpc calls, authentication checks, and comprehensive error handling to return a PostDisplayModel.
Gate post creation behind admin role using authControllerProvider and AuthState, displaying a FloatingActionButton only for admins; test image upload, public post-images bucket, and a hot restart to reveal new posts.
Create a global event bus to broadcast post updates across the app; define PostCreatedDispatched as a GlobalEvent, implement GlobalEventBus with a stream, and provide it via riverpod keepAlive.
Broadcasts PostCreatedDispatched on new post creation through the GlobalEventBus, and lets PostListController listen, defer during refresh, prepend the new post, and scroll to top for real-time updates.
See how the GlobalEventBus updates the post list instantly within the app, while Supabass Realtime pushes important updates across devices, balancing speed and cost with a smart strategy.
Ensure a robust pull-to-refresh on the post detail screen by guarding against duplicate requests, preserving data with AsyncData, and handling errors via transientFailure and the global event bus for updates.
Implement refresh and fetch next page in the CommentListController with defensive checks, snapshot-based state updates, and robust error handling to ensure smooth, non-blocking pagination.
Connects post detail and comment state via Riverpod, implements scroll-based pagination with a scroll controller, and consumes transientFailure to show an error snackbar exactly once.
Explore domain, data, and presentation layers to implement a synchronized like feature on post pages, using optimistic updates, an event bus, and toggleLike flow with like result models in Supabase.
Explore implementing the like workflow on the post detail page using Riverpod mutations, pending state tracking, and error handling, including UI updates, snackbars, and testing.
Implement createComment, deleteComment, and updateComment in the post remote data source using Supabase RPC functions, with authentication checks and error handling, and wire them into the repository.
Learn to implement create, delete, and update comment mutations in Riverpod, wiring use cases through post_detail_mutations.dart, updating the comment list and post detail via a global event bus.
Implement runDeleteComment to delete a comment via deleteCommentMutation and update the CommentListController. Refill after delete fetches one more comment to maintain the list and update post detail.
Create a bottom-aligned CommentInputField on the post detail page, wired to mutations for the post via postId, and ensure new comments appear at the top using a scroll controller.
Implement domain level post deletion and post edit by wiring DeletePost, DeletePostFolder, and UpdatePost use cases with a PostRepository, image upload, and optional image handling.
Develop and wire deletePost, deletePostFolder, and updatePost in the post remote data source, including authentication checks, storage deletion, and an RPC update returning a PostDisplayModel.
Register the delete and update post use cases in Riverpod, implement deletePostMutation and updatePostMutation, and broadcast PostDeletedDispatched and PostUpdatedDispatched events for UI updates.
Enable author-only edit and delete actions on the post detail page, navigate to a prefilled post form for edits, and confirm deletions with a CircularProgressIndicator and error snackbars.
Describe editing on PostFormPage by loading the existing post in edit mode, prefilling fields once, and handling image state, updates, and error notifications with Riverpod async values.
Discover how to balance readability and reuse in riverpod state management by prioritizing readability over duplication, separating orchestration from data transformation, and limiting shared logic to feature scope.
Define the profile domain layer by creating entities, repositories, and use cases, outlining getProfile and updateProfile with avatar upload and deletion workflows.
The data layer implements the repository, communicates with Supabase, and defines profile remote data sources to support getProfile, updateProfile, uploadAvatar, and deleteAvatar.
This lecture demonstrates dependency injection with Riverpod by registering profile remote data source, repository, and use cases, using abstraction via ProfileRemoteDataSource to enable flexible implementations.
Fetch and display the logged-in user's profile on the MyProfilePage, including avatar, name, and role. If admin, retrieve and show their created posts with a post list powered by Riverpod.
Explore domain and data layers to implement getMyPosts with a dedicated use case and repository, upholding separation of concerns, and fetch user posts via a Supabase RPC with pagination.
Register GetMyPostsUseCase in Riverpod and add a ProfileUpdatedDispatched event to the GlobalEventBus, so controllers refresh posts when the profile changes by updating post authors' usernames and avatars.
Create an independent MyPostList state and controller with Riverpod, using a userId family provider and GetMyPosts, plus global event filtering and a runMyPostToglike mutation to toggle likes.
Connect the MyProfilePage to MyProfileController and MyPostListController to display profile data and posts, handle loading and error states, and implement admin pagination with Riverpod and scrolling.
Create a responsive user profile page with a circular avatar, iOS-style pull-to-refresh, and a clean layout that shows username, role, and a posts list using a reusable MyPostList component.
Create the MyPostList consumer widget in the presentation post folder, wiring Riverpod providers to handle loading, error with snackbars, and data state with pagination and PostCard.
Create a scalable Flutter user profile page that fetches another user's data by id with Riverpod's AsyncNotifierProvider, and, if admin, displays their posts via MyPostList.
The edit profile page presents a profile edit form and an updateProfileMutation that uses UpdateProfileUseCase to update a UserEntity and dispatches a global ProfileUpdatedDispatched event to sync the app.
Add an edit button to the app bar and navigate via pushNamed to EditProfilePage; build a Riverpod‑driven, validated profile form with image handling, safe data loading, and mutation‑level loading feedback.
Create a Flutter profile edit page with an app bar, using AsyncValue to show loading, error, and data states, and a scrollable form featuring avatar preview and image picking.
Implement a domain-driven search feature in Flutter by defining a repository interface and use cases for post and user searches, following clean architecture with domain, data, and presentation layers.
Learn how the data layer implements a repository interface, uses a Supabase search remote data source, and returns PostDisplayModel and UserModel via JSON parsing.
Define Riverpod providers to inject the search data source, repository, and use cases for the app. Wire the SupabaseClient via ref.watch, separating data and domain layer responsibilities.
Explore building a search feature with a dedicated search controller and search state to manage real-time user input, tab-based loading states for users and posts, and overall state management logic.
Explore building a debounced search controller in Flutter using Riverpod, handling global events to reflect post and profile updates via a hybrid approach for instant, consistent search results.
Implement a search controller in Flutter that handles user and post searches with Riverpod, using setQuery, _scheduleSearch, executeNow, and copyWith-based state updates for loading, loaded, and failure states.
Explore how SearchController handles optimistic post likes in search results using copyWith updates, a toggleLike use case, and a Riverpod mutation wrapper that broadcasts updates.
transform the search page into a consumer stateful widget to manage text editing controller input and tab lifecycles in flutter, using a tab controller and ticker for smooth transitions.
Implement a search page for users and posts with loading and error states, avatar and post cards, and navigation to user details, including like toggles and minimum post search characters.
"Go beyond Flutter basics and become an architect capable of designing professional, production-ready apps."
Are you ready to move past simple Counter or TODO apps and tackle the complex challenges of real-world services? If you’ve experienced the frustration of code becoming tangled as you add features, or felt the fragility of your app with every small change, this course is designed for you.
This is more than just a tutorial on building an app; it is a deep dive into proven development methodologies for creating scalable and maintainable applications that stand the test of time.
Why This Course Matters in the AI Era
In an era where AI can generate code snippets in seconds, what is the role of a professional developer?
Beyond Snippets: AI is excellent at writing functions, but it cannot yet design a complex, interconnected system. Understanding Clean Architecture means you know how to organize those AI-generated pieces into a scalable whole.
The Architect’s Advantage: As AI lowers the barrier to entry for coding, the market will be flooded with "fragmented code." The true value will lie in the Architect—the one who can manage technical debt, ensure maintainability, and design a robust "vessel" (Architecture) to hold the logic.
Future-Proof Your Career: This course evolves you from a "coder" who follows instructions to an "architect" who masters AI as a tool, rather than being replaced by it.
The Three Pillars of This Course
We will build a high-performance 'Community Board' app from scratch, grounded in three essential technical pillars for large-scale projects:
Robust Architecture (Clean Architecture): Bring order to chaotic code. Learn to separate concerns into distinct layers, creating a structure that is easy to test, maintain, and evolve.
Modern Backend (Supabase): Bypass complex server setups. Leverage Supabase—a powerful Backend-as-a-Service—to implement databases, authentication, and realtime features in a fraction of the time.
Efficient State Management (Riverpod & Event Bus): Master Riverpod, the industry standard for Flutter, and combine it with a Global Event Bus architecture to synchronize data across multiple screens with elegance and precision.
Key Learning Features
Build a Real-World Community App: Implement industry-standard features including Authentication, Post CRUD, Real-time likes/comments, Profile management, and Reactive search.
Professional Monorepo Setup: Learn to decouple features into independent packages to maximize code reusability and manage large-scale projects like a pro.
Advanced Streams & Real-time Control: Master Supabase Realtime for instant data syncing and utilize advanced stream techniques like Debounce and timer-based input control for an optimized search experience.
The Essence of Scalability: Design an architecture so flexible that you could swap your state management tool without touching a single line of your core business logic.
Curriculum Roadmap
Foundations: Master the VS Code environment and essential productivity tools to eliminate boilerplate code.
Architecture: Establish core principles of Clean Architecture, focusing on the dependency rule and separation of concerns.
Infrastructure: Build a Monorepo environment and design a Supabase backend (SQL, RLS, Functions, and Triggers).
Development: Implement core features (Auth, Posts, Search) using Riverpod combined with a Global Event Bus.
Advanced: Deep dive into Supabase Realtime for live data detection and UI synchronization.
Next Level: Project review and a strategic look at how this architecture extends to other state management libraries.
Who is this course for?
Flutter developers who have built basic apps and are ready to tackle professional, production-ready architectures.
Developers struggling with maintenance as their projects grow and seeking "Clean Architecture" as a definitive solution.
Solo developers or startup engineers who want to launch high-performance apps quickly using Supabase (BaaS).
Job seekers looking to showcase "Scalable App Design" and "Monorepo Management" skills in their professional portfolio.
Prerequisites
Flutter & Dart Basics: You should be comfortable with basic widgets and have a foundational understanding of asynchronous programming (async/await).
State Management Exposure: Experience with any state management solution (Provider, Riverpod 2, BLoC, GetX, etc.) is helpful. Even if you are new to Riverpod, you will be able to follow along.
Basic SQL Knowledge: A basic understanding of reading/writing data is recommended. Complex database policies (RLS) and functions will be covered step-by-step.
Lecture Materials and Source Code Provided
High-quality PDF slides: PDF presentation materials containing key theories and architecture diagrams for each section are provided. (Download from the Resources tab for each section)
Final source code provided:
Foundation Level: Complete code for productivity tools and core syntax (such as data_class) covered in Section 2 is provided.
Main Project: The monorepo structure and final implementation code for the entire community_board app starting in Section 4 is provided.
Links to the source code and usage instructions will be provided in detail in the first lecture of Sections 2 & 4.
Don't just learn 'how' to build; understand 'why' we design this way. Join me on this journey to elevate your development skills to the next level!