---
title: Castopod Plugins
---

import { FileTree, Aside, Tabs, TabItem } from "@astrojs/starlight/components";

Plugins are ways to extend Castopod's core features.

## Plugin folder structure

<FileTree>
  * hello-world
    * i18n
      * en.json
      * fr.json
      * …
    * icon.svg
    * manifest.json // required
    * Plugin.php // required
    * README.md
</FileTree>

Plugins reside in the `plugins/` directory under a `vendor/` folder, ie. the
organisation or person who authored the plugin.

<FileTree>
  * **plugins**
    * acme
      * hello-world/
      * …
    * atlantis/
</FileTree>

### Plugin manifest (required)

The plugin manifest is a JSON file containing the plugin's metadata and
declarations.

This file will determine whether a plugin is valid or not. The minimal required
data being:

```json
// manifest.json
{
  "name": "acme/hello-world",
  "version": "1.0.0"
}
```

Checkout the [manifest.json reference](./manifest).

### Plugin class (required)

This is where the plugin's logic lives.

The Plugin class extends Castopod's BasePlugin class and implements one or more
[Hooks](./hooks) (methods) intended to be run throughout Castopod's codebase.

```php
// Plugin.php
<?php

declare(strict_types=1);

use Modules\Plugins\Core\BasePlugin;

class AcmeHelloWorldPlugin extends BasePlugin
{
    // this rssBeforeChannel method is a Hook
    public function rssBeforeChannel(Podcast $podcast): void
    {
        // …
    }
}
```

<Aside type="note">
  The Plugin class name is determined by its `vendor/name` pair.\
  For example, a plugin living under the `acme/hello-world` folder must be named
  `AcmeHelloWorldPlugin`:

  * the first letter of every word is capitalized (ie. PascalCase)
  * any special caracter is removed
  * the `Plugin` suffix is added
</Aside>

### Plugin README

The `README.md` file is loaded into the plugin's view page for the user to read
through.\
It should be used for any additional information to help guide the user in using
the plugin.

### Plugin icon

The plugin icon is displayed next to its title, it is an SVG file intended to
give a graphical representation of the plugin.

The icon should be squared, and be legible in a 64px by 64px circle.

### Internationalization (i18n)

Plugins can be translated. Translation strings live inside the `i18n` folder.
Translation files are JSON files named as locale keys:

<FileTree>
  * **i18n**
    * en.json // default locale
    * fr.json
    * de.json
    * …
</FileTree>

Supported locales are:
`br`,`ca`,`de`,`en`,`es`,`fr`,`nn-no`,`pl`,`pt-br`,`sr-latn`,`zh-hans`.

The translation strings allow you to translate the title, description and
settings keys (ie. labels, hints, helpers, etc.).

<Tabs>
  <TabItem label="English">
    ```json
    // i18n/en.json
    {
      "title": "Hello, World!",
      "description": "A Castopod plugin to greet the world!",
      "settings": {
        "general": {
          "field-key": {
            "label": "Enter a text",
            "hint": "You can enter any type of character."
          }
        },
        "podcast": {},
        "episode": {}
      }
    }
    ```
  </TabItem>

  <TabItem label="French">
    ```json
    // i18n/fr.json
    {
      "title": "Bonjour, le Monde !",
      "description": "Un plugin castopod pour saluer le monde !",
      "settings": {
        "general": {
          "field-key": {
            "label": "Saisissez un texte",
            "hint": "Vous pouvez saisir n'importe quel type de caractère."
          }
        },
        "podcast": {},
        "episode": {}
      }
    }
    ```
  </TabItem>
</Tabs>
