A production-grade, offline-first SaaS platform for private tutors and tutoring centers in Egypt / MENA. Each tenant (a teacher or a center) runs a cross-platform Flutter app on their devices, their parents track progress through a web dashboard, and the platform owner runs the whole business from an admin console. Fully bilingual (Arabic / English, RTL-aware) end to end.
Table of Contents
- Elevator Pitch
- Architecture Overview
- Technology Stack
- Teacher App — Feature Deep-Dive
- In-Classroom Digital Exam Engine
- Synchronization Engine
- Parent Web Dashboard
- Landing Site, Billing & Owner Admin Console
- WhatsApp Messaging Microservice
- Backend — Supabase Platform
- Subscription Model & Plan Gating
- Billing Integration (Stripe → Paymob)
- Security & Multi-Tenancy
- Engineering Practices
- Resume / Portfolio Highlights
1. Elevator Pitch
Mudarris digitizes the full operation of a private tutoring business: students, class groups, staff, attendance, homework, monthly invoicing and payments, a question bank, and live digital exams delivered to students' phones over the classroom Wi-Fi — all working fully offline and syncing to the cloud (and peer-to-peer across devices) when a connection is available. Parents get a real-time web portal and WhatsApp updates. The platform owner sells it as a subscription SaaS with self-service signup, free trials, tiered plans, and a complete analytics + administration console.
The system is a Melos-managed monorepo comprising four applications, a shared Dart package, and a Supabase backend (Postgres + Edge Functions + scheduled cron jobs).
2. Architecture Overview
Monorepo layout (Melos — packages apps/* + packages/*):
| Component | Path | Stack | Role |
|---|---|---|---|
| Teacher app | apps/tutoring_app | Flutter (Android / iOS / macOS / Windows) | Offline-first management app for the tutor/center |
| Parent dashboard | apps/parent_dashboard | Next.js (App Router) | Web portal for parents to track their children |
| Landing + Admin + Billing | apps/landing | Next.js (App Router) | Marketing site, tenant signup, billing, owner admin panel |
| WhatsApp service | apps/whatsapp_service | Node.js + Express + Baileys | Relay that sends WhatsApp messages to parents |
| Backend | supabase/ | Supabase (Postgres + Edge Functions + pg_cron) | Cloud database, sync APIs, billing, scheduled jobs |
| Shared models | packages/shared_models | Dart | Shared enums/entities across the Dart apps |
┌──────────────────────────────┐
│ Supabase Backend │
│ Postgres + RLS (tenant_id) │
│ Edge Functions (Deno) │
│ pg_cron scheduled jobs │
└──────────────────────────────┘
▲ ▲ ▲ ▲
sync-token / │ │ │ │ service
cloud-sync │ │ │ │ webhooks
┌───────────────────┘ │ │ └────────────────┐
│ │ │ │
┌───────────────┐ ┌──────────────────┐ │ ┌───────────────────┐
│ Teacher App │ │ Parent Dashboard │ │ │ Landing + Admin │
│ Flutter │ │ Next.js (web) │ │ │ Next.js (web) │
│ Android/iOS/ │ │ phone login, │ │ │ marketing, signup,│
│ macOS/Windows │ │ web push (VAPID) │ │ │ billing, /admin │
│ offline SQLite│ └──────────────────┘ │ └───────────────────┘
└───────────────┘ │
│ │ │
│ │ LAN sync (WebSocket 8082 / UDP 8083) │
│ └──────────► other teacher devices │
│ │
│ embedded HTTP exam server (port 8080) │
└──────────► students' browsers on classroom LAN
│
┌────────────────────────┘
▼
┌────────────────────────┐
│ WhatsApp Service │
│ Node + Express + Baileys│
│ (Fly.io / Docker) │
└────────────────────────┘
Design principles
- Offline-first: the teacher app is fully functional with no network; all writes are buffered locally and reconciled on reconnect.
- Tenant isolation: every business row carries a
tenant_id; Postgres Row Level Security enforces isolation from the JWT. - Least privilege on device: the Supabase service-role key never ships in the app — clients authenticate cloud sync with a scoped, revocable sync token.
- Clean Architecture + BLoC on the client; framework-agnostic domain logic with
Either<Failure, Success>error modeling.
3. Technology Stack
Teacher App — Flutter (Dart >=3.5, Flutter >=3.24)
| Concern | Technology |
|---|---|
| State management | flutter_bloc 8.x, bloc, equatable |
| Dependency injection | get_it 7.x + injectable (codegen) |
| Routing | go_router 14.x (StatefulShellRoute nav stacks) |
| Local database | sqflite / sqflite_common_ffi + sqlcipher_flutter_libs (encryption staged) |
| Cloud client | supabase_flutter 2.x, http, connectivity_plus |
| Embedded exam server | shelf, shelf_router, shelf_web_socket |
| LAN sync | web_socket_channel + raw UDP sockets |
| QR | qr_flutter (generate), mobile_scanner (scan) |
| Charts | fl_chart, flutter_staggered_grid_view |
| Crypto / auth | crypto, encrypt, local_auth (biometrics) |
| Documents | pdf + printing, excel, archive, xml |
| Media / files | image, image_picker, image_cropper, file_picker, share_plus, video_player |
| System | shared_preferences, permission_handler, url_launcher, package_info_plus, flutter_local_notifications, flutter_foreground_task |
| i18n | flutter_localizations + intl + .arb files |
| Testing | flutter_test, integration_test, mocktail, bloc_test |
Parent Dashboard — Next.js 14.2 (App Router)
- React 18 + TypeScript 5, Tailwind CSS 3.4
@supabase/supabase-js+@supabase/ssr(auth + Realtime)recharts(charts),date-fns,lucide-react,clsx,tailwind-merge- Web Push (VAPID) via service workers
- E2E testing with Playwright
Landing + Admin — Next.js 14.2 (App Router)
- React 18 + TypeScript 5, Tailwind CSS 3.4
framer-motion(animation),recharts,lucide-react@supabase/supabase-js+@supabase/ssr- Billing: Stripe (legacy) → Paymob (Intention API, HMAC verification)
- Unit testing with Vitest
WhatsApp Service — Node.js (ES modules)
@whiskeysockets/baileys6.7 (WhatsApp Web protocol)express4.21,cors,qrcode,pino(logging)- Deployed on Fly.io via Docker; PM2 process management
Backend — Supabase
- Postgres with Row Level Security
- Edge Functions (Deno / TypeScript)
pg_cronscheduled jobs- Supabase Auth (parent + admin + tenant accounts)
- Supabase Realtime (parent dashboard live updates)
Shared
packages/shared_models— Dart package shared by the Flutter apps:- 15 enums: StudentStage, DiscountType, StudentStatus, GroupStatus, EmployeeRole, Permission, InvoiceStatus, PaymentMethod, ExamStatus, AttendanceStatus, HomeworkStatus, DifficultyLevel, AcademicTerm, SyncOperation, WhatsAppMessageType.
- 4 models: ScheduleSlot, ExamQuestion, StudentAnswer, TabSwitchEvent.
- Monorepo orchestration with Melos (
bootstrap,analyze,test,build:runner,format)
4. Teacher App — Feature Deep-Dive
A cross-platform (Android / iOS / macOS / Windows) Clean-Architecture Flutter app. ~18 feature
modules, each with data / domain / presentation layers and dedicated BLoCs.
Authentication & Access Control
- PIN login (4–6 digits, SHA-256 hashed with an app salt).
- Biometric unlock (fingerprint / Face ID) via
local_auth, toggleable. - Brute-force protection: 5-attempt lockout with a 30-minute cooldown.
- Multi-user device: a local-only Admin plus named employees, each with their own PIN and role-based permissions.
- Session persistence across restarts.
Students
- Full CRUD, search by name / phone / academic stage, soft-delete (history preserved).
- Duplicate detection on entry.
- Bulk import from Excel.
- QR sticker codes (
STU-XXXX) for fast attendance/identification. - Parent-account linking by phone.
Groups (Classes)
- Class groups with subject, academic stage, grade year, and weekly schedule slots.
- Dual pricing model: monthly fee and per-session fee; online vs in-person.
- Archive/active states; soft-delete.
- QR sticker-sheet PDF export for a whole group.
Employees / Staff
- Staff CRUD with name, phone, email, role.
- Per-employee PIN and granular permission set controlling which modules they can use.
Invoices
- Automatic monthly invoice generation (configurable day of month, default the 15th).
- Pricing formula
(monthlyFee / 4.33) × sessionCountwith sibling discounts for families. - Statuses: pending / paid / partially paid / overdue (with a configurable grace period).
- PDF invoice export.
Payments
- Record payments by method (cash / bank transfer / online), capture payer and date.
- Revenue reporting.
Question Bank
- Question CRUD with multiple-choice options, per-question marks, question + explanation images (base64), and term tagging.
- Rich filtering: subject / stage / grade / chapter / term / difficulty, with pagination.
- Excel import/export.
- Intentionally local-only (excluded from cloud sync) to avoid bulk question leakage and sync overhead.
Attendance
- Mark present / absent / late / excused per session; per-student reports; cloud-synced.
Homework
- Assign per group with due dates; bulk-mark completion; statuses assigned / submitted / graded / overdue; date-range filtering.
Dashboard / Analytics
- Metric tiles (students, groups, employees, upcoming exams, pending invoices, monthly revenue, attendance rate).
- Charts via
fl_chart(revenue trend, stage distribution, attendance). - "Safe mode" to hide sensitive financial/student data on shared screens.
WhatsApp Automation (client)
- Rule-based parent messaging: attendance alerts, invoice reminders, homework notices, custom broadcasts.
- Controls: enable per rule, quiet hours, cooldown, auto-send vs review queue, group/student scoping.
- Template variables (
[StudentName],[GroupName],[DueDate], …) with a styled template editor. - Local send queue with SHA-1 event deduplication, flushed every minute when the relay is online.
- Per-send logging; feature-gated by plan with a monthly send limit.
Backup & Export
- Timestamped local SQLite backups; full Excel export of all business data (multi-sheet); restore from file. Feature-gated.
Tenant & Subscription
- Connect a device to a tenant via a connection code; founding-deploy build-time single-tenant mode.
- Live subscription status, trial banner with days remaining, and automatic sync-token refresh on 401/403.
Parents & Pending Registrations
- Create/link parent portal accounts (auto-generates credentials), onboarding queue processed during sync.
- Review students who self-registered online and enroll them.
Settings
- Theme (light / dark / system), language (AR/EN), business-rule preferences (default subject, enabled stages), exam-login branding (name, slogan, logo, color), dashboard safe mode, parent-dashboard URL.
5. In-Classroom Digital Exam Engine
The standout feature: the teacher app embeds a full HTTP + WebSocket server (shelf,
~3,700 LOC) on port 8080, turning the teacher's device into an exam host that students join from
their own phone browsers over the classroom Wi-Fi — no internet required.
Exam authoring
- Digital and paper exams; manual or smart/randomized question selection; per-student question counts; term filtering; backward-navigation toggle; per-student wrong-answer review whitelist; grade override with automatic re-grade.
Student delivery endpoints
- Login (scan QR or enter ID + PIN), exam page (HTML5),
/api/exam-data(questions + remaining time, answers withheld), question images, real-time answer save, submit + auto-scoring, heartbeat, status.
Live teacher control (admin endpoints + WebSocket monitor)
- Pause / resume the exam, extend time (globally or per student), block / unblock a student, force-submit, allow re-entry, live results dump.
Anti-cheat
- Per-student question and option shuffling (original indices preserved for grading).
- Session tokens bound to the student's IP to prevent hijacking.
- Tab-switch detection & counting, screenshot-attempt tracking, per-student watermark (ID + timestamp).
- Heartbeat watchdog auto-blocks a student whose connection drops for >15 s.
Delivery quality
- Gzip-compressed responses, CORS, teacher branding on the login page, AR/EN student UI, configurable pass threshold (default 50%). A foreground service keeps the server alive when the app is backgrounded.
6. Synchronization Engine
Two independent, complementary sync layers.
Cloud Sync (Supabase Edge Functions)
- Write path (
cloud-sync) and incremental read path (cloud-sync-read,sincecursor). - Authenticated per-tenant with
x-tenant-id+x-sync-tokenheaders; server-side plan-limit enforcement and per-tenant rate limiting (~60 req/min). - Driven by a local
change_trackertable that stamps every mutation with device + tenant ID. - Staggered cadence: core tables every 5 min, attendance/homework every 10 min, question bank every 30 min.
- Last-write-wins with a smart merge for exam questions; WhatsApp logs and payments excluded.
- 401/403 transparently triggers tenant re-authentication / token refresh.
LAN Sync (peer-to-peer)
- WebSocket sync server on port 8082 + UDP broadcast discovery on port 8083.
- Shared-secret pairing between devices; periodic 30 s sync; full database export/import merge; coordinated workspace reset.
- Lets a center's devices stay consistent even with no internet — feature-gated to higher plans.
7. Parent Web Dashboard
Next.js web portal (Supabase Auth + Realtime), fully Arabic RTL.
- Phone-number login normalized to an internal email (
201XXXXXXXXX@tutoring.local), tolerant of Arabic/Persian numerals; forced first-login password change. - Multi-child support — parents see only their own children (RLS-isolated); persistent student selector.
- Overview: latest invoice + status, latest exam result, current-month attendance %, recent activity feed.
- Payments: invoices by student/year — gross, discount, net, method, status; totals paid vs remaining.
- Exams: results list + score-trend chart, stats (count, average, highest, #rank-1), color-coded performance, per-exam score/time/rank.
- Attendance: monthly calendar with present/late/absent + summary.
- Homework: assignments calendar.
- Web Push (VAPID): service-worker push subscription with mobile permission prompt, notification bell, and preferences; auto-cleanup of stale subscriptions server-side.
- Realtime: Supabase channels auto-refresh on invoice changes.
8. Landing Site, Billing & Owner Admin Console
A single Next.js app serving three audiences.
Public Marketing Site (AR/EN)
Home (hero, stats, feature cards, how-it-works, pricing, testimonials, FAQ, CTA), features, pricing,
terms, privacy. All copy, branding, SEO metadata, social links, analytics IDs, and download URLs are
editable from the admin CMS (site_settings table) — no redeploy needed.
Tenant Self-Service
- Signup creates a Supabase auth user → invokes the
tenant-signupEdge Function → provisions the tenant + a 14-day trial → returns a time-limited connection code (TM-XXXX, 72 h) used to link the desktop/mobile app. - Welcome page with the connection code and platform download links; dashboard with subscription status.
- Subscribe / manage / cancel via the billing provider (see §12).
Owner Admin Console (/admin, auth-protected)
| Section | Capabilities |
|---|---|
| Dashboard | KPI cards (total tenants, active subscriptions, MRR, new signups) + monthly-signups area chart |
| Tenants | Search; table with usage; detail page (subscription, usage metrics, billing-events history) with actions: extend trial (+14 d), suspend, activate |
| Subscriptions | Filter by lifecycle (active / trialing / past_due / canceled) |
| Plans editor | Inline-edit prices (monthly/yearly EGP), limits (students/groups/employees/questions/WhatsApp) and feature toggles (cloud sync, parent dashboard, WhatsApp, LAN sync, backup, reports) |
| Revenue | MRR, churn trend, monthly revenue line chart, plan-distribution pie |
| Settings (CMS) | Contact, branding (AR/EN), SEO, hero & CTA copy, social, analytics, app download URLs, password change |
9. WhatsApp Messaging Microservice
A standalone Node service that sends WhatsApp messages to parents on the platform's behalf.
- Stack: Express +
@whiskeysockets/baileys(WhatsApp Web),qrcode,pino. - Endpoints:
/health,/status,/qr(base64 PNG pairing code surfaced inside the Flutter app),/send(single, 24 h dedupe, optional schedulednotBefore),/send-bulk(batch + per-recipient results),/disconnect. - Auth:
x-api-keywith constant-time comparison; the service refuses to boot without a token. - Reliability: FIFO send queue with jittered delays (anti-throttling), max-queue cap (HTTP 429 when full), in-memory deduplication, auto-reconnect, and a persistent auth-state volume.
- Deployment: Docker + Fly.io (
fly.toml) / PM2. - Consumers: the
daily-parent-summaryandsend-parent-notificationEdge Functions.
10. Backend — Supabase Platform
Edge Functions (Deno)
| Function | Purpose |
|---|---|
tenant-signup | Provision tenant + 14-day trial, generate connection code, auto-confirm email |
cloud-sync | Write sync (insert/update/delete) with server-side plan-limit enforcement + rate limiting |
cloud-sync-read | Incremental read sync with a since cursor across core tables |
create-checkout | (Stripe, legacy) create checkout session |
create-portal-session | (Stripe, legacy) customer billing portal |
stripe-webhook | (Stripe, legacy) idempotent event handling → billing_events |
check-trial-expiry | Cron — downgrade expired trials to free |
daily-parent-summary | Cron (Cairo midnight) — attendance/exam/invoice summaries via WhatsApp + in-app |
send-parent-notification | Create in-app parent notification (by parent_id or phone) |
dispatch-parent-web-push | Deliver VAPID web push; prune stale (404/410) subscriptions |
upsert-parent-account | Create/link parent auth account, normalize Egyptian phone numbers, optional credential send |
reset-parent-password | Issue temp password, set must_change_password, bump credentials_version |
Scheduled Jobs (pg_cron)
- Trial-expiry downgrade.
- Daily parent summaries (Cairo timezone).
Data Model Highlights
- Tenant isolation:
tenant_idon every business table; RLS viaget_current_tenant_id()derived from the JWT; Edge Functions perform privileged service-role writes. - SaaS tables:
tenants,subscriptions,plans,billing_events,usage_metrics,admin_users,site_settings. - Billing (Paymob):
payment_cards(saved card tokens for auto-renew),payment_transactions(charge ledger: initial + renewal, order/transaction IDs, status). - Academic (tenant-scoped):
students,groups,employees,invoices,exam_results,attendance,homework,question_bank. - Parent stack:
parents(phone-normalized, auth_uid, notification flag),parent_notifications(6 types),parent_push_subscriptions(VAPID keys),whatsapp_log.
11. Subscription Model & Plan Gating
Plans are stored in the plans table and gated twice — client-side at the point of creation
and server-side inside cloud-sync — so limits can't be bypassed by tampering with the app.
| Plan | EGP/mo | Students | Groups | Employees | Questions | WhatsApp/mo | Cloud sync | Parent dash | LAN sync | Backup | Reports | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Free | 0 | 30 | 3 | 0 | 100 | 0 | ✗ | ✗ | ✗ | ✗ | ✗ | basic |
| Basic | 199 | 150 | 10 | 3 | 500 | 100 | ✓ | ✓ | ✓ | ✗ | ✓ | full |
| Pro | 399 | ∞ | ∞ | ∞ | ∞ | ∞ | ✓ | ✓ | ✓ | ✓ | ✓ | full |
New tenants start on a 14-day trial. Subscription lifecycle: trialing → active → past_due → canceled / expired, with automatic downgrade-to-free on trial expiry via cron.
12. Billing Integration (Stripe → Paymob)
The platform is migrating its payment provider from Stripe to Paymob (chosen for the Egyptian market: card auto-renew plus wallet / InstaPay flows, with WhatsApp payment reminders).
- Paymob (new): live DB schema (
payment_cards,payment_transactions,payment_provider,payment_method,auto_renew), a client library implementing the Intention API, EGP→piasters conversion, and HMAC webhook verification. Saved card tokens enable automatic renewal. - Stripe (legacy): checkout, customer portal, and webhook handling still present during the transition.
- The architecture cleanly abstracts the provider behind the
subscriptions/billing_eventstables, so the cutover is contained.
13. Security & Multi-Tenancy
- Row Level Security on all tenant data, keyed off the JWT — no cross-tenant leakage.
- No service-role key on device — the app uses a scoped, revocable sync token; a 401/403 forces re-auth.
- PIN hashing (SHA-256 + salt), biometric gate, and 5-attempt lockout.
- Exam integrity — IP-bound session tokens, tab-switch/screenshot detection, watermarking, heartbeat watchdog.
- Idempotent billing webhooks (dedupe via provider event ID) and a full
billing_eventsaudit log. - Non-blocking root/jailbreak detection at startup.
- WhatsApp relay protected by constant-time API-key comparison; SQLCipher-ready local storage.
14. Engineering Practices
- Clean Architecture (data / domain / presentation) with the BLoC pattern and
Either<Failure, Success>error handling. - Dependency injection via
get_it+injectablecodegen (~124 registered services). - Monorepo managed with Melos (unified bootstrap, analyze, test, format, build_runner).
- Versioned SQLite migrations (schema v16) run automatically at startup.
- Testing: Flutter unit + widget + integration tests (
mocktail,bloc_test); Playwright E2E for the parent dashboard; Vitest unit tests for the landing app. - 15 business rules (BL-01 … BL-15) implemented and documented.
- Internationalization with
.arbfiles and a JSON i18n layer on the web; RTL-aware everywhere.
15. Resume / Portfolio Highlights
Concise bullets you can drop straight into a portfolio or CV.
- Built a multi-tenant SaaS serving four client surfaces (cross-platform Flutter app, two Next.js web apps, a Node microservice) from a single Supabase backend, with Postgres Row Level Security for tenant isolation.
- Engineered an offline-first mobile/desktop app with versioned local SQLite, a change-tracking sync engine, and dual synchronization — cloud (Supabase Edge Functions) and peer-to-peer LAN (WebSocket + UDP discovery).
- Designed and implemented an in-classroom digital exam engine: an embedded HTTP/WebSocket server delivering randomized, watermarked exams to students' phones over local Wi-Fi, with live teacher controls and anti-cheat (IP-bound sessions, tab-switch detection, heartbeat watchdog).
- Delivered a subscription billing system with tiered plans, free trials, server-enforced feature/usage gating, and a payment-provider migration from Stripe to Paymob (Intention API + HMAC verification + saved-card auto-renew).
- Created a parent engagement layer: a real-time web dashboard with Web Push (VAPID) and an automated WhatsApp notification pipeline (Baileys) with deduplication, queueing, and scheduled daily summaries via
pg_cron. - Shipped a complete owner admin console — tenant management, plan editor, MRR/churn/revenue analytics, and a content-managed marketing site.
- Full Arabic/English RTL localization across every application.
Stack at a glance: Flutter · Dart · BLoC · Next.js · React · TypeScript · Tailwind · Supabase (Postgres, Edge Functions/Deno, RLS, Realtime, pg_cron) · Node.js · Express · Baileys · Stripe / Paymob · Web Push (VAPID) · SQLite/SQLCipher · Playwright · Vitest · Melos · Docker · Fly.io.