Manage. Track. Grow.
EditFlow is a modern project and client management application built for freelancers, video editors, content creators, and creative agencies. This documentation is written to serve as a comprehensive onboarding guide for both human developers and AI coding agents.
The project follows a feature-first structure. Shared cross-cutting concerns (themes, services, widgets) live in root-level packages, while specific domains are isolated in lib/features/.
lib/
βββ app.dart # Application Entry Widget
βββ app_shell.dart # Layout Shell with Bottom Nav Bar & Haptic Taps
βββ main.dart # Supabase / App Initializer
βββ router.dart # GoRouter Mapping and Transition Configurations
βββ core/
β βββ constants/ # System Constants (e.g. Supabase credentials)
β βββ theme/
β βββ app_colors.dart # EditFlow Premium Dark/Light Palette Tokens
β βββ app_spacing.dart # Padding & Margin Tokens
β βββ app_text_styles.dart # Typography Configurations
β βββ app_transitions.dart # Blur & Symmetric Pop Route Transitions
βββ services/
β βββ supabase_service.dart # Static Client & Auth User Accessors
βββ shared/
β βββ models/ # Shared Data Models (e.g. Activity logs)
β βββ providers/
β β βββ computed_providers.dart # Grouped Metrics, Calculations, Top Freelancers
β βββ services/
β β βββ activity_service.dart # Local/Cloud Activity Logging
β βββ widgets/
β βββ animated_list_item.dart # Cascading Staggered Entrance Animations
β βββ empty_state.dart # Pulsing Ring & Scale Feedbacks
β βββ shimmer_card.dart # Stop-sorting Assertion Proof Skeleton Loaders
βββ features/
βββ auth/ # Sign-In, Registration, Splash Screens & Providers
βββ calendar/ # Deadline Visualizations & Filters
βββ clients/ # Client Records, Avatars, Profiles, Freelancers Screen
βββ dashboard/ # Stat Counters, Count-ups, Celebration Goal Rings
βββ payments/ # Invoices, UPI QR, Image/Text Sharing Sheets
βββ projects/ # Project Pipelines, comments, and Voice Recording
EditFlow relies on Supabase (PostgreSQL) for authentication, tables, and storage buckets. Row-Level Security (RLS) is enabled globally to isolate data between freelancers and clients.
public.profiles: Synchronized automatically withauth.usersvia a Postgres trigger.idUUID PRIMARY KEY (referencesauth.users(id))full_nameTEXT,emailTEXT
public.clients: Stores client organizations and maps them to client users.idUUID PRIMARY KEYuser_idUUID (referencesauth.users(id)) -> Owning Freelancerclient_user_idUUID (referencesauth.users(id)) -> Mapped Client User (for Portal access)nameTEXT,phoneTEXT,emailTEXT,companyTEXT,notesTEXT
public.projects: Main entity for tracking creative jobs.idUUID PRIMARY KEYuser_idUUID (referencesauth.users(id)) -> Owning Freelancerclient_idUUID (referencesclients.id)nameTEXT,descriptionTEXT,priceNUMERIC,received_amountNUMERIC,deadlineTIMESTAMPTZ,statusTEXT (yet_to_start, in_progress, revision_pending, completed, paid)
public.comments: Project feed comments supporting audio attachments.idUUID PRIMARY KEYproject_idUUID (referencesprojects.idON DELETE CASCADE)user_idUUID (referencesauth.users(id))user_nameTEXT,contentTEXTvoice_urlTEXT (nullable public storage link)voice_durationINT (nullable duration in seconds)
public.activities: Audit trail of freelancer operations.
profiles: Users can select profiles belonging to themselves, their assigned clients, or their owning freelancer.clients: Freelancers can read/write their own client records. Client users can only read their matching client row.projects: Freelancers can read/write their own projects. Clients can only select projects whoseclient_idmatches their client record.comments: Readable and writeable by anyone authenticated who has access to the parent project record.
Run this script inside the Supabase SQL editor to install triggers and syncher:
CREATE OR REPLACE FUNCTION public.handle_user_sync()
RETURNS trigger AS $$
BEGIN
INSERT INTO public.profiles (id, full_name, email)
VALUES (new.id, COALESCE(new.raw_user_meta_data->>'full_name', 'User'), new.email)
ON CONFLICT (id) DO UPDATE
SET full_name = EXCLUDED.full_name, email = EXCLUDED.email;
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE OR REPLACE TRIGGER on_auth_user_changed
AFTER INSERT OR UPDATE OF email, raw_user_meta_data ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_user_sync();The application relies heavily on Riverpod AsyncNotifier and StreamProvider variables.
ββββββββββββββββββββββββββ
β authProvider β
βββββββββββββ¬βββββββββββββ
βΌ
ββββββββββββββββββββββββββ
β settingsProvider β
βββββββββββββ¬βββββββββββββ
βΌ
βββββββββββββββββββ΄ββββββββββββββββββ
βΌ βΌ
[Freelancer Mode] [Client Mode]
- ProjectRepository - ClientProjectRepository
- Swaps stream queries - Blocks writes (throws errors)
- Show all metrics - Translates label metrics
- Full bottom navigation tabs - Collapses bottom tabs to 2
When toggling isClientMode inside settingsProvider, the local memory caches flags (_hasLoadedOnce and _lastValidData) inside projectProvider and clientProvider are automatically cleared. This ensures that switching profiles pulls fresh data from Supabase instead of displaying stale, cached queries.
When a client signs in, they are placed in a read-only portal:
- Write Lockdowns: Any edits, creations, deletions, or data imports/exports are hidden in UI. The repository layer switches to
ClientProjectRepositorywhich explicitly throwsUnsupportedErroron database modifications. - Navigation Collapsing: Floating app shell bottom bar collapses from 4 tabs down to 2 (Dashboard & Freelancers screen).
- Metric Conversions: Business earnings are translated to client expenditures:
- "Total Earnings" -> Total Expense
- "Pending Revenue" -> Total Due
- "Top Clients" -> Top Freelancers (ordered by upcoming deadline urgency).
The payments screen displays visual invoice receipts and handles QR generating logic.
- Indian Bank Security Compliance: Prefilled parameters such as amount (
am), note (tn), and currency (cu) are deliberately omitted from native UPI deep links (upi://pay?pa=...&pn=...). This guarantees that banking applications (like Paytm, PhonePe, GPay, and Kotak 811) resolve VPAs successfully without hitting security flags. - Error Correction Level (
QrErrorCorrectLevel.H): Set to High to handle center-embedded logo coverage (up to 30%). This prevents "invalid QR code" errors when scanning. - Launcher Monogram Design: The center of the QR embeds EditFlow's official flowing "ef" monogam launcher logo, featuring a 2px white border margin frame.
- Invoice Layout: Centered vertical cards with dedicated "UPI PAYMENT" divider lines. Sticky "Share Image" and "Share Text" actions are anchored to the bottom of the sheet, preventing scrolling fatigue.
EditFlow features compressed voice notes for project feedback to stay well within Supabase's 1GB Free Tier limits.
[Audio Recording] -> Low Bitrate AAC/M4A (16kHz, 24kbps) -> File Size ~180KB/min
β
βΌ (Uploads to Bucket)
[Supabase Storage] -> Bucket: "voice-notes" / Path: "projects/{project_id}/{fileName}.m4a"
β
βΌ (Dashboard Initialization / Refresh)
[Background Cleanup] -> Selects records > 14 days old -> Deletes files & Nullifies URLs
- Codec Settings: Encoded using
AudioEncoder.aacLcwith a 16kHz sample rate and 24kbps bitrate, capping files at exactly 60 seconds (approx. 180 KB total). - 14-day Auto-cleanup: Whenever the dashboard completes initialization,
CommentRepository.cleanupOldVoiceNotes()queries the database for feedback rows older than 14 days. It deletes corresponding files from thevoice-notesbucket and nullifies the database columnsvoice_urlandvoice_duration. This maintains a very low storage footprint.
EditFlow runs a persistent Android Foreground Service isolating notifications and metrics synchronization:
- Background Isolate Thread: Uses
flutter_foreground_taskto query updates directly on a background isolate thread context, avoiding app sleep suspensions. - SharedPreferences Auth Bridge: Since UI-heavy
Supabase.initializefails in background isolates during release builds, the isolate queries user credentials (ID & Session JWT token) stored safely insideSharedPreferencesby the main thread on login/refresh. It instantiates a pure DartSupabaseClientwithAuthorization: Bearer <token>headers to bypass UI storage dependencies. - Dual Monitoring Modes:
- Freelancer Mode: Persistently shows active project count:
Active: X Projects | Running in background. - Client Mode: Persistently shows total assigned creative collaborators:
Freelancers: X | Active Projects: Y.
- Freelancer Mode: Persistently shows active project count:
- Robust WebSockets & Polling Fallback: streams data in real-time using Supabase database subscriptions. If the background socket connection drops, it automatically falls back to secure REST HTTP polling every 30 seconds.
- VM Entry-point Protection: Callback entrypoints and handling classes/methods are guarded with
@pragma('vm:entry-point')to prevent the R8 compiler from stripping or obfuscating background isolate routines in release builds.
The /docs/ folder contains a responsive marketing landing page optimized to deploy directly via GitHub Pages:
- Assets and Mono-Logo: Employs the custom-designed programmatic "ef" vector monogram (
logo.svg) and holds the compiled production APK (editflow.apk) for direct user downloads. - Custom Mobile Mockup: An interactive CSS frame notch holds the real dashboard screenshot. Configured with a smooth transition scrolling the viewport on hover.
- Features Grid: Details dedicated value propositions for Freelancer Workspace and Client Portal systems.
Create a .env file at the root:
SUPABASE_URL=your_supabase_project_url
SUPABASE_ANON_KEY=your_supabase_anon_key- Currency: Defaults to INR (βΉ) for all projects, pipelines, and dashboard counters on both portals.
- Theme: Defaults to Dark Mode on initial launch and clear-data startups.
- Fetch Dependencies:
flutter pub get - Static Analysis:
flutter analyze(ensurelib/directory remains with 0 issues). - Run Tests:
flutter test(all 10 unit/widget tests must pass). - Build Android APK:
flutter build apk --release(generates release binaries insidebuild/app/outputs/flutter-apk/app-release.apkand copies todocs/editflow.apkfor the site).
Release compilations optimize binary code using R8. Add the following rules to android/app/proguard-rules.pro to prevent stripping of Supabase authentication session models and isolate task callbacks:
-keep class com.supabase.** { *; }
-keep class io.supabase.** { *; }
# Keep background service task handler entrypoints
-keep class * extends com.pravera.flutter_foreground_task.models.TaskHandler { *; }
-keepclassmembers class * {
@kotlin.jvm.JvmStatic <methods>;
}