# Mobile: Plugin support

**URL:** <https://discourse.joplinapp.org/t/mobile-plugin-support/35262>\
**Category:** Beta Testing\
**Tags:** plugins\
**Created:** [17 January 2024 05:16 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262 "2024-01-17T05:16:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [17 January 2024 05:16 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/1 "2024-01-17T05:16:52Z")

</div>

**Note** : Plugin support has been merged. It should be available in the [Android Joplin pre-release](https://github.com/laurent22/joplin-android/releases/tag/android-v3.0.1).

See [this GitHub issue](https://github.com/laurent22/joplin/issues/10154) for more information about plans for plugin support on iOS.

* * *

Over the past few weeks, I've been working on adding plugin support to mobile (see [the relevant pull request on GitHub](https://github.com/laurent22/joplin/pull/9652)).

This post summarizes the status of the pull request.

# To-do

- Better development experience
  - Currently, it's possible to inspect plugin `WebView`s in Google Chrome, but only in a [development build](https://joplinapp.org/help/dev/BUILD) of Joplin. Assuming most plugin authors won't be running a development build of Joplin, a way to enable plugin WebView debugging should be added.

- Refactoring & automated tests (where possible)
- Performance improvements
  - Fix: Large renderer content scripts (like that included in ABC Sheet Music) significantly slow down the renderer.
  - Fix: Plugin background WebView is created even if there are no plugins to load.

- Support more of the plugin API (see below).
- Add a way to start the mobile app in safe mode (i.e. without running plugins).

# Plugins known to work

## [ABC sheet music](https://joplinapp.org/plugins/plugin/org.joplinapp.plugins.AbcSheetMusic/)

 ![Screenshot: Note titled ABC sheet music test shows a simple score rendered in the note viewer on iOS](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/4/d/4ddc20641c752453cc0999c3ef3169d65e13eb6c.jpeg)

The ABC sheet music plugin mostly works.

Known issues:

- In dark mode, the music is difficult to read.

> **An error message is briefly shown before music renders.**
>
> ABC sheet music registers a renderer content script. This content script tries to access the plugin's settings.
> 
> With the plugin API pull request, the renderer is run inside the note viewer `WebView` for security and to provide renderer plugins access to DOM APIs. This does mean, however, that communication with renderer scripts is **asynchronous**.
> 
> The settings API is synchronous, however (and so is `markdown-it` rendering). Thus, attempting to access a setting returns `undefined`, loads the setting, then triggers a re-render (with the setting loaded).
> 
> After the first render, an error message is shown by the ABC Sheet Music plugin because it doesn't expect the setting to be `undefined`. The error message disappears because the setting is not `undefined` in the second render.

## [The example CodeMirror 6 plugin](https://github.com/personalizedrefrigerator/joplin/blob/pr/mobile-plugin-support/load-jpl-via-expo/packages/app-cli/tests/support/plugins/codemirror6/README.md)

 ![Screenshot: Line numbers and toggle arrows shown running on iOS](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/6/9/69f9d0c5b402dfe6889626591e8418e7223af00e.jpeg)

The mobile editor is based on CodeMirror 6. As such, the [demo CodeMirror 6 plugin](https://github.com/personalizedrefrigerator/joplin/blob/pr/mobile-plugin-support/load-jpl-via-expo/packages/app-cli/tests/support/plugins/codemirror6/README.md) for desktop works.

Because the existing CodeMirror 6 plugin API includes a [compatibility layer](https://github.com/personalizedrefrigerator/joplin/blob/pr/mobile-plugin-support/load-jpl-via-expo/packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.ts), plugins that target CodeMirror 5 may work, depending on the features they use.

**Note** : For testing purposes, this plugin is included with the demo Android APK and enabled by default.

## [Function plot](https://joplinapp.org/plugins/plugin/com.hieuthi.joplin.function-plot/)

 ![Screenshot: Function plot demo note](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/f/3/f342dafa74b891da2a590eeb18ca8c6e8e12477a.png)

## [Math mode](https://joplinapp.org/plugins/plugin/plugin.calebjohn.MathMode/)

 ![Screenshot: Math mode test: Renders e^(i pi) to be -1](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/4/3/4372c56d19d5f7b08814fca7525b9671dc8c17fb.png)

**Known issue** : Clicking on the same line as a math expression does not move the cursor to that line.

## [Spoilers](https://joplinapp.org/plugins/plugin/joplin.plugin.spoiler.cards/)

 ![Screenshot: Spoilers plugin button shown in toolbar](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/3/f/3f3133d0c90e5cfee26b9d15e6c5434ae7d3c2b7.png)

**Known issue** : Some content is missing a show/hide arrow (renders a box instead).

# Plugins known not to work

- Plugins that require file system access (e.g. Simple Backup, Outline)

# Plugin API

## Supported

**Update 2025** : This list may be outdated. See the [plugin API documentation](https://joplinapp.org/api/references/plugin_api/classes/joplin.html) for more up-to-date information.

- [Markdown-it](https://joplinapp.org/api/references/plugin_api/classes/joplincontentscripts.html) and [CodeMirror 6 content scripts](https://joplinapp.org/help/api/tutorials/cm6_plugin)
- [`joplin.data`](https://joplinapp.org/api/references/plugin_api/classes/joplindata.html)
- [`joplin.views.toolbarButtons.create`](https://joplinapp.org/api/references/plugin_api/classes/joplinviewstoolbarbuttons.html)
  - Currently only works for [`ToolbarButtonLocation.EditorToolbar`](https://joplinapp.org/api/references/plugin_api/enums/toolbarbuttonlocation.html)

- [`joplin.clipboard.readText`, `joplin.clipboard.writeText`](https://joplinapp.org/api/references/plugin_api/classes/joplinclipboard.html)
  - Missing support for `readHtml`, `writeHtml`

- Most of [`joplin.views.dialogs`](https://joplinapp.org/api/references/plugin_api/classes/joplinviewsdialogs.html)
  - Missing support for `showOpenDialog`

- [`joplin.commands`](https://joplinapp.org/api/references/plugin_api/classes/joplincommands.html)
  - Only a very small set of built-in commands are currently supported: [editor commands](https://github.com/personalizedrefrigerator/joplin/blob/pr/mobile-plugin-support/load-jpl-via-expo/packages/app-mobile/components/NoteEditor/commandDeclarations.ts), [app commands](https://github.com/laurent22/joplin/tree/dev/packages/app-mobile/commands), [note screen commands](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/components/screens/Note/commands/index.ts), and [some of the commands in lib/commands](https://github.com/laurent22/joplin/tree/dev/packages/lib/commands).

- [`joplin.settings`](https://joplinapp.org/api/references/plugin_api/classes/joplinsettings.html)
- [`joplin.views.panels`](https://joplinapp.org/api/references/plugin_api/classes/joplinviewspanels.html)

## Unsupported

- [`joplin.imaging`](https://joplinapp.org/api/references/plugin_api/classes/joplinimaging.html)
- [`joplin.views.noteList`](https://joplinapp.org/api/references/plugin_api/classes/joplinviewsnotelist.html)
- [`joplin.views.menus`](https://joplinapp.org/api/references/plugin_api/classes/joplinviewsmenus.html)
- [`joplin.window`](https://joplinapp.org/api/references/plugin_api/classes/joplinwindow.html)
- [`joplin.interop`](https://joplinapp.org/api/references/plugin_api/classes/joplininterop.html)
- [`joplin.require`](https://joplinapp.org/api/references/plugin_api/classes/joplin.html#require)

## API Notes

- There are almost certainly bugs in the APIs listed as "supported" above.
- `joplin.versionInfo()` has been extended to include a [`platform`](https://github.com/personalizedrefrigerator/joplin/blob/4e1d00ebd7d255cda07a63fc933122f5b4bb1534/packages/lib/services/plugins/api/types.ts#L231) key, which is set to `mobile` when running on mobile. This API is not finalized — it might be replaced with something similar to `joplin.isMobile()` or `joplin.platform.isMobile()`. ([Example usage](https://github.com/personalizedrefrigerator/joplin-plugin-revealjs-slides/blob/42eac586ce0b70bfd9796f5e52cae56b65822827/src/util/isMobile.ts#L3)).

## Development notes

Plugins can be loaded from `.jpl` files by clicking the "Install from file" button in plugin settings.

 ![screenshot: Arrow points to the "Install from file" button at the bottom of the "Plugins" section of the configuration screen](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/3/f/3fdc0bdadfbb8c77921c1ee1c04e042938f6a848.png)

If a plugin has uncaught errors/promise rejections, an "Error" button should be visible on that plugin's card in settings. It may be necessary to close and re-open settings for the button to be visible just after installing a plugin:

 ![Screenshot 2024-01-16 at 9.02.11 PM](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/9/d/9db3aae1ea7f7fb570707a678d1e3e5204ed7854.png)

Clicking that button should show entries in the application log that include the plugin's ID.

# Android APK

> **[Release Mobile Plugins — Prerelease 3 · personalizedrefrigerator/joplin](https://github.com/personalizedrefrigerator/joplin/releases/tag/prerelease-7)**
>
> Summary
> 
> Adds a dialog that shows panels associated with plugins.
> Bundles the example table of contents plugin by default.
> 
> Screenshot

> ****
>
> This APK is built from [the plugin support pull request](https://github.com/laurent22/joplin/pull/9652) and published under the "releases" page of my fork of Joplin on GitHub.
> 
> Before building, I first changed the application ID from `net.cozic.joplin` to `net.personalizedrefrigerator.joplin` (and renamed the app to `Joplin (Beta)`). Thus, the application can be installed alongside an existing version of Joplin without overwriting it.

# Feedback

Suggestions and feedback are welcome and can be posted in the comments below.

---

<div class="post-metadata">

**Author:** ![whitewall](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/whitewall/32/6018_2.png) [@whitewall](https://discourse.joplinapp.org/u/whitewall)\
**Post date:** [17 January 2024 05:34 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/2 "2024-01-17T05:34:15Z")

</div>

So far I have never needed plugins on mobile. But I highly appreciate your work on this. Thanks!

---

<div class="post-metadata">

**Author:** ![shikuz](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/shikuz/32/21839_2.png) [@shikuz](https://discourse.joplinapp.org/u/shikuz)\
**Post date:** [18 January 2024 10:26 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/3 "2024-01-18T10:26:45Z")

</div>

Looking forward to this! Thank you!

Will be interesting to see if the [Quick Links Plugin](https://discourse.joplinapp.org/t/quick-links-plugin/14214) works on mobile.

---

<div class="post-metadata">

**Author:** ![roman\_r\_m](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/roman_r_m/32/3297_2.png) [@roman\_r\_m](https://discourse.joplinapp.org/u/roman_r_m)\
**Post date:** [18 January 2024 10:40 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/4 "2024-01-18T10:40:38Z")

</div>

I'm pretty sure it won't because of this

> [@personalizedrefriger](#):
>
> Because the existing CodeMirror 6 plugin API includes a [compatibility layer](https://github.com/personalizedrefrigerator/joplin/blob/pr/mobile-plugin-support/load-jpl-via-expo/packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.ts), plugins that target CodeMirror 5 may work, depending on the features they use.

---

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [20 January 2024 21:59 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/5 "2024-01-20T21:59:05Z")

</div>

I've created a pull request that should add support for CodeMirror 6 to quick links:

> <https://github.com/roman-r-m/joplin-plugin-quick-links/pull/15>
>
> \# Summary
> 
> Adds support for the beta CodeMirror 6 editor.
> 
> Fixes #14.
> 
> \# N…otes
> 
> \- This pull request updates \`webpack.config.js\` and \`package.json\` to \[match an unreleased version of the Joplin plugin template\](https://github.com/laurent22/joplin/blob/dev/packages/generator-joplin/generators/app/templates/webpack.config.js). This is required to add CodeMirror 6 plugins.\[^1\]
> - To make this pull request easier to review, I did not commit changes to \`package-lock.json\`. I can add those changes to this pull request upon request.
> \- For the CodeMirror 6 extension to work, at least \[Joplin v2.14.6\](https://github.com/laurent22/joplin/releases/tag/v2.14.6) is required.
> - The plugin still works with CodeMirror 5 (tested in versions 2.12.15)
> \- For styles in the CodeMirror 6 editor to be properly applied, requires \[this Joplin pull request to be merged\](https://github.com/laurent22/joplin/pull/9748). Without this pull request, the default CodeMirror autocomplete menu styles are applied.
> 
> \[^1\]: The updated \`webpack.config.js\` prevents Webpack from creating duplicate copies of the CodeMirror 6 packages. Duplicate copies of these packages can break CodeMirror (or, more accurately, cause extensions to have no effect).
> 
> \# Testing
> 
> I've tested this pull request by:
> 1. Starting a development version of Joplin built from the v2.14.10 tag
> 2. Enabling the beta editor
> 3. Adding the Quick Links plugin as a development dependency and restarting
> 4. Enabling all Quick Links settings
> 5. Adding a link to another note with \`@@\` followed by that note's name
> 6. Accepting a completion by pressing \<kbd\>Enter\</kbd\>
> 7. Creating a to-do by typing \`@@Testing\`
> 8. Disabling all Quick Links settings
> 9. Creating a link to one of the welcome notes with the plugin
> 10. Repeating steps 3-8 for the legacy CodeMirror 5 editor
> 11. Repeating steps 3-8 for Joplin 2.12.15

---

<div class="post-metadata">

**Author:** ![Wladefant](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/wladefant/32/16820_2.png) [@Wladefant](https://discourse.joplinapp.org/u/Wladefant)\
**Post date:** [21 January 2024 09:19 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/6 "2024-01-21T09:19:25Z")

</div>

Same goes for the anchor link plugin. Does it work? Or as an alternative it could just be built into the default app experience

It apparently does work as far as the ui goes, and even displays the copied when pressed, but does not copy unfortunately  
 ![SmartSelect_20240121_124351_Joplin (Beta)](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/d/5/d52452e2fe5c4bad713ba9c3164df6722169bf1f.jpeg)

---

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [21 January 2024 19:47 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/7 "2024-01-21T19:47:23Z")

</div>

That should now be fixed! (I plan to release a new prerelease version later today.)

> **Information about the fix**
>
> A debug statement attempted to log plugin messages with `logger.debug`. That debug statement tried to convert a message sent by the anchor link plugin to a string, which failed with the error `TypeError: Cannot determine default value of object`.
> 
> Changing the log statement from
> 
> ```ts
> logger.debug(`Handling message from content script: ${contentScriptId}: ${message}`);
> 
> ```
> 
> to
> 
> ```ts
> logger.debug(`Handling message from content script: ${contentScriptId}:`, message);
> 
> ```
> 
> seems to fix the issue.

**Edit** : [APK with the fix.](https://github.com/personalizedrefrigerator/joplin/releases/tag/prerelease-6)

---

<div class="post-metadata">

**Author:** ![shikuz](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/shikuz/32/21839_2.png) [@shikuz](https://discourse.joplinapp.org/u/shikuz)\
**Post date:** [22 January 2024 03:35 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/8 "2024-01-22T03:35:01Z")

</div>

Thanks so much for your efforts. This will be an incredible upgrade to the mobile experience. I love the bundled line numbers (mostly thanks to the folding sections).

I understand that plugin panels may be a tricky thing to fully support, but perhaps in the future registered panels can add an icon to the top header, next to the the list of notebooks button. Then, when pressed, the panel may be rendered as a floating element, like the list of notebooks. I don't know what's the technical complexity of this, but if this is achievable at some point, it could make plugins almost as powerful as on the desktop. Features provided by the outline plugin, backlinks and such will benefit from this (much easier to navigate than via the rendered preview sections of `toc` or backlinks).

 ![Screenshot](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/0/3/03e7a5a520bc9075077a82eed009d8fa97db01e8.jpeg)

---

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [22 January 2024 14:29 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/9 "2024-01-22T14:29:43Z")

</div>

> [@shikuz](#):
>
> registered panels can add an icon to the top header, next to the the list of notebooks button

I like this idea!

Because phone screens can be small, it might make sense to show just one icon, then show a tabbed dialog (one tab per panel). For example,

 ![diagram: Plugin icon just to the left of the note actions menu opens a tabbed panel, panel 1 is mapped to the outline plugin](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/6/a/6a5f7b499e1e76799a94ea80fb3c2994f570cc22.png)

---

<div class="post-metadata">

**Author:** ![shikuz](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/shikuz/32/21839_2.png) [@shikuz](https://discourse.joplinapp.org/u/shikuz)\
**Post date:** [22 January 2024 22:59 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/10 "2024-01-22T22:59:06Z")

</div>

This would be totally amazing!

---

<div class="post-metadata">

**Author:** ![Wladefant](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/wladefant/32/16820_2.png) [@Wladefant](https://discourse.joplinapp.org/u/Wladefant)\
**Post date:** [23 January 2024 12:05 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/11 "2024-01-23T12:05:47Z")

</div>

First of all would love a pin button on the notebooks

 ![image](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/1/e/1e9542eaab45c7b98509b7a47f136470da64c810.png)  
Apparently obsidian does that too. Something similar would be needed  
 ![image](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/1/3/13f27011eca407dacd56aec86e43c36e393d5e2d.jpeg)

When talking about the panels, I would go for the easier solution that would make the same thing for desktop and mobile. I mean the editing bar is the same.

 ![image](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/d/f/df9ffdf62407b9d2554b5fc95ca9aaed174adc06.png)  
And most plugins are integrated there either way, so I would just say, make the same on mobile  
 ![image](https://canada1.discourse-cdn.com/flex028/uploads/cozic/original/3X/6/d/6d66152397215d46024976c047c31647d0405f66.png)

Even better (especially for small screens to have a button to change between the plugin buttons and editing buttons.

Edit: I now understand that we are talking about different things and they are both compatible and should be working quite well together.  
I agree with the panel views and that would help for consistency between desktop and mobile.  
The top bar should be fully hidden when the panels are activated and only when they are closed should the bar be visible once again. Another thing for example for the oultine plugin that you should keep in mind that when a link is clicked it should jump to the note to the heading

---

<div class="post-metadata">

**Author:** ![Wladefant](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/wladefant/32/16820_2.png) [@Wladefant](https://discourse.joplinapp.org/u/Wladefant)\
**Post date:** [23 January 2024 12:07 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/12 "2024-01-23T12:07:10Z")

</div>

Just saw the collapse button, quite nice, should be integrated into the Viewer too

---

<div class="post-metadata">

**Author:** ![Wladefant](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/wladefant/32/16820_2.png) [@Wladefant](https://discourse.joplinapp.org/u/Wladefant)\
**Post date:** [23 January 2024 12:09 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/13 "2024-01-23T12:09:46Z")

</div>

As expected the note tabs plugins does not work, but would be quite nice, if it could (at the bottom for example). Dont know what the complexity here is.

I can see that all the viewer plugins work good:

Anchor Links works  
Admonition works

---

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [24 February 2024 22:30 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/14 "2024-02-24T22:30:40Z")

</div>

This has been implemented!

The plugin panels dialog can be opened by clicking "show plugin panels" in the actions menu for a note. Currently, a note needs to be open to show or hide the plugin panels dialog.

---

<div class="post-metadata">

**Author:** ![shikuz](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/shikuz/32/21839_2.png) [@shikuz](https://discourse.joplinapp.org/u/shikuz)\
**Post date:** [25 February 2024 10:16 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/15 "2024-02-25T10:16:47Z")

</div>

This is very very cool, thank you @personalizedrefriger !!

I can confirm that the [Automatic Backlinks](https://discourse.joplinapp.org/t/automatic-backlinks-with-manual-insert-option/13632) panel (and preview section) seem to work on mobile out of the box, which is a great addition.

One thought regarding the implementation, is that currently access to panels requires at least 2 clicks (actions --\> show plugin panels), while a more optimized solution will require just 1 click to open the panel. Is this something that you can envision? I suggested a button on the header for this reason, but I'll be very grateful for any one-click solution that anyone comes up with.

I can also understand if at this point plugins on the mobile are not a priority feature (i.e., that requires quick access), but I do expect them to gain popularity and perhaps even become indispensable as they are currently on the desktop.

---

<div class="post-metadata">

**Author:** ![Medullitus](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/medullitus/32/19316_2.png) [@Medullitus](https://discourse.joplinapp.org/u/Medullitus)\
**Post date:** [28 February 2024 21:08 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/16 "2024-02-28T21:08:48Z")

</div>

A fantastic project!

Thank you very much @personalizedrefriger

---

<div class="post-metadata">

**Author:** ![cwhittl](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/cwhittl/32/20627_2.png) [@cwhittl](https://discourse.joplinapp.org/u/cwhittl)\
**Post date:** [6 March 2024 16:50 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/17 "2024-03-06T16:50:24Z")

</div>

If you need an IOS beta, let me know. I have a Dev account so I can deploy just might need some links on how to for this project.

---

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [9 March 2024 01:18 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/18 "2024-03-09T01:18:06Z")

</div>

The iOS AppStore guidelines has restrictions on 3rd-party code that we'll need to make sure we comply with. At the time of this writing, the guidelines were:

> **Guidelines**
>
> See [App Review Guidelines - Apple Developer](https://developer.apple.com/app-store/review/guidelines/#third-party-software)
> 
> > 4.7 Mini apps, mini games, streaming games, chatbots, and plug-ins
> > 
> > Apps may offer certain software that is not embedded in the binary, specifically mini apps, mini games, streaming games, chatbots, and plug-ins. You are responsible for all such software offered in your app, including ensuring that such software complies with these Guidelines and all applicable laws. Software that does not comply with one or more guidelines will lead to the rejection of your app. You must also ensure that the software adheres to the additional rules that follow in 4.7.1 and 4.7.5. These additional rules are important to preserve the experience that App Store customers expect, and to help ensure user safety.
> > 
> > **4.7.1** Software offered in apps under this rule must:
> > 
> > - follow all privacy guidelines, including but not limited to the rules set forth in Guideline 5.1 concerning collection, use, and sharing of data, and sensitive data (such as health and personal data from kids);
> > - include a method for filtering objectionable material, a mechanism to report content and timely responses to concerns, and the ability to block abusive users; and
> > - use in-app purchase in order to offer digital goods or services to end users.
> > 
> > **4.7.2** Your app may not extend or expose native platform APIs to the software without prior permission from Apple.  
> > **4.7.3** Your app may not share data or privacy permissions to any individual software offered in your app without explicit user consent in each instance.  
> > **4.7.4** You must provide an index of software and metadata available in your app. It must include universal links that lead to all of the software offered in your app.  
> > **4.7.5** Your app must share the age rating of the highest age-rated content available in your app.

As such, before creating a version that can be distributed for iOS, I suspect that we'll need to allow only a specific set of plugins and versions (though perhaps the restrictions are different for TestFlight?). We may also need to get permission from Apple to allow plugins to access the clipboard (which currently uses a native API) and Joplin's database (this includes access to notes).

---

<div class="post-metadata">

**Author:** ![personalizedrefriger](https://yyz2.discourse-cdn.com/flex028/user_avatar/discourse.joplinapp.org/personalizedrefriger/32/13210_2.png) [@personalizedrefriger](https://discourse.joplinapp.org/u/personalizedrefriger)\
**Post date:** [21 March 2024 23:56 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/19 "2024-03-21T23:56:47Z")

</div>

Mobile plugin support has been merged and should be present in the Joplin v3.0.1 [pre-release](https://joplinapp.org/help/about/changelog/android) for Android:

> **[Release android-v3.0.1 · laurent22/joplin-android](https://github.com/laurent22/joplin-android/releases/tag/android-v3.0.1)**
>
> Android releases for Joplin. Contribute to laurent22/joplin-android development by creating an account on GitHub.

See the following GitHub issue for more information about plans for plugin support on iOS:

> <https://github.com/laurent22/joplin/issues/10154>
>
> \### Operating system
> 
> iOS
> 
> \### Joplin version
> 
> 3
> 
> \### Desktop version in…fo
> 
> \_No response\_
> 
> \### Current behaviour
> 
> Currently, plugin support is disabled in the iOS app because of \[this section of the iOS AppStore guidelines\](https://developer.apple.com/app-store/review/guidelines/#third-party-software) (accessed March 18 2024):
> 
> \> \*\*4.7 Mini apps, mini games, streaming games, chatbots, and plug-ins\*\*
> \> 
> \> Apps may offer certain software that is not embedded in the binary, specifically mini apps, mini games, streaming games, chatbots, and plug-ins. You are responsible for all such software offered in your app, including ensuring that such software complies with these Guidelines and all applicable laws. Software that does not comply with one or more guidelines will lead to the rejection of your app. You must also ensure that the software adheres to the additional rules that follow in 4.7.1 and 4.7.5. These additional rules are important to preserve the experience that App Store customers expect, and to help ensure user safety.
> \> 
> \> - \*\*4.7.1\*\* Software offered in apps under this rule must:
> \> - follow all privacy guidelines, including but not limited to the rules set forth in Guideline 5.1 concerning collection, use, and sharing of data, and sensitive data (such as health and personal data from kids);
> \> - include a method for filtering objectionable material, a mechanism to report content and timely responses to concerns, and the ability to block abusive users; and
> \> - use in-app purchase in order to offer digital goods or services to end users.
> \> - \*\*4.7.2\*\* Your app may not extend or expose native platform APIs to the software without prior permission from Apple.
> \> - \*\*4.7.3\*\* Your app may not share data or privacy permissions to any individual software offered in your app without explicit user consent in each instance.
> \> - \*\*4.7.4\*\* You must provide an index of software and metadata available in your app. It must include universal links that lead to all of the software offered in your app.
> \> - \*\*4.7.5\*\* Your app must share the age rating of the highest age-rated content available in your app.
> 
> To support this, we will likely need to:
> 1. Review and approve a subset of plugins.
> 2. Disable access to certain parts of the plugin API (e.g. clipboard access) on iOS.
> 
> \## Supporting plugin review
> 
> Here are a few ideas for how we might support only showing reviewed plugins on iOS:
> 
> \> \[!NOTE\]
> \>
> \> Both of the ideas mentioned below continue to use GitHub as the source for downloading plugins. Depending on how trusted \[the GitHub mirrors\](https://github.com/laurent22/joplin/blob/56b010ba0ea22b03619f387ecfd428837095f761/packages/lib/services/plugins/RepositoryApi.ts#L19) are, we may need to disable them on iOS. Alternatively, reviewed plugins could be signed.
> \>
> 
> 
> \### 1. Create a separate repository for reviewed plugins
> 
> This repository could be located at \`joplin/plugins-reviewed\` or perhaps be a separate branch of the existing plugin repository. Joplin maintainers manually update plugins in this repository after reviewing them.
> 
> With this method, the plugin review process would be similar to the following:
> 1. A maintainer either
> 1. Reviews the source code of the plugin locally, then builds the plugin and uploads it to the "reviewed" repository, or
> 2. Extracts the plugin, reviews the (probably minified) JavaScript source, then uploads the \`.jpl\` file to the private repository.
> 
> \*\*Pros\*\*:
> - This method should require very little code change on iOS.
> - We could support this by using a different plugin repository URL (this could be changed \[here\](https://github.com/laurent22/joplin/blob/56b010ba0ea22b03619f387ecfd428837095f761/packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useRepoApi.ts#L19)).
> \- We could more easily have the @joplinbot build plugins from a specific commit and auto-upload to the repository.
> 
> \*\*Cons\*\*:
> \- The plugin repository would be split across two GitHub repositories or branches. This may make it more difficult to work with (e.g. when reviewing plugins).
> \- If we want to show certain plugins/versions as \`reviewed\` on other clients, the client will need to check both repositories.
> - All plugins in the \`reviewed\` repository will be older versions of plugins in the main plugin repository. As such, reviewed plugins will need to update from the reviewed repository and not the main repository. To support this on non-iOS clients, we'll need to store additional data (e.g. add a \`\_reviewed\` manifest key).
> 
> \### 2. Create a new \`reviewed\` subdirectory in the \[\`@joplin/plugins\`\](https://github.com/joplin/plugins/tree/master) repository
> 
> The review process for this option would be very similar to the process outlined above for option 1. 
> 
> \*\*Pros\*\*:
> \- We still only need one plugin repository/branch.
> \- Creating a separate folder for reviewed plugins makes them easier to find and update.
> 
> \*\*Cons\*\*:
> \- May be more complicated to implement than option \`1\`.
> 
> \### 3. Add a new private manifest property that indicates the last reviewed commit
> 
> A new private manifest key (\[similar to \`\_recommended\`\](https://github.com/laurent22/joplin/blob/0715340dc0437efe785b227c2ea61820728b0485/packages/plugin-repo-cli/lib/validateUntrustedManifest.ts#L17)), \`\_lastReviewedCommit\` could be assigned to plugins using \[\`manifestOverrides.json\`\](https://github.com/joplin/plugins/blob/master/manifestOverrides.json). On iOS, plugins would then be downloaded using the JPL from that commit. The download URL might then, for example, be \`https://github.com/joplin/plugins/raw/e45d1b6361e986a88ff2bb63a51134588b5991f6/plugins/io.github.personalizedrefrigerator.joplin-vimrc/plugin.jpl\`.
> 
> The plugin review process would then be similar to the following:
> 1. A maintainer downloads a plugin's \`.jpl\` file from a specific commit, then extracts it and reviews the (probably minified) JavaScript).
> - Note: \`.jpl\` files can also be inspected using the \[Plugin Website\](https://joplinapp.org/plugins/view-source.html?plugin=io.github.personalizedrefrigerator.joplin-vimrc#index.js) by drag-and-dropping a \`.jpl\` file into the source viewer, which can format minified files with \`prettier\`.
> - We could also encourage plugin authors to \[disable minification\](https://webpack.js.org/configuration/optimization/#optimizationminimize) to make the review process easier.
> 2. After reviewing, a \`\_lastReviewedCommit\` field can be added to \[\`manifestOverrides.json\`\](https://github.com/joplin/plugins/blob/master/manifestOverrides.json) to indicate which commit was last reviewed.
> 
> 
> \*\*Pros\*\*:
> \- No need to maintain multiple plugin repositories.
> \- No need to change the overall structure of the main plugin repository.
> 
> \*\*Cons\*\*:
> \- We can't build plugins' \`.jpl\` files ourselves when reviewing.
> - This could be fine, particularly if we encourage plugin developers to create \[NPM packages that are verifiably linked to a CI build\](https://github.blog/2023-04-19-introducing-npm-package-provenance/) for their plugins.
> \- Likely requires more code changes than option 1.
> \- May be unable to use mirrors to download plugins from a specific commit.

---

<div class="post-metadata">

**Author:** ![crtkugrrvjy](https://avatars.discourse-cdn.com/v4/letter/c/6bbea6/32.png) [@crtkugrrvjy](https://discourse.joplinapp.org/u/crtkugrrvjy)\
**Post date:** [25 March 2024 19:54 UTC](https://discourse.joplinapp.org/t/mobile-plugin-support/35262/20 "2024-03-25T19:54:27Z")

</div>

Amazing work thank you!

Embedded Search works!

[Next page](https://discourse.joplinapp.org/t/mobile-plugin-support/35262.md?page=2)
