# What is a plugin

A plugin is a self-contained package that extends Celena without changing its core. It can:

- add pages to the admin and/or the front;
- register new template-engine tags and async blocks;
- subscribe to core hooks (`news.published`, `user.registered`, etc.) and emit its own;
- have its own migrations, models and services;
- be distributed via the marketplace or manually (zip).

A key principle: **the core is self-sufficient**. Everything works without a plugin; a plugin only extends through hooks and does not modify the core. Plugins can be enabled and disabled in the **Plugins** section of the control panel.

## Structure

```
plugins/<slug>/
├── manifest.json     metadata (required)
├── plugin.php        entry point (required)
├── README.md         recommended
├── migrations/       DB migrations (optional)
├── src/              PHP classes (PSR-4 Celena\Plugin\<Slug>\)
│   ├── Controllers/
│   ├── Admin/
│   ├── Repositories/
│   └── Support/
├── templates/        plugin .tpl (admin and front)
├── languages/        ru.json, en.json, etc.
├── assets/           CSS/JS → copied to public/assets/plugins/<slug>/
└── docs/             plugin Markdown documentation
```

## manifest.json

```json
{
  "slug": "shop",
  "name": "Online store",
  "version": "1.0.0",
  "author": "Celena",
  "description": "Catalog, cart, orders, payments.",
  "requires": { "php": ">=8.3", "celena": ">=1.0", "plugins": [] },
  "permissions": ["news.read", "options.write"],
  "migrations": "migrations/"
}
```

The `slug` field is required and must match `^[a-z0-9][a-z0-9_\-]*$`. The folder name = `slug`.

## How the core finds and loads plugins

1. `PluginManager::discover()` scans `plugins/*` and reads each `manifest.json`.
2. The list of active plugins is stored in the `active_plugins` option (a JSON array of slugs in the `cl_celena_options` table).
3. For active plugins `PluginManager::load()`:
   - registers the `Celena\Plugin\<Slug>\` namespace → `plugins/<slug>/src/`;
   - includes `plugin.php` (where routes, hooks and tags are registered);
   - syncs `assets/` to `public/assets/plugins/<slug>/`.

Enabling/disabling a plugin = adding/removing its slug in `active_plugins` (via the admin). Migrations run on first enable.

## Reference plugins

The bundle ships with working plugins — study them as templates:

- `plugins/leads/` — a form builder and lead intake (forms, honeypot, export, injecting the form into the landing). A good minimal example.
- `plugins/analytics/` — first-party analytics (tracker, events, goals, dashboard).
- `plugins/shop/` — a large e-commerce plugin (catalog, cart, orders) — an example of a big plugin.

Next — [building a plugin step by step](/docs/code/plugin-create).
