Overview
This is the project that taught me how software actually works. Before hackathons, before AI agents, before microservices — there was the INSAT Student App. A full-stack desktop application for first and second-year students at INSAT (Institut National des Sciences Appliquées et de Technologie, Tunis) that I built from scratch, learning system design, API architecture, database modeling, and GUI programming along the way. The frontend is a 5947-line PyQt5 desktop app with 145 methods — grade tracking, INSAT orientation simulation (GL, RT, IIA, IMI with historical 2022/2023 averages), chart visualizations (spider, line, bar via PyQtChart), an AI-powered orientation report generator (Llama 3.1 8B via llama-cpp-python), multi-language support (EN/FR/AR), and dark/light theming. The backend is a 2258-line single-file Cloudflare Worker with 50+ handler functions — full authentication (register, verify email, login, token refresh, password reset with HTML email templates), students/grades CRUD, matières management, reclamation system, notification emails, AI report storage, profile picture uploads via Cloudinary, and even a targeted ad system — all running against Neon Serverless Postgres.
The Problem
INSAT students (especially MPI — Mathématiques, Physique, Informatique) have no tool to track their grades, understand their ranking within their section, or simulate how future exam scores would affect their orientation eligibility for GL, RT, IIA, or IMI. Everything is done on paper or in scattered spreadsheets. Students can't visualize their academic trajectory or compare against historical averages to understand where they stand.
Solution
Built the PyQt5 desktop frontend (5947 lines, 145 methods in `main_app.py`) with custom widgets: NeedleGauge for orientation probability, CircularProgress for rankings, BarChartFrame for grade comparison, and ToggleSwitch for settings. The grade view shows DS, TP, Exam, and Final scores per subject with per-subject ranking against the section. PyQtChart powers spider charts (comparing student scores against 2022/2023 GL/RT/IIA/IMI historical averages), line charts (rank progression over time), and bar charts (section statistics).
Implemented a full orientation simulation engine: students input hypothetical grades for upcoming exams, and the system recalculates their Moyenne Générale in real-time, showing updated rankings and orientation eligibility across GL, RT, IIA, and IMI — using the actual INSAT orientation formulas with coefficient-weighted averages.
Built an admin app (`admin_app.py`) that generates personalized AI orientation reports for MPI students using Llama 3.1 8B running locally via llama-cpp-python. The reports analyze each student's strengths, weaknesses, and orientation fit, and are uploaded to the backend for students to access.
Engineered the entire backend as a single Cloudflare Worker (`index.js`, 2258 lines, 50+ functions) with Neon Serverless Postgres via `@neondatabase/serverless`. The Worker handles: full auth flow (register with email verification, login/logout, bcryptjs hashing, token refresh, password reset with cooldowns and HTML email templates), students/grades/matières CRUD, reclamation submission and tracking, notification system (per-user, per-section, and broadcast emails), profile picture uploads to Cloudinary, log file uploads, a targeted ad system with click tracking, and AI report storage/retrieval.
Added multi-language support (English, French, Arabic) with a `translations.py` dictionary, theme switching (dark/light with fade animation), font size customization, and connectivity awareness — the app detects internet status and gracefully disables online features when offline.
Architecture
PyQt5 desktop app communicates via HTTP requests (`api_client.py`) to a single Cloudflare Worker that handles all 50+ API routes. The Worker connects to Neon Serverless Postgres for all data (users, students, grades, matières, reclamations, notifications, AI reports, ads). Profile pictures and log files are uploaded to Cloudinary via the Worker. The admin app runs Llama 3.1 8B locally via llama-cpp-python and pushes generated reports to the Worker API. All auth uses bcryptjs with Bearer token verification on every request.
Tech Stack
PyQt5 + PyQtChart (5947 lines)
Desktop GUI — custom NeedleGauge, CircularProgress, BarChart, ToggleSwitch widgets, spider/line/bar charts, fade animations, 3 languages (EN/FR/AR)
Cloudflare Worker (2258 lines)
50+ handler functions — auth, CRUD, reclamations, notifications, uploads, ads, AI reports — single-file JavaScript, esbuild bundled
Neon Serverless Postgres
Full relational schema: users, students, grades, matières, reclamations, notifications, AI reports, ad clicks
Llama 3.1 8B (Admin AI)
Local LLM inference via llama-cpp-python — generates personalized orientation reports for each MPI student
Cloudinary
Profile picture hosting and log file storage — uploaded via Worker proxy
INSAT Orientation Engine
Real formulas for GL/RT/IIA/IMI eligibility with 2022/2023 historical averages for comparison
Results
PyQt5 desktop app with 145 methods — grades, simulation, charts, AI reports, 3 languages
Single Cloudflare Worker with 50+ handlers — auth, CRUD, notifications, uploads
GL, RT, IIA, IMI simulation with historical 2022/2023 averages
Llama 3.1 8B generated personalized reports per student
Full English, French, and Arabic translation support
Key Takeaways
This project taught me more about software engineering than any course ever could. Before this, I didn't understand why you separate frontend from backend, why APIs exist, or why databases need schemas. Building everything from scratch — auth flows, API design, database modeling, GUI state management — gave me the mental model I now use for every project.
The biggest lesson was about architecture mistakes. I put too much business logic in the frontend (grade calculations, ranking, simulation) — and by the time I realized it should be on the backend, it was too deeply embedded to refactor easily. That mistake taught me the importance of thinking about where logic belongs before writing a single line of code.
Writing a 2258-line Cloudflare Worker as a single file was not ideal, but it worked — and the process of organically growing an API from 5 endpoints to 50+ is how I learned to think about API design, auth middleware, and route organization. Every project since has started with proper structure because of what I learned here.
Building a real product for real users (INSAT students) is fundamentally different from building exercises. When your friends are the users, bugs are embarrassing and features matter. That pressure is what pushed me to add features like email verification, password reset with cooldowns, offline mode, and multi-language support.