AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Moodle Mobile App

skill-saadrahman01-claude-moodle-dev-moodle-mobile-app · by SaadRahman01

Use when integrating a Moodle plugin with the Moodle Mobile app — db/mobile.php remote templates, Ionic/Angular components delivered server-side, mobile.php view types, addons, push notifications, and offline support.

No reviews yet
0 installs
48 views
0.0% view→install

Install

$ agentstack add skill-saadrahman01-claude-moodle-dev-moodle-mobile-app

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-saadrahman01-claude-moodle-dev-moodle-mobile-app)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Moodle Mobile App? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Moodle Mobile App Integration

Overview

Moodle Mobile app (Ionic/Angular) loads plugin UI as remote templates declared in db/mobile.php. The server returns Mustache-like templates + JS that the app renders inline. No app rebuild required — works on any user's installed app once the site declares the addon.

When to Use

  • Adding plugin UI to mobile app
  • Surfacing notifications, dashboard items, or activity views in the app
  • Offline-capable content
  • Push notifications for plugin events

Skip when: plugin only used in browser admin UI.

Architecture

Moodle server                          Moodle Mobile app
─────────────                          ─────────────────
db/mobile.php          ────────────►   Discovers addons via
classes/output/mobile.php              tool_mobile_get_plugins_supporting_mobile

Returns                ────────────►   Renders Ionic components
  templates (.html)
  initial JS
  styles

App calls a server function which returns:

  • A Mustache-like template (Ionic + custom directives)
  • Optional JS to run client-side
  • Optional initial data
  • Optional offline functions

db/mobile.php

 [
        'handlers' => [
            'mainmenu' => [
                'displaydata' => [
                    'title' => 'pluginname',
                    'icon'  => 'list',
                    'class' => '',
                ],
                'delegate'    => 'CoreMainMenuDelegate',
                'method'      => 'mobile_main_menu_view',
                'styles'      => [
                    'url'     => '/local/example/mobile/styles.css',
                    'version' => 1,
                ],
                'offlinefunctions' => [
                    'mobile_main_menu_view' => [],
                ],
            ],
            'courseoption' => [
                'displaydata' => [
                    'title' => 'attendance',
                    'class' => '',
                ],
                'delegate' => 'CoreCourseOptionsDelegate',
                'method'   => 'mobile_course_view',
            ],
        ],
        'lang' => [
            ['pluginname', 'local_example'],
            ['attendance', 'local_example'],
        ],
    ],
];

Delegates

| Delegate | Where it shows | |----------|----------------| | CoreMainMenuDelegate | Main menu (bottom tab bar) | | CoreUserDelegate | User profile page | | CoreCourseOptionsDelegate | Course menu | | CoreCourseModuleDelegate | Activity in course (for mod_* plugins) | | CoreBlockDelegate | Sidebar block (for block_*) | | CoreSettingsDelegate | App settings page | | CoreMessageOutputDelegate | Message output handler |

classes/output/mobile.php

