FLUTTER BLOG APP

This is a Flutter blog app that follows the Clean Architecture and SOLID principles. The app allows users to sign up, log in, create, and view blogs. The app uses Supabase as the backend. Local data is cached using Hive. The app also uses Easy Localization for localization and Internet Connection Checker to check for internet connectivity. The app follows the BLoC pattern for state management and uses GetIt for dependency injection.

Table of Contents 📎

Screenshots 📸

SignUp SignUp LogIn LogIn Blogs Blogs
NewBlog NewBlog BlogDetails BlogDetails

Clean Architecture 🏗

The Clean Architecture is a software design philosophy that separates the software into layers. Each layer has its own responsibilities and dependencies. The layers are:

  • Domain: This layer contains the business logic of the application. It is the innermost layer and does not depend on any other layer. It contains entities, use cases, and repositories.
  • Data: This layer contains the implementation of the repositories. It depends on the domain layer.
  • Presentation: This layer contains the UI of the application. It depends on the domain layer.

The Clean Architecture allows for the separation of concerns and makes the codebase more maintainable and testable.

Features 🎉

  • Authentication: Users can sign up and log in to the app.
  • Blogs: Users can create and view blogs.

SOLID Principles 🌟

The SOLID principles are a set of five design principles that help make software designs more understandable, flexible, and maintainable. The principles are:

  • Single Responsibility Principle (SRP): A class should have only one reason to change.
  • Open/Closed Principle (OCP): Software entities should be open for extension but closed for modification.
  • Liskov Substitution Principle (LSP): Objects of a superclass should be replaceable with objects of its subclasses without affecting the functionality of the program.
  • Interface Segregation Principle (ISP): A client should not be forced to implement an interface that it does not use.
  • Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.

The SOLID principles help make software designs more modular, flexible, and maintainable.

Clean Architecture + SOLID Principles 🚀

The Clean Architecture and SOLID principles work well together. The Clean Architecture provides a structure for the software, while the SOLID principles provide guidelines for writing clean and maintainable code. By following the Clean Architecture and SOLID principles, developers can create software that is easy to understand, test, and maintain.

Getting Started 🚀

Prerequisites 📋

Installation 🔧

  1. Clone the repository:
git clone
  1. Navigate to the project directory:
cd flutter_blog_clean_arc_app
  1. Install the dependencies:
flutter pub get
  1. Create a assets/env/.env and assets/env/.dev.env file in the root directory and add the following:
SupabaseUrl=YOUR_SUPABASE_URL
SupabaseAnonKey=YOUR_SUPABASE_ANON_KEY
SupabaseServiceRoleKey=YOUR_SUPABASE_SERVICE_ROLE_KEY
  1. Supabase:
  • Auth > Enable Email & Password
  • Database > profiles > SQL > Run the following query:
create table profiles (
  id uuid references auth.users on delete cascade not null primary key,
  updated_at timestamp with time zone,
  name text,

  constraint name_lenght check (char_length(name) >= 2)
);

alter table profiles
  enable row level security;

create policy "Public profiles are viewable by everyone." on profiles
  for select using (true);

create policy "Users can insert their own profile." on profiles
  for insert with check (auth.uid() = id);

create policy "Users can update own profile." on profiles
  for update using (auth.uid() = id);

create function public.handle_new_user()
returns trigger as $$
begin
  insert into public.profiles (id, name)
  values (new.id, new.raw_user_meta_data->>'name');
  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();
  • Database > blogs > SQL > Run the following query:
create table blogs (
  id uuid not null primary key,
  updated_at timestamp with time zone,
  owner_user_id uuid not null,
  title text not null,
  content text not null,
  image_url text,
  topics text array,
  foreign key (owner_user_id) references public.profiles(id)
);

alter table profiles
  enable row level security;

create policy "Public blogs are viewable by everyone." on blogs
  for select using (true);

create policy "Users can insert their own blogs." on blogs
  for insert with check (auth.uid() = id);

create policy "Users can update own blogs." on blogs
  for update using (auth.uid() = id);

insert into storage.buckets (id, name)
  values ('blog_images', 'blog_images');

create policy "Avatar images are publicly accessible." on storage.objects
  for select using (bucket_id = 'blog_images');

create policy "Anyone can upload an avatar." on storage.objects
  for insert with check (bucket_id = 'blog_images');

create policy "Anyone can update their own avatar." on storage.objects
  for update using (auth.uid() = owner) with check (bucket_id = 'blog_images');
  • Storage > Create a bucket with the name blog_images
  1. Run the app:
flutter run

Packages 📦

Thanks 🙏