Skip to content
Go back

Building a Custom Strapi v5 Plugin for Admin Panel

Building a Custom Strapi v5 Plugin for Admin Panel

Introduction

Strapi v5 plugins extend the admin panel with custom functionality using the Plugin SDK. This guide covers creating, developing, and integrating a plugin that works exactly like built-in plugins or 3rd-party plugins from the Marketplace.

Prerequisites

Step 1: Create Plugin Using Plugin SDK

cd my-strapi-project
npm create strapi-plugin@latest custom-plugin

This creates plugins/custom-plugin with the proper Strapi v5 structure.

Step 2: Plugin Structure Overview

Strapi v5 plugins have a structured approach with:

Step 3: Define Server Entry Point

Edit plugins/custom-plugin/server/index.js:

"use strict";

module.exports = ({ strapi }) => {
  return {
    async initialize() {
      strapi.log.info("Custom Plugin Initialized");

      // Register routes
      strapi.server.routes([
        {
          method: "GET",
          path: "/custom/hello",
          handler: "custom-plugin.hello",
          config: { auth: false },
        },
      ]);
    },
  };
};

Step 4: Add Server Logic

Create plugins/custom-plugin/server/controllers/custom-plugin.js:

"use strict";

module.exports = {
  async hello(ctx) {
    ctx.body = {
      message: "Hello from Strapi v5 custom plugin!",
      version: "5.0.0",
    };
  },
};

Step 5: Extend Admin UI with Admin Panel API

In plugins/custom-plugin/admin/src/index.js:

import pluginPkg from "../../package.json";

export default strapi => {
  const pluginName = pluginPkg.strapi.name;

  return {
    register(app) {
      // Add menu link to admin sidebar
      app.addMenuLink({
        to: `/plugins/${pluginName}`,
        icon: "plugin",
        intlLabel: {
          id: `${pluginName}.plugin.name`,
          defaultMessage: "Custom Plugin",
        },
        Component: async () => {
          const component = await import(
            /* webpackChunkName: "custom-plugin-page" */ "./pages/App"
          );
          return component;
        },
      });

      // Add plugin settings
      app.addSettingsLink("global", {
        intlLabel: {
          id: `${pluginName}.plugin.settings`,
          defaultMessage: "Custom Plugin Settings",
        },
        id: "custom-plugin-settings",
        to: `/settings/custom-plugin`,
        Component: async () => {
          const component = await import("./pages/Settings");
          return component;
        },
      });
    },
  };
};

Create plugins/custom-plugin/admin/src/pages/App/index.js:

import React from "react";
import { request } from "@strapi/helper-plugin";
import { Main, ContentLayout, HeaderLayout } from "@strapi/design-system";

const App = () => {
  const [message, setMessage] = React.useState("");
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    request("/custom/hello", { method: "GET" })
      .then(data => {
        setMessage(data.message);
        setLoading(false);
      })
      .catch(error => {
        console.error("Error fetching data:", error);
        setLoading(false);
      });
  }, []);

  return (
    <Main>
      <HeaderLayout title="Custom Plugin" subtitle="Strapi v5 Plugin Example" />
      <ContentLayout>
        {loading ? (
          <div>Loading...</div>
        ) : (
          <div>
            <h3>{message}</h3>
            <p>This is a custom plugin page in Strapi v5!</p>
          </div>
        )}
      </ContentLayout>
    </Main>
  );
};

export default App;

Step 6: Plugin Configuration

Add plugin configuration in config/plugins.js:

module.exports = {
  "custom-plugin": {
    enabled: true,
    config: {
      // Plugin-specific configuration
      apiKey: process.env.CUSTOM_PLUGIN_API_KEY,
      features: ["feature1", "feature2"],
    },
  },
};

Step 7: Build and Test

Restart Strapi to load the plugin:

npm run develop

Your plugin will appear in the admin sidebar and can be used as a local plugin or submitted to the Marketplace.

Advanced Features

Custom Fields Plugin

Plugins can also be used to add custom fields to Strapi:

module.exports = {
  type: "string",
  name: "customField",
  intlLabel: {
    id: "custom-plugin.customField",
    defaultMessage: "Custom Field",
  },
  intlDescription: {
    id: "custom-plugin.customField.description",
    defaultMessage: "A custom field for your content",
  },
};

Data Storage

Store and access data from your plugin:

module.exports = ({ strapi }) => ({
  async storeData(data) {
    return await strapi.entityService.create("plugin::custom-plugin.data", {
      data,
    });
  },

  async getData(id) {
    return await strapi.entityService.findOne("plugin::custom-plugin.data", id);
  },
});

Summary

Creating a custom Strapi v5 plugin involves using the Plugin SDK, defining server logic with the Server API, and extending the admin UI with the Admin Panel API. This provides tailored CMS features without modifying core code and allows for both local use and Marketplace distribution.


Share this post on:

Previous Post
Monitoring VPS with Prometheus + Grafana
Next Post
Using Caddy Server with VPS for Automatic HTTPS