A bilingual (Arabic / English) learning platform for secondary-school students: lessons organised by subject and unit, timed exams graded on the server, and a personal dashboard that tracks progress.
Built with ASP.NET Core 10 (REST API, JWT, EF Core + SQLite) and a vanilla HTML / CSS / JavaScript front end — no framework, no build step.

For students
Interface
css/app.css) used by every page| Dashboard — dark mode, English | Login |
|---|---|
![]() |
![]() |
| Course | Exams |
|---|---|
![]() |
![]() |
| Progress | Mobile |
|---|---|
![]() |
![]() |
| Layer | Technology |
|---|---|
| API | ASP.NET Core 10, controllers, minimal hosting |
| Auth | JWT bearer tokens, ASP.NET Identity PasswordHasher |
| Data | Entity Framework Core 10, SQLite, code-first migrations, seed data |
| Docs | Swagger / OpenAPI with an Authorize button for testing |
| Front end | HTML5, CSS3 (custom properties, grid, container queries), vanilla JavaScript (ES2020) |
| i18n | Custom dictionary with Arabic plural rules and RTL/LTR switching |
Requirements: .NET 10 SDK.
git clone https://github.com/amanykhaled4/itqan-learning-platform.git
cd itqan-learning-platform
dotnet run --project backend
Open http://localhost:5111 — the API serves the front end too, so that one command runs the whole platform. The SQLite database is created and filled with subjects, lessons and exams on first run.
Demo account — press Try the demo account on the login page, or log in with:
| Password | |
|---|---|
demo@itqan.app |
demo1234 |
It already has finished lessons and exam results, so every page has something to show. You can also create your own account from the register page.
API documentation: http://localhost:5111/swagger
dotnet test Itqan.slnx
17 tests in tests/ItqanApi.Tests. Most are integration tests that start the real API in memory against a throwaway SQLite database (WebApplicationFactory) and check:
The same tests run on every push with GitHub Actions (.github/workflows/ci.yml).
Prefer VS Code Live Server for the front end? Open
frontend/on port 5500; it will call the API on port 5111 automatically (CORS is already allowed in development).
backend/
Controllers/ Auth, Me (profile & settings), Subjects & lessons, Exams, Progress
Data/ AppDbContext and seed content
Dtos/ Request / response records with validation attributes
Models/ Student, Subject, Unit, Lesson, Exam, Question, Option, attempts
Services/ TokenService (JWT), ProgressService (stats & streaks)
Migrations/ EF Core migrations
frontend/
*.html One page per screen
css/app.css Shared design system (tokens, components, dark mode, RTL)
js/api.js Fetch wrapper: token handling, errors, expired sessions
js/i18n.js Arabic / English dictionary
js/app.js Layout, sidebar, notifications, toasts, dialogs
js/pages/ Page-specific scripts
tests/
ItqanApi.Tests/ xUnit integration and unit tests
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register |
Create an account, returns a token |
| POST | /api/auth/login |
Log in, returns a token |
| GET / PUT | /api/me |
Read or update the profile |
| PUT | /api/me/settings |
Language, theme, notification preferences |
| PUT | /api/me/password |
Change password |
| GET | /api/subjects |
Subjects with the student’s progress |
| GET | /api/subjects/{slug} |
Units and lessons of a subject |
| GET | /api/lessons/{id} |
Lesson content with previous / next links |
| POST / DELETE | /api/lessons/{id}/complete |
Mark or unmark a lesson as complete |
| GET | /api/exams |
Exams with best score and attempt count |
| GET | /api/exams/{id} |
Questions and options (without answers) |
| POST | /api/exams/{id}/submit |
Grade answers and return the review |
| GET | /api/exams/attempts |
Past results |
| GET | /api/progress |
Overall stats, per-subject progress, recent activity |
All endpoints except register and login need an Authorization: Bearer <token> header.
backend/appsettings.Development.json contains a development-only JWT key. Outside development the placeholder key is never used: without Jwt__Key the API generates a random key at startup (secure, but everyone is logged out when the server restarts). To keep logins across restarts, set your own secret:
Jwt__Key="a-long-random-secret"
The repo includes a Dockerfile (API + front end in one container) and a Render Blueprint (render.yaml) that generates the JWT secret automatically:
On the free plan the SQLite database lives inside the container, so it starts fresh (with the demo account) after each restart.
إتقان منصة تعليمية لطلاب المرحلة الثانوية: دروس مقسّمة إلى مواد ووحدات، واختبارات بوقت محدد تُصحَّح على السيرفر، ولوحة تحكم تتابع تقدّم الطالب. الواجهة تدعم العربية والإنجليزية والوضع الليلي وتعمل على الموبايل.
للتشغيل: ثبّت .NET 10 SDK ثم نفّذ dotnet run --project backend وافتح http://localhost:5111، واضغط «جرّب الحساب التجريبي» للدخول مباشرة.