Context for working with REB Library Moodle plugin - a digital library system with TypeScript/Preact frontend, PHP backend, and custom education structure tables
Guidance for working with the **REB Library** (`local_reblibrary`) Moodle local plugin - a digital library management system for the Rwanda Education Board.
**Location:** `moodle_app/public/local/reblibrary/`
**Version:** 1.3.1 (2025102403)
**Tech Stack:**
**Environment:**
**Education Structure:**
**Resource Management:**
All CRUD operations exposed via Moodle external API (defined in `db/services.php`):
**Resources:** `classes/external/resources.php` - get_all, get_by_id, create, update, delete
**Education Structure:** `classes/external/edu_structure.php` - CRUD for levels, sublevels, classes, sections
**Categories:** `classes/external/categories.php` - Category CRUD
**Authors:** `classes/external/authors.php` - Author CRUD
**TypeScript + Preact + Tailwind CSS:**
**Key Modules:**
**Build System:**
Located in `admin/`:
Requires `moodle/site:config` capability.
Run from plugin directory:
```bash
pnpm install
pnpm run build
pnpm run dev
```
```bash
docker compose exec php php /var/www/html/moodle_app/admin/cli/purge_caches.php
```
```bash
docker compose exec php php /var/www/html/moodle_app/admin/cli/purge_caches.php
docker compose exec php php /var/www/html/moodle_app/admin/cli/upgrade.php --non-interactive
docker compose exec -T mariadb mariadb -u moodleuser -pmoodlepass moodle -e \
"SELECT name, value FROM mdl_config_plugins WHERE plugin='local_reblibrary';"
```
```bash
docker compose exec mariadb mariadb -u moodleuser -pmoodlepass moodle
docker compose exec -T mariadb mariadb -u moodleuser -pmoodlepass moodle -e \
"SHOW TABLES LIKE 'mdl_local_reblibrary_%';"
docker compose exec -T mariadb mariadb -u moodleuser -pmoodlepass moodle -e \
"SELECT * FROM mdl_local_reblibrary_resources;"
```
1. Create file in `amd/src/` (e.g., `amd/src/mymodule.ts`)
2. Export an `init` function
3. Build: `pnpm run build`
4. Load in PHP: `$PAGE->requires->js_call_amd('local_reblibrary/mymodule', 'init');`
5. Purge caches
**Example:**
```typescript
// amd/src/mymodule.ts
import { h, render } from 'preact';
export const init = () => {
const container = document.getElementById('app');
render(<div className="p-4 bg-blue-500">Hello Tailwind!</div>, container);
};
```
1. Create method in appropriate external API class (e.g., `classes/external/resources.php`)
2. Define `{method}_parameters()` function
3. Define `{method}_returns()` function
4. Implement method with validation, context, capability checks
5. Register in `db/services.php`
6. Increment `$plugin->version` in `version.php`
7. Run upgrade and purge caches
**Pattern:**
```php
// classes/external/myapi.php
namespace local_reblibrary\external;
class myapi extends external_api {
public static function my_method_parameters() {
return new external_function_parameters([...]);
}
public static function my_method($param) {
$params = self::validate_parameters(self::my_method_parameters(), ['param' => $param]);
$context = context_system::instance();
self::validate_context($context);
require_capability('local/reblibrary:view', $context);
// Implementation...
}
public static function my_method_returns() {
return new external_single_structure([...]);
}
}
```
1. Edit `db/install.xml` using XMLDB syntax
2. Create upgrade step in `db/upgrade.php`:
```php
if ($oldversion < 2025102404) {
// Create/modify tables using $dbman
upgrade_plugin_savepoint(true, 2025102404, 'local', 'reblibrary');
}
```
3. Increment `$plugin->version` in `version.php`
4. Run upgrade: `docker compose exec php php /var/www/html/moodle_app/admin/cli/upgrade.php`
Place components in `amd/src/components/`:
```tsx
// amd/src/components/MyComponent.tsx
import { h } from 'preact';
interface Props {
title: string;
}
export default function MyComponent({ title }: Props) {
return (
<div className="p-4 rounded-lg bg-white shadow-md">
<h2 className="text-xl font-bold">{title}</h2>
</div>
);
}
```
Import in entry point module:
```typescript
// amd/src/mypage.ts
import { h, render } from 'preact';
import MyComponent from './components/MyComponent';
export const init = () => {
render(<MyComponent title="Hello" />, document.getElementById('app'));
};
```
**Vite Configuration:**
**Adding New Entry Points:**
**Public:**
**Admin:**
1. **Always purge caches** after PHP, template, language, or JavaScript changes
2. **Use Moodle APIs** - Never write raw SQL; use `$DB->get_records()`, `$DB->insert_record()`
3. **Validate all inputs** - Use `required_param()`, `optional_param()`, external API validation
4. **Check capabilities** - Always verify permissions with `require_capability()`
5. **Version increments** - Update `version.php` after schema changes to trigger upgrades
6. **TypeScript types** - Define interfaces in `amd/src/types.ts`
7. **Frontend state** - Use Preact signals (`@preact/signals`) for reactive state
8. **CSS classes** - Use Tailwind utility classes; avoid custom CSS files
**Changes not showing:**
**Database changes not applied:**
**TypeScript module not found:**
**Web service not working:**
Defined in `db/access.php`:
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/moodle-reb-library-plugin-development/raw