Skip to content

Write a plugin

A plugin teaches Yonto to read one kind of site or server. Yonto’s own plugins for Jellyfin, Plex and Emby are written the same way as the one you will write.

A plugin is one JavaScript file. Its manifest, which says who it is and where it may reach, is a comment at the top of that file. The rest of the file exports a few functions: list the categories, list the titles in one, describe one title and search. Yonto calls them, and shows what they return.

/* yonto-plugin
{ "kind": "content-source", "id": "video-blog", "name": "Video blog", "version": "1.0.0",
"contractVersion": 21, "provides": "source-type", "allowedHosts": [],
"configSchema": [{ "id": "feedUrl", "label": "Feed URL", "type": "url", "required": true }] }
*/
export default {
async getCategories() { /* … */ },
async getMediaList(categoryId, { page }) { /* … */ },
async getMediaDetail(id) { /* … */ },
async search(query) { /* … */ },
};
  • Node.js 20 or later and git, for the command-line tool, yonto-plugin. It lints, runs and diagnoses a plugin on your computer, with no television, emulator or Android SDK.
  • A text editor.
  • A site or server to read, and the right to read it.

The tool is in kangzj/yonto-plugins on GitHub, with the plugin contract and Yonto’s own plugins for Jellyfin, Plex, Emby, MacCMS and XPTV, all under the MIT licence. Install it from there:

Terminal window
git clone https://github.com/kangzj/yonto-plugins.git
cd yonto-plugins
npm ci --prefix tools/plugin-cli
npm install -g ./tools/plugin-cli

Then run it as yonto-plugin <command>. Most commands take the plugin’s directory and default to the one you are in. Yonto’s own plugins in that repository are worked examples, and most come with recordings, so yonto-plugin doctor plugins/jellyfin --replay runs one without a server.

Terminal window
yonto-plugin init my-site

This creates my-site/ with a plugin that already passes lint and doctor, so you can see the whole loop before you change anything. Choose another starting point with --template, and name the plugin with --name.

Template What it is
blank The default. The four required functions answering one made-up title, with no network.
video-blog The plugin built in the tutorial: a blog’s RSS feed, with a recorded feed that doctor --replay runs offline.

The id is 2 to 32 lowercase letters, digits and hyphens, and init refuses a directory that exists.

A plugin does not run in Node.js or in a browser. It runs in QuickJS, a small JavaScript engine, the same one inside Yonto on a television and inside yonto-plugin on your computer. That is what makes a plugin that passes on your computer a plugin that works on a television.

There is no URL, URLSearchParams, TextDecoder, Buffer, console, setTimeout or Intl. Everything that reaches outside the plugin goes through one global, yonto: yonto.fetch for requests, yonto.log for logs, yonto.store for a small cache, and a few parsers. The plugin reference lists all of it.

  1. Take your video blog to TV builds a working plugin from an RSS feed, start to finish, and is the quickest way to see all the parts.
  2. Plugin reference is the manifest, the methods, the yonto global, the errors and the limits.
  3. Test and debug covers lint, run, doctor and fixtures.
  4. Publish and security covers sharing a plugin, making a repo, and what a viewer is asked when they install yours.