# 04 · Add a plugin

Adding a capability to the app is one line of JSON. You turn on a catalog plugin in the manifest and the navigation and screens grow on their own — you don't write routes, the core derives them from the plugin.

## Turn the plugin on in the manifest

The plugin packages already ship in the generated app's dependencies — `@fayz-ai/plugin-crm`, `plugin-tasks`, `plugin-agenda`, `plugin-financial`, `plugin-inventory` and others are already in `package.json`. Turning one on means adding its `id` to the surface's `plugins` list.

Open `app.manifest.json` and add `crm` (and, as a bonus, `tasks`) alongside `dashboard`:

```json
{
  "surfaces": {
    "admin": {
      "scaffold": "admin",
      "plugins": [
        { "id": "dashboard" },
        { "id": "crm" },
        { "id": "tasks" }
      ]
    }
  }
}
```

Save. You do **not** need to touch `src/plugins.generated.ts` for now — the local preview validates the wiring through the manifest; the full screens come from the runtime that consumes this same list.

## Confirm with doctor

```bash
npx @fayz-ai/cli doctor
```

```
⚠ manifest references plugin(s) [dashboard, crm, tasks] — each id must resolve to an installed @fayz-ai/plugin-* factory wired in src/plugins.generated.ts or src/config/app.tsx

0 error(s), 1 warning(s)
```

Notice the list in the warning grew: `dashboard, crm, tasks`. Doctor is reading the manifest and reminding you that each id needs to match an installed `@fayz-ai/plugin-*` package — which already came with the generated app's dependencies.

{% callout type="tip" %}
✓ You should see: all three ids — `dashboard, crm, tasks` — in the doctor warning, with `0 error(s)`. If you type an id that doesn't exist in the catalog, this is where the error shows up.
{% /callout %}

## What happens to the navigation

Each plugin declares its own navigation and routes in the plugin manifest. When you turn it on in a surface, the platform runtime injects the menu item and the matching screens — CRM adds the contacts section, Tasks adds the task board. That's why you never edit a router: navigation is derived from the plugin list.

{% callout type="info" %}
Where the change shows up: plugin screens and menus are rendered by the full Fayz platform runtime, which consumes this same list. Today's local preview is an anchor screen, so this step is validated with `doctor` (the capability is correctly wired). To browse the full catalog of available plugins, see the [Plugins](/en/docs/plugins) section.
{% /callout %}

Before moving on, leave only `dashboard` in the list if you want a lean app for the next step — or keep all three; either works with Supabase.

---

[← Previous: 03 · Theme and brand](/en/docs/tutorial/03-theme-and-brand) · [Next: 05 · Real data with Supabase →](/en/docs/tutorial/05-real-data-with-supabase)
