A full-featured spaced repetition study management application with Laravel 12 backend and Vue 3 frontend. Track topics, manage revision schedules, log practice sessions, and monitor progress — all powered by a REST API with OAuth 2.0 authentication and a beautiful responsive UI.
- 🚀 Frontend Setup: See
FRONTEND_README.mdfor Vue.js frontend docs - ⚡ Quick Start:
FRONTEND_QUICKSTART.mdfor 5-minute setup - ✅ Verification:
FRONTEND_CHECKLIST.mdto verify everything works - 📚 Full Frontend Docs:
FRONTEND_SETUP.md - 🔌 API Endpoints:
API-DOCUMENTATION.md
- Features
- Tech Stack
- Architecture
- Requirements
- Installation
- Configuration
- API Documentation
- Frontend Application
- Admin Panel
- Scheduled Commands
- Rate Limiting
- Security
- License
- Topic Management — Create, update, archive, and browse study topics with categories, difficulty levels, tags, and source links
- Adaptive Spaced Repetition — Revisions start at Day +1, +7, +30, +90 (or the topic's category schedule) and adapt to recall grades: Again restarts the steps with a relearn check tomorrow, Hard brings the topic back tomorrow, Good advances one step, Easy skips one; later reviews are re-planned from the day you actually reviewed
- Customizable Revision Templates — System defaults with per-user override support for custom revision schedules
- Schedule Presets per Category — Standard (1·7·30·90), Exam soon (1·3·7·14 then weekly until an exam date), Long horizon (1·3·7·21·60 then every 90 days) or custom schedules per category; each topic keeps the schedule it was created with
- Question-First Review — A review page serves today's due topics one at a time (overdue first, then mixed across categories): answer the recall questions from memory, reveal the answer key, grade Again/Hard/Good/Easy with the next date shown on each button; sessions stop at your daily time budget
- Weekly Plan with Gears — Choose Green/Yellow/Red per week, get blocks shaped for your study profile — a job holder (office and off days) or a student (class recap and deep block on class days, two long blocks on free days) — pre-decide each block's task, mark done/partial/missed/red, and score the week against an 80% success line; the dashboard shows this week's score and "Next up"
- Block Timer — Start any of today's blocks from the Weekly Plan or the dashboard; a mini timer stays on top of every page (and can pop out above other apps in Chrome/Edge), alerts at the block's breaks and at its end, marks the block done when its time runs out or partial when stopped early, then opens a "What did you learn?" wrap-up on the topic page
- Mistakes Notebook — Log every wrong answer with its cause; it is reviewed at +1/+3/+7 days and then merged into its parent topic's recall questions
- Recall Cards — Each topic can hold up to 10 recall questions (with optional answers), a summary used as the answer key, a practice prompt and a lane (Major/Minor/Work)
- Review Load — "Due today: N topics ≈ M min" banner with a warning above your budget, plus soft warnings for review debt, the weekly new-topic cap and missed days
- Daily Agenda — Grouped daily task view (Learn → Revision 1–4 → Practice → Overdue) with completion summary
- Task Actions — Complete (with a recall grade for revisions), skip, or reschedule tasks with notes
- Date Locking — Completed tasks become immutable (date and status locked)
- Practice Logs — Log study sessions with type (problem solving, implementation, reading, note making, mock interview), duration, and outcomes
- Calendar View — Monthly calendar with per-day task completion/pending/overdue counts
- Dashboard Stats — Total/active topics, today's pending, overdue count, daily completions, streak calculator
- Category System — User-created and system-wide categories with color and icon support
- Streak Tracking — Consecutive day completion streak calculated efficiently in a single query
- Pagination & Filtering — All list endpoints support pagination, search, and multi-field filtering
- OAuth 2.0 — Laravel Passport with password grant for API token-based authentication
- Token Lifecycle — Access tokens (3 hours), refresh tokens (15 days), personal access tokens (6 months)
- Login Tracking — Records successful/failed OAuth logins with IP and device info
- Role-Based Access Control — Spatie Laravel Permission with roles and permissions
- Admin Middleware — Type-based access control (Super Admin, Admin, User, API User)
- Dashboard — System-wide overview with key metrics
- Study Tracker Overview — Aggregate stats, 14-day completion chart (Chart.js), top users summary
- Trend & Stats Reports — Date-range completion trends, task type breakdown, top topics, practice type analysis, most active users
- Users Report — Paginated list of all type-3 users with topic counts, task stats, practice log counts (search + sort)
- Per-User Deep Report — Individual user analysis: topics, task completion rate, recent practice logs, upcoming tasks
- Topics Report — All topics with task/practice counts, filterable by status, difficulty, and search
- Categories Report — System vs user categories with topic counts and task completion stats
- Tasks Report — Advanced task management with 7 filters (status, type, user, topic, date range, sort)
- Data Deletion Requests — Review users' requests to delete chosen data: live data summary, approve (archive → verify → delete) or reject with a reason, download the archive, restore it within the retention period
- User Management — Create/edit users, change status, reset passwords
- Role & Permission Management — Full CRUD for roles and permissions
- OAuth Client Management — Manage Passport password grant clients, regenerate secrets
- Activity Logs — Comprehensive audit trail with cleanup
- Login History — Browse all user login records
- System Logs — View, download, and delete Laravel log files
- Settings — Configurable site settings with bulk update
- Backup & Restore — Database backup, download, restore, and delete
- Cache Management — Clear config/route/view/all caches, optimize
- Standardized API Responses — All responses use
CustomResponseTraitwith consistent{flag, msg, data, response_code}format - API Resource Classes —
TopicResource,StudyTaskResource,PracticeLogResource,CategoryResource,UserResource - Form Request Validation — Dedicated request classes with user-scoped
existsrules - Service Layer — Business logic separated into service classes (
CreateTopicWithPlanService,GenerateRevisionTasksService,CompleteTaskService,BuildDailyAgendaService,AddPracticeLogService) - Exception Handling — API-specific renderers for 404, 403, 401, and general HTTP exceptions
- Rate Limiting — Per-route named rate limiters optimized for AWS free tier
- Soft Deletes — Topics and categories support soft deletion
- Scheduled Tasks — Automatic overdue task marking via
study:mark-missed
| Layer | Technology |
|---|---|
| Framework | Laravel 12.x |
| PHP | 8.4 (8.2+ supported) |
| Node.js | 20+ (22 in CI) |
| Database | MySQL 8.0 / MariaDB 10.3+ |
| Authentication | Laravel Passport (OAuth 2.0 Password Grant) |
| Authorization | Spatie Laravel Permission |
| Frontend | Vue 3 + Vue Router + Pinia + Tailwind CSS |
| Frontend Build | Vite 7 with HMR |
| Admin UI | SB Admin 2, Bootstrap 4, Chart.js 4.4 |
| HTTP Client | Axios with token injection |
| Styling | Tailwind CSS 3 (mobile-first responsive) |
| Date Handling | date-fns |
| Device Detection | jenssegers/agent |
| Notifications | PHP Flasher |
app/
├── Console/Commands/ # Artisan commands (study:mark-missed)
├── Exceptions/ # Custom exception handler with API renderers
├── Http/
│ ├── Controllers/
│ │ ├── Api/
│ │ │ ├── AuthController # OAuth token issue/refresh
│ │ │ ├── UserApiController # User profile endpoint
│ │ │ └── StudyTracker/ # 5 API controllers
│ │ └── AdminStudyTrackerController # Admin reports & overview
│ ├── Middleware/ # ApiHeadersCheck, TokenApiHeadersCheck, AdminMiddleware
│ ├── Requests/StudyTracker/ # 6 form request classes
│ └── Resources/ # 5 API resource classes
├── Models/ # 10 Eloquent models
├── Services/StudyTracker/ # 5 service classes
├── Traits/ # CustomResponseTrait, HasFiles
└── Providers/ # Rate limiters, Passport config
- PHP 8.4 (or 8.2+)
- Composer
- MySQL 8.0 / MariaDB 10.3+
- Node.js 20+
- Git
- See CI_CD_EC2_GUIDE.md for GitHub Actions CI/CD setup
- EC2 t2.micro or larger, Ubuntu 22.04 LTS (or Amazon Linux 2)
deploy/ec2-setup.shconfigures all dependencies automatically
# Clone the repository
git clone https://github.com/naymur92/StudyTracker.git
cd StudyTracker
# Install PHP dependencies
composer install
# Install Node dependencies
npm install
# Copy environment file
cp .env.example .env
# Generate application key
php artisan key:generate
# Configure .env with your local database (MySQL 8.0)
# Edit: DB_HOST, DB_DATABASE, DB_USERNAME, DB_PASSWORD
# Run migrations
php artisan migrate
# Seed default data (admin user, permissions, revision templates)
php artisan db:seed
# Create Passport encryption keys
php artisan passport:keys
# Create Passport password grant client
php artisan passport:client --password
# Build frontend assets (for production) or start Vite dev server
npm run build # Production build
# OR
npm run dev # Development with hot reload (port 5173)
# Start development server (backend runs at http://localhost:8000)
php artisan serveConfigure frontend environment:
VITE_API_URL=http://localhost:8000/api
VITE_OAUTH_CLIENT_ID=<from passport:client output>
VITE_OAUTH_CLIENT_SECRET=<from passport:client output>For automated CI/CD deployment to AWS EC2, see the complete guide:
The workflow uses GitHub Actions for CI (test + build) and automatic deployment to EC2 on every push to main.
Quick summary:
- Run
deploy/ec2-setup.shon EC2 once (installs PHP 8.4, MySQL, Redis, Nginx, Node.js) - Create GitHub Action secrets for SSH (EC2_HOST, EC2_USERNAME, EC2_SSH_PRIVATE_KEY, etc.)
- Push to
main→ GitHub Actions tests → deploys to EC2 automatically
APP_URL=http://localhost:8000
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=study_tracker
DB_USERNAME=root
DB_PASSWORD=
CACHE_STORE=databaseFor the Vue.js frontend, set these environment variables in .env or configure via command line:
# Required for OAuth 2.0 password grant flow
VITE_API_URL=http://localhost:8000/api # or your production API URL
VITE_OAUTH_CLIENT_ID=<from passport:client>
VITE_OAUTH_CLIENT_SECRET=<from passport:client>Get OAuth credentials from the admin panel or create with:
php artisan passport:client --passwordThe VITE_* variables are replaced at build time by Vite, so they must be set before running npm run build for production.
Add to crontab for automatic overdue task marking:
* * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1A modern, responsive Vue 3 web application for managing your study tracker.
# Install dependencies
npm install
# Start development server (with hot reload)
npm run dev
# Build for production
npm run buildThe app runs at http://studytracker.test (or http://localhost:8080 with Docker). The Vite dev server runs on http://localhost:5173 for hot-reload during development only.
✅ Responsive Design — Mobile-first, works on all devices
✅ Authentication — Secure signup, login, email verification
✅ Dashboard — Daily overview, stats, and task agenda
✅ Topic Management — Create, edit, delete study topics
✅ Categories — Organize with custom colors and icons
✅ Study Tasks — Track daily assignments with spaced repetition
✅ Practice Logs — Record study sessions with details
✅ Calendar View — Monthly view of planned and completed tasks
✅ Review Page (/app/review) — Question-first review session with recall grades
✅ User Guide (/app/guide) — Manual for every menu, with the techniques and algorithms behind it, their benefits and research references; every page has a "Guide" link to its section
✅ Features Page (/features, public) — Features, learning techniques, "How StudyTracker decides" (each algorithm with a worked example) and an APA reference list
✅ User Profile — View statistics and manage account
The Features page and User Guide render shared content modules:
resources/js/content/learningScience.js— references (APA, DOI,verifiedflag), techniques and algorithms with evidence labels (Research-backed / Rule of thumb), benefits and citationsresources/js/content/userGuide.js— one section per sidebar item (guideSectioninresources/js/config/navigation.js)resources/js/content/features.js— the feature overview cards
npm run check:content (also run automatically before npm run build) fails on an unknown, uncited or unverified reference, on an entry without an evidence label, two benefits and a reference, and on a sidebar item without a guide section.
- Quick Start:
FRONTEND_QUICKSTART.md(5 minutes) - Setup Checklist:
FRONTEND_CHECKLIST.md - Full Guide:
FRONTEND_SETUP.md - Index & Navigation:
FRONTEND_README.md
Full API reference with request/response examples:
Import the ready-to-use Postman collection for testing all 31 API endpoints:
After importing, configure these Postman collection variables:
| Variable | Description | Example |
|---|---|---|
url |
API base URL | http://localhost:8000 |
token |
Bearer access token | (from /api/auth/token response) |
client_id |
Passport password grant client ID | 1 |
client_secret |
Passport password grant client secret | abc123... |
All endpoints below require the Authorization: Bearer <token> header.
| Method | Endpoint | Description | Rate Limit |
|---|---|---|---|
| Authentication (OAuth 2.0) | |||
POST |
/api/auth/register |
Register new user | 8/min/IP |
POST |
/api/auth/email/resend |
Resend verification email | 8/min/IP |
POST |
/api/auth/token |
Get access token | 8/min/IP |
POST |
/api/auth/token/refresh |
Refresh access token | 20/min/IP |
POST |
/api/auth/forgot-password |
Request password reset code | 8/min/IP |
POST |
/api/auth/reset-password |
Reset password with code | 8/min/IP |
| User | |||
GET |
/api/user |
Get authenticated user profile | 30/min/user |
PUT |
/api/user |
Update user profile | 30/min/user |
POST |
/api/user/change-password |
Change password | 30/min/user |
| Dashboard | |||
GET |
/api/study/dashboard |
Dashboard stats + daily agenda | 60/min/user |
GET |
/api/study/calendar |
Monthly calendar view | 60/min/user |
| Study Tasks | |||
GET |
/api/study/daily-tasks |
Daily task agenda | 60/min/user |
POST |
/api/study/tasks/{id}/complete |
Mark task as complete | 30/min/user |
POST |
/api/study/tasks/{id}/skip |
Skip a task | 30/min/user |
POST |
/api/study/tasks/{id}/reschedule |
Reschedule a task | 30/min/user |
| Topics | |||
GET |
/api/study/topics |
List topics (paginated) | 60/min/user |
POST |
/api/study/topics |
Create topic + revision plan | 30/min/user |
GET |
/api/study/topics/{id} |
Topic detail with tasks & logs | 60/min/user |
PUT |
/api/study/topics/{id} |
Update topic | 30/min/user |
DELETE |
/api/study/topics/{id} |
Archive topic (soft delete) | 30/min/user |
| Practice Logs | |||
GET |
/api/study/practice-logs |
List practice logs (paginated) | 60/min/user |
POST |
/api/study/practice-logs |
Create practice log | 30/min/user |
PUT |
/api/study/practice-logs/{id} |
Update practice log | 30/min/user |
DELETE |
/api/study/practice-logs/{id} |
Delete practice log | 30/min/user |
| Categories | |||
GET |
/api/study/categories |
List categories | 60/min/user |
POST |
/api/study/categories |
Create category | 30/min/user |
PUT |
/api/study/categories/{id} |
Update category | 30/min/user |
DELETE |
/api/study/categories/{id} |
Delete category (soft delete) | 30/min/user |
| Revision Templates | |||
GET |
/api/study/revision-templates |
Get revision schedule template | 60/min/user |
PUT |
/api/study/revision-templates |
Update revision schedule | 30/min/user |
POST |
/api/study/revision-templates/reset |
Reset to system defaults | 30/min/user |
| Review | |||
GET |
/api/study/review-queue |
Today's review session queue | 60/min/user |
GET |
/api/study/review-load |
Due-today estimate + warnings | 60/min/user |
| Review Schedules | |||
GET |
/api/study/schedule-presets |
Built-in schedule presets | 60/min/user |
GET |
/api/study/categories/{id}/schedule |
Category review schedule | 60/min/user |
PUT |
/api/study/categories/{id}/schedule |
Set category review schedule | 30/min/user |
DELETE |
/api/study/categories/{id}/schedule |
Revert category to default | 30/min/user |
| Mistakes | |||
GET |
/api/study/mistakes |
List mistakes (filters) | 60/min/user |
POST |
/api/study/mistakes |
Log a mistake | 30/min/user |
PATCH |
/api/study/mistakes/{id} |
Edit a mistake | 30/min/user |
DELETE |
/api/study/mistakes/{id} |
Delete a mistake | 30/min/user |
POST |
/api/study/mistakes/{id}/merge |
Merge into parent topic | 30/min/user |
| Weekly Plan | |||
GET |
/api/study/weekly-plan |
Week plan, blocks, score | 60/min/user |
GET |
/api/study/weekly-plan/history |
Recent weekly scores | 60/min/user |
POST |
/api/study/weekly-plan |
Create a week (gear + blocks) | 30/min/user |
PATCH |
/api/study/weekly-plan/{id} |
Update gear / weekly review | 30/min/user |
DELETE |
/api/study/weekly-plan/{id} |
Delete a week | 30/min/user |
POST |
/api/study/weekly-plan/{id}/regenerate |
Re-plan remaining blocks | 30/min/user |
POST |
/api/study/weekly-plan/{id}/blocks |
Add a block | 30/min/user |
PATCH |
/api/study/blocks/{id} |
Update a block | 30/min/user |
DELETE |
/api/study/blocks/{id} |
Delete a block | 30/min/user |
GET |
/api/study/timer |
Active timer + recent run | 60/min/user |
POST |
/api/study/blocks/{id}/timer/start |
Start a block's timer | 30/min/user |
POST |
/api/study/blocks/{id}/timer/pause |
Pause the timer | 30/min/user |
POST |
/api/study/blocks/{id}/timer/resume |
Resume the timer | 30/min/user |
POST |
/api/study/blocks/{id}/timer/stop |
Stop (done / partial) | 30/min/user |
DELETE |
/api/study/blocks/{id}/timer |
Discard the active run | 30/min/user |
DELETE |
/api/study/blocks/{id}/timer/runs |
Clear recorded time | 30/min/user |
| Study Preferences | |||
GET |
/api/study/preferences |
Get study preferences | 60/min/user |
PUT |
/api/study/preferences |
Update study preferences | 30/min/user |
| Data Deletion | |||
GET |
/api/study/data-deletion/summary |
Deletable data per category | 60/min/user |
GET |
/api/study/data-deletion/requests |
Own deletion requests | 60/min/user |
POST |
/api/study/data-deletion/requests |
Request data deletion | 30/min/user |
GET |
/api/study/data-deletion/requests/{id} |
One deletion request | 60/min/user |
Access the admin panel at /admin after logging in with a Super Admin (type 1) or Admin (type 2) account.
| Route | Description |
|---|---|
/admin |
Dashboard |
/admin/study-tracker |
Study Tracker overview with aggregate stats |
/admin/study-tracker/reports |
Trends & stats with date-range filtering |
/admin/study-tracker/users-report |
All type-3 users with study stats |
/admin/study-tracker/users/{id} |
Per-user deep report |
/admin/study-tracker/topics-report |
All topics with completion stats |
/admin/study-tracker/categories-report |
Category analysis |
/admin/study-tracker/tasks-report |
Advanced task management |
/admin/data-requests |
Data deletion requests (review, archive, restore) |
/admin/users |
User management (CRUD, status, password) |
/admin/roles |
Role management |
/admin/permissions |
Permission management |
/admin/oauth-clients |
OAuth client management |
/admin/activity-logs |
Activity audit trail |
/admin/login-history |
Login history |
/admin/system-logs |
Laravel log viewer |
/admin/settings |
Application settings |
/admin/backups |
Backup & restore |
/admin/cache/info |
Cache management |
Users ask for data to be deleted from their Profile page ("Delete my data"); each request appears on the admin dashboard and under Data Requests in the sidebar (with a pending badge).
- Review — open the request at
/admin/data-requests/{id}: user, chosen categories, reason, the counts taken when the user asked, and a live data summary (rows per kind of record, date ranges, sample titles, links that will be cleared). Counts that changed since the request are highlighted. - Approve — after confirming, a queued job (
defaultqueue, never retried automatically) collects the rows, writes a gzip JSON archive tostorage/app/private/data-archives/{user_id}/{uuid}.json.gz, reads it back to verify the SHA-256 and row counts, and only then deletes exactly those rows in one transaction. On failure nothing is deleted and the request becomesfailed(retry or reject it). - Reject — requires a reason, which the user sees. Nothing is deleted.
- Archive — download it (logged) or restore it (preview first; rows come back with their original IDs, current data wins on clashes) until it is purged after
DATA_ARCHIVE_RETENTION_DAYS(default 90).
The account itself, system categories, login history and activity logs are never deleted. Every step is written to the activity log (data_deletion).
| Permission | Allows |
|---|---|
data-request-list |
List requests, dashboard card, sidebar item |
data-request-view |
Request detail and live data summary |
data-request-approve |
Approve, reject, retry |
data-request-restore |
Restore from archive |
data-request-archive-download |
Download the archive |
Deploying this feature to an existing server: run php artisan db:seed --class=PermissionTableSeeder --force once. It creates the five permissions and grants them to the existing Super Admin role; give them to other roles from /admin/roles.
| Command | Schedule | Description |
|---|---|---|
study:mark-missed |
Daily at 00:01 | Marks overdue pending tasks as missed |
study:snapshot-review-load |
Daily at 00:03 | Records each user's start-of-day review load (review-debt history) |
demo:reset |
Daily at 00:05 | Resets the demo account's sample data |
data-requests:purge-archives |
Daily at 00:10 | Deletes data-deletion archives older than DATA_ARCHIVE_RETENTION_DAYS (default 90); --dry-run lists them |
Run manually:
php artisan study:mark-missed
php artisan study:snapshot-review-load
php artisan data-requests:purge-archives --dry-runOptimized for low-resource deployments (AWS free tier):
| Limiter | Limit | Scope |
|---|---|---|
auth-token |
8 requests/min | Per IP |
auth-refresh |
20 requests/min | Per IP |
study-read |
60 requests/min | Per authenticated user |
study-write |
30 requests/min | Per authenticated user |
api-profile |
30 requests/min | Per authenticated user |
- OAuth 2.0 password grant with JWT tokens
- Scoped validation rules — users can only reference their own resources
- Automatic date locking on task completion
- Role-based admin access (type 1 & 2 only)
- Custom API middleware for header validation (
Accept,Content-Type,X-Client-Id,X-Client-Secret) - Rate limiting on all API endpoints
- Soft deletes preserve data integrity
- CSRF protection on web routes
- Password hashing via bcrypt
users ─┬─< topics ─┬─< study_tasks ──< practice_logs
│ ├─< practice_logs
│ └─< topics (mistake entries, via parent_topic_id)
│
├─< categories ──< topics
│ └─< category_review_schedules (per user)
│
├─< topic_revision_templates
├─< review_load_snapshots
└─< study_weeks ──< study_blocks ──< study_block_sessions
Study Tracker tables: categories, topics, topic_revision_templates, study_tasks, practice_logs, category_review_schedules, review_load_snapshots, study_weeks, study_blocks, study_block_sessions
Notable columns added by the adaptive learning system:
topics— recall card (recall_questions,summary,practice_prompt,lane), mistake entries (kind,parent_topic_id,mistake_details,merged_at), schedule state (srs_step,srs_lapses,last_reviewed_on) and the schedule snapshot (srs_offsets,srs_repeat_every_days,srs_repeat_until,srs_schedule_source)study_tasks—recall_grade,review_seconds,review_kindusers—study_preferences(JSON, merged overconfig/study.phpdefaults)
data_deletion_requests — a user's request to delete data categories: status, request-time counts, reviewer, archive path/size/SHA-256 and purge time, deleted counts and restore report.
This project is open-sourced software licensed under the MIT License.