Craft 3 Documentation

Intro to Plugin Dev

What are Plugins? #

Plugins are mini applications that run alongside Craft’s core code. They can be simple, serving a single purpose like providing a new Dashboard widget type, or they can be complex, introducing entirely new concepts to the system, like an e-commerce application. Craft’s plugin architecture provides a solid foundation for building just about anything.

Technically, plugins are a superset of Yii Modules, which means they can have models, active record classes, controllers, application components, and other things. It wouldn’t hurt to take some time to read up on those concepts if you are new to Yii.

The main benefits of Craft Plugins over Yii Modules are:

Getting Started #

Use [] to create your plugin’s scaffolding with just a few clicks.

Preparation #

Before you begin working on a plugin, you need to decide on a few things:

Naming things is one of the two hardest things in computer science, so if you can make a decision on those things, the rest of the plugin should practically write itself.

Setting up the basic file structure #

To create a plugin, create a new directory for it somewhere on your computer. A common approach is to store them in a ~/dev/ folder alongside your Craft projects:


The name of your plugin directory doesn’t matter. Just choose something that is easy to identify.

composer.json #

Whether or not you wish to make your plugin available as a Composer dependency (you probably should), your plugin must have a composer.json file. Craft will check this file to get basic information about the plugin.

Use this template as a starting point for your composer.json file:

  "name": "package/name",
  "description": "Your plugin’s package description",
  "version": "1.0.0",
  "type": "craft-plugin",
  "minimum-stability": "dev",
  "require": {
    "craftcms/cms": "^3.0.0-RC1"
  "autoload": {
    "psr-4": {
      "ns\\prefix\\": "src/"
  "support": {
    "email": ""
  "extra": {
    "handle": "plugin-handle",
    "name": "Plugin Name",
    "developer": "Developer Name",
    "developerUrl": ""


Here’s a full list of the properties that can go in that extra object:

Don’t include composer/installers as a Composer dependency.

While not strictly required by Composer, we recommend you explicitly set the version in your composer.json because it makes a couple things easier on your when developing the plugin. Don’t forget to keep it updated though!

Primary Plugin Class #

The src/Plugin.php file is your plugin’s primary class. It will get instantiated at the beginning of every request. Its init() method is the best place to register event listeners, and any other steps it needs to take to initialize itself.

Use this template as a starting point for your Plugin.php file:

namespace ns\prefix;

class Plugin extends \craft\base\Plugin
    public function init()

        // Custom initialization code goes here...

Replace ns\prefix with your plugin’s namespace prefix.

Loading your plugin into a Craft project #

To get Craft to see your plugin, you will need to install it as a Composer dependency of your Craft project. There are multiple ways to do that:

Path Repository #

During development, the easiest way to work on your plugin is with a path repository, which will tell Composer to symlink your plugin into the vendor/ folder right alongside other dependencies.

To set it up, open your Craft project’s composer.json file and make the following changes:

  "minimum-stability": "dev",
  "prefer-stable": true,
  "repositories": [
      "type": "path",
      "url": "../my-plugin"

Set the url value to the absolute or relative path to your plugin’s source directory. (The ../my-plugin example value assumes that the plugin lives in a folder alongside the project’s folder.)

In your terminal, go to your Craft project and tell Composer to require your plugin. (Use the same package name you gave your plugin in its composer.json file.)

> cd ~/dev/my-craft-project
> composer require package/name

Composer’s installation log should indicate that the package was installed via a symlink:

  - Installing package/name (X.Y.Z): Symlinking from ../my-plugin

One caveat of path Composer repositories is that Composer will ignore path-based dependencies when you run composer update. So any time you change anything in composer.json, such as your plugin’s dependency requirements or its plugin information, you will need to completely remove and re-require your plugin in your project for those changes to take effect.

> cd ~/dev/my/craft-project
> composer remove package/name
> composer require package/name

Packagist #

If you’re ready to publicly release your plugin, register it as a new Composer package on Packagist. Then you can install it like any other package, by just passing its package name to Composer’s require command.

> cd ~/dev/my-craft-project
> composer require package/name

Plugin Icons #

Plugins can provide an icon, which will be visible on the Settings → Plugins page.

The Settings → Plugins page in Craft’s Control Panel.

Plugin icons must be square SVG files, saved as icon.svg at the root of your plugin’s source directory (e.g src/).

If your plugin has a Control Panel section, you can also give its global nav item a custom icon by saving an icon-mask.svg file in the root of your plugin’s source directory. Note that this icon cannot contain strokes, and will always be displayed in a solid color (respecting alpha transparency).