Portfolio
Proyecto propio (bloque Moodle) · 2024–2025

Course Recommender Block for Moodle

Tag-based Moodle block

A Moodle block that recommends courses by crossing a user's interests against course tags, returning live results without reloading the page.

My role Full design and implementation

  • PHP
  • Moodle Block API
  • Moodle External Services (REST/AJAX)
  • JavaScript AMD (RequireJS, jQuery)
  • Mustache
  • Moodle MUC (caché)
  • SQL (CTE)
  • Grunt
Course Recommender Block for Moodle
837
Lines of PHP
~44%
AMD minification (Grunt)
1
External web service
23 EN / 23 ES
Language strings

Screenshots

Problem

On a Moodle site with a large catalogue, learners rarely find the courses that truly match their interests: they browse by category, not by topic. The question "which course should I take next?" had no guided answer inside the platform itself, and freshly published courses went unnoticed.

Solution

I designed and built the block_course_recommender block from scratch. The learner picks interests as clickable badges, and the block crosses those tags against each course's tags via a SQL query with a CTE that scores by number of matches and favours the most recent. Recommendations arrive in real time through a Moodle external web service (AJAX), validated with sesskey and context, with no page reload. The front end runs on an AMD module (RequireJS + jQuery) and Mustache templates; the tag catalogue is cached in MUC with a configurable TTL to avoid repeated queries. It filters visible courses with self-enrolment and excludes any the learner is already enrolled in. I added admin settings (colour, tag count, sort order), a GDPR privacy provider and full ES/EN i18n.

Result

The block ships as a stable v2.0.0 release, installable like any Moodle plugin. It brings affinity-based course discovery into the campus itself, with instant suggestions, configurable tags and Grunt-minified JavaScript (~44% smaller). It follows Moodle conventions end to end: GPL v3 header, PHPDoc, privacy and bilingual strings, ready for distribution.