get_records('local_example_items',
            ['userid' => $USER->id], 'timecreated DESC', '*', 0, 20);

        return [
            'templates' => [
                [
                    'id'   => 'main',
                    'html' => self::render_main_template(),
                ],
            ],
            'javascript' => self::get_javascript(),
            'otherdata'  => [
                'items' => json_encode(array_values($items)),
                'sesskey' => sesskey(),
            ],
            'files' => [],
        ];
    }

    private static function render_main_template(): string {
        return '

    {{ \'plugin.local_example.attendance\' | translate }}
    
        
            {{ item.name }}
            {{ item.timecreated | coreFormatDate }}
        
        
            {{ \'plugin.local_example.markpresent\' | translate }}
        
    
';
    }

    private static function get_javascript(): string {
        return "
this.markPresent = (id) => {
    const params = {sessionid: id, userid: this.CoreSitesProvider.getCurrentSite().getUserId()};
    return this.CoreSitesProvider.getCurrentSite()
        .write('local_example_mark_present', params)
        .then((result) => {
            this.CoreDomUtilsProvider.showToast('plugin.local_example.marked', true, 2000);
        });
};";
    }
}

Required web services

The function name in db/mobile.php ('method' => 'mobile_main_menu_view') must be exposed as a web service in db/services.php:

$functions = [
    'local_example_mobile_main_menu_view' => [
        'classname'    => 'local_example\output\mobile',
        'methodname'   => 'mobile_main_menu_view',
        'description'  => 'Main menu mobile view',
        'type'         => 'read',
        'capabilities' => '',
        'services'     => [MOODLE_OFFICIAL_MOBILE_SERVICE],
    ],
];

Plus the AJAX/REST functions used inside the template (local_example_mark_present).

Template syntax

Mobile templates use Angular + Ionic with Moodle directives:

| Directive | Use | |-----------|-----| | {{ 'plugin.local_example.foo' \| translate }} | Lang string | | {{ value \| coreFormatDate }} | Format unix timestamp | | {{ html \| coreFormatText }} | Format Moodle text | | ` | Same, component form | | ngFor="let item of CONTENT_OTHERDATA.items" | Loop | | ngIf="condition" | Conditional | | (click)="handler()" | Event | | , , | Ionic UI | | ` | "Nothing here" placeholder |

CONTENT_OTHERDATA = data passed via 'otherdata'. Strings JSON-decoded automatically.

JavaScript scope

Helpers injected into JS scope:

| Object | Use | |--------|-----| | this.CoreSitesProvider | Current site, current user, web service calls | | this.CoreDomUtilsProvider | Toasts, alerts, modals | | this.CoreFilepoolProvider | Cache files for offline | | this.CoreUtilsProvider | Misc helpers | | this.refreshContent(false) | Reload current view |

Offline support

Add functions to 'offlinefunctions':

'offlinefunctions' => [
    'mobile_main_menu_view' => [],
    'local_example_get_items' => [],
],

App pre-fetches results during sync — they survive offline. For mutations (mark present), use the offline write API:

this.CoreSitesProvider.getCurrentSite().write(
    'local_example_mark_present',
    params,
    {forceOffline: false, getFromCache: false}
).catch((error) => {
    if (this.CoreUtilsProvider.isWebServiceError(error)) {
        return Promise.reject(error);
    }
    // Queue for later sync
    return this.CoreCourseProvider.storeOfflineAction(...);
});

Push notifications

Push delivery via Moodle's airnotifier service. Plugin events trigger notifications via \core\message\manager::send_message(). Mobile app receives them automatically when:

  • Site has airnotifier configured (Site admin > Mobile > Push notifications)
  • User logged into mobile app
  • User has the addon's notification preference enabled

Testing

  1. Local dev: install Moodle Mobile app, point at http://10.0.2.2:8000 (Android emulator) or your LAN IP
  2. Site admin > Mobile > Enable web services for mobile devices
  3. Log in to app — addon appears
  4. To force template re-fetch after server change: pull-to-refresh, or app settings > Synchronisation > Synchronise now
  5. Browser-based dev: npx ionic serve against moodle-mobile-app source pointing at your site

Styles

local/example/mobile/styles.css (referenced from db/mobile.php):

.local_example-marked {
    color: var(--ion-color-success);
    font-weight: bold;
}

Bumping 'version' => N in db/mobile.php invalidates app's cached styles.

Common Mistakes

| Mistake | Fix | |---------|-----| | Method not exposed as web service | Declare in db/services.php with MOODLE_OFFICIAL_MOBILE_SERVICE | | Lang strings not declared in db/mobile.php | App can't render {{ 'plugin...' | translate }} | | ` instead of Ionic | Use Ionic components for native look | | Forgetting MOODLEOFFICIALMOBILESERVICE | Web service callable but not for mobile | | Heavy DB queries on every refresh | Cache via MUC + invalidate on update | | Hand-formatting timestamps | Use coreFormatDate filter | | Embedding HTML directly | Use coreFormatText for formattext-equivalent escaping | | No offlinefunctions for read views | Pre-fetch fails — declare them | | Not bumping styles version | App keeps old CSS | | Calling fetch() directly | Use CoreSitesProvider` — handles auth + tokens |

References

  • Mobile addons: https://moodledev.io/general/app/development/plugins-development-guide
  • Templates spec: https://moodledev.io/general/app/development/plugins-development-guide/templates
  • Delegates list: https://moodledev.io/general/app/development/plugins-development-guide/api-reference
  • Offline support: https://moodledev.io/general/app/development/plugins-development-guide/offline
  • Push notifications: https://moodledev.io/general/app/development/plugins-development-guide/notifications
  • App source: https://github.com/moodlehq/moodleapp

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.