Plugin Development
Getting Started

Getting Started with Plugins

Create your first custom plugin for FeedGen CMS.

Prerequisites

  • A FeedGen CMS website
  • Basic JavaScript knowledge
  • A text editor

Step 1: Create Plugin Folder

Create a new folder for your plugin:

my-plugin/
├── plugin.json         # Plugin manifest (required)
├── index.js            # Plugin entry point (required)
└── assets/             # Optional static files
    ├── css/
    └── js/

Step 2: Create plugin.json

The manifest file defines your plugin:

plugin.json
{
  "name": "My Plugin",
  "version": "1.0.0",
  "description": "A custom plugin for my website",
  "author": "Your Name",
  "license": "MIT",
  
  "main": "index.js",
  
  "permissions": [
    "content:read",
    "hooks"
  ],
  
  "settings": [
    {
      "key": "enabled",
      "type": "boolean",
      "label": "Enable Feature",
      "default": true
    },
    {
      "key": "apiKey",
      "type": "text",
      "label": "API Key",
      "default": ""
    }
  ]
}

Available Permissions

PermissionDescription
content:readRead posts, categories, authors, tags
content:writeCreate/edit/delete content
media:readAccess media library
media:writeUpload/delete media
settings:readRead site settings
settings:writeModify site settings
hooksUse hooks and filters
shortcodesRegister shortcodes
widgetsRegister widgets
adminAdd admin pages
restCreate REST endpoints

Step 3: Create index.js

The entry point for your plugin:

index.js
module.exports = async function(sdk) {
  // Plugin initialization code
  console.log('My plugin loaded!');
  
  // Access plugin settings
  const settings = await sdk.storage.get('settings') || {};
  
  // Return lifecycle methods
  return {
    activate: async () => {
      // Called when plugin is activated
      console.log('Plugin activated!');
    },
    
    deactivate: async () => {
      // Called when plugin is deactivated
      console.log('Plugin deactivated!');
    },
    
    uninstall: async () => {
      // Called when plugin is uninstalled
      // Clean up any stored data
      await sdk.storage.delete('settings');
    }
  };
};

Step 4: Add Functionality

Add a Shortcode

index.js
module.exports = async function(sdk) {
  
  // Register a simple shortcode
  // Usage: [greeting name="John"]
  sdk.shortcodes.register('greeting', (attrs, content) => {
    const name = attrs.name || 'Friend';
    return `<div class="greeting">
      <p>Hello, ${name}! 👋</p>
    </div>`;
  });
  
  return { activate: async () => {}, deactivate: async () => {} };
};

Add a Hook

index.js
module.exports = async function(sdk) {
  
  // Modify post titles
  sdk.hooks.addFilter('post.title', (title) => {
    return `📝 ${title}`;
  }, 10); // priority
  
  // Do something when a post is viewed
  sdk.hooks.addAction('post.viewed', async (post) => {
    console.log(`Post viewed: ${post.title}`);
  });
  
  return { activate: async () => {}, deactivate: async () => {} };
};

Register a Widget

index.js
module.exports = async function(sdk) {
  
  sdk.widgets.registerWidget('recent-comments', {
    name: 'Recent Comments',
    description: 'Display recent comments',
    icon: '💬',
    settings: [
      { key: 'title', type: 'text', label: 'Title', default: 'Recent Comments' },
      { key: 'count', type: 'number', label: 'Number to show', default: 5 }
    ],
    render: async (settings) => {
      // Widget HTML
      return `
        <div class="widget recent-comments">
          <h3>${settings.title}</h3>
          <p>Comments would go here...</p>
        </div>
      `;
    }
  });
  
  return { activate: async () => {}, deactivate: async () => {} };
};

Step 5: Upload Your Plugin

  1. Zip your plugin folder
  2. Go to Admin Panel → Plugins
  3. Click Upload Plugin
  4. Select your zip file
  5. Click Activate to enable your plugin

Complete Example

Here's a complete plugin that adds a "Read Time" feature:

plugin.json
{
  "name": "Read Time",
  "version": "1.0.0",
  "description": "Display estimated reading time on posts",
  "author": "Your Name",
  "main": "index.js",
  "permissions": ["hooks"]
}
index.js
module.exports = async function(sdk) {
  
  // Calculate reading time
  function calculateReadTime(content) {
    const text = content.replace(/<[^>]*>/g, ''); // Strip HTML
    const words = text.split(/\s+/).length;
    const minutes = Math.ceil(words / 200); // 200 words per minute
    return minutes;
  }
  
  // Add reading time to post data
  sdk.hooks.addFilter('post.data', (post) => {
    if (post.content) {
      post.readTime = calculateReadTime(post.content);
    }
    return post;
  }, 10);
  
  // Register shortcode to display it
  sdk.shortcodes.register('read-time', (attrs) => {
    const minutes = attrs.minutes || 1;
    return `<span class="read-time">📖 ${minutes} min read</span>`;
  });
  
  return {
    activate: async () => {
      console.log('Read Time plugin activated');
    },
    deactivate: async () => {
      console.log('Read Time plugin deactivated');
    }
  };
};

Now in your theme, you can use:

<span>{{ post.readTime }} min read</span>

Or with the shortcode in content:

[read-time minutes="5"]

Next Steps