Developer Portal
Plugin Development

Plugin Quick Start Guide

Build your first AIPostify plugin in under 10 minutes. This guide walks you through folder structure, the BasePlugin class, lifecycle hooks, and the plugin.json manifest.

📦 Example Plugin: postify-announcements

All code examples reference the real, working postify-announcements plugin included in the AIPostify codebase at content/plugins/postify-announcements/.

1. Folder Structure

Every plugin lives inside content/plugins/<your-plugin-slug>/. Here's the minimal structure:

content/plugins/my-first-plugin/
├── plugin.json          # Manifest (required)
├── MyFirstPlugin.php    # Main class extending BasePlugin (required)
├── views/
│   └── admin/
│       └── settings.blade.php
└── assets/
    ├── css/
    └── js/

The postify-announcements plugin follows this exact structure. Check its PostifyAnnouncements.php main class for a real-world reference.

2. Create plugin.json

This manifest file describes your plugin to the AIPostify core and the Marketplace:

{
    "name": "My First Plugin",
    "slug": "my-first-plugin",
    "version": "1.0.0",
    "description": "A demo plugin to learn the AIPostify plugin API.",
    "author": "Your Name",
    "author_url": "https://example.com",
    "main_class": "MyFirstPlugin",
    "min_aipostify_version": "1.0.0",
    "license": "MIT",
    "tags": ["demo", "starter"]
}

⚠️ Known Inconsistency: Some existing plugins use requires_aipostify and others use min_aipostify_version for the minimum version field. The recommended canonical field name is min_aipostify_version. See the plugin.json Reference for full details.

3. Extend BasePlugin

Your main plugin class must extend App\CMS\Plugins\BasePlugin. Override the lifecycle methods to hook into AIPostify:

<?php

namespace Plugins\MyFirstPlugin;

use App\CMS\Plugins\BasePlugin;
use App\CMS\Hooks\Hook;

class MyFirstPlugin extends BasePlugin
{
    /**
     * Called when the plugin is first activated.
     * Use for one-time setup: create DB tables, seed defaults, etc.
     */
    public function activate(): void
    {
        // Run on first activation
        \Log::info('MyFirstPlugin activated!');
    }

    /**
     * Called when the plugin is deactivated.
     * Use for cleanup: remove scheduled tasks, clear caches.
     */
    public function deactivate(): void
    {
        \Log::info('MyFirstPlugin deactivated.');
    }

    /**
     * Called on every request when the plugin is active.
     * Register hooks, shortcodes, post types, menus, etc.
     */
    public function boot(): void
    {
        // Register a hook listener
        Hook::listen('after_post_content', function ($content) {
            return $content . '<p>Powered by My First Plugin</p>';
        });

        // Register an admin menu item
        $this->registerAdminMenu();
    }

    protected function registerAdminMenu(): void
    {
        Hook::listen('admin_menu', function () {
            app('admin.menu')->add([
                'title' => 'My Plugin Settings',
                'slug'  => 'my-first-plugin-settings',
                'icon'  => '⚙️',
                'view'  => 'plugins.my-first-plugin.views.admin.settings',
            ]);
        });
    }
}

BasePlugin Lifecycle Methods

Method When Called Typical Use
activate()Plugin first enabled by adminCreate tables, seed defaults, register capabilities
deactivate()Plugin disabled by adminCleanup caches, remove scheduled tasks
boot()Every request (when active)Register hooks, shortcodes, post types, admin menus

4. Register Your First Hook

The Hook system is the backbone of the AIPostify extension API. Use Hook::listen() for actions and Hook::filter() / Hook::applyFilters() for filters:

// Action: Fire-and-forget event listener
Hook::listen('after_post_save', function ($post) {
    \Log::info("Post saved: {$post->title}");
});

// Filter: Modify a value in a pipeline
Hook::listen('the_content', function ($content) {
    return str_replace('foo', 'bar', $content);
}, priority: 10);

// WordPress-style aliases also work:
add_action('init', function () { /* ... */ });
add_filter('the_title', function ($title) { return strtoupper($title); });

See the full Hook API Reference for all available methods and known core hook points.

5. Test Your Plugin

  1. Copy your my-first-plugin/ folder into content/plugins/.
  2. Log in to the AIPostify admin dashboard.
  3. Navigate to Plugins → Installed Plugins.
  4. Click Activate next to "My First Plugin".
  5. Your boot() method will run on the next page load — check the admin menu for your settings link!

💡 Tip: Enable APP_DEBUG=true in your .env and watch storage/logs/laravel.log for your \Log::info() messages during development.

Next Steps

Last verified against AIPostify core. © 2026 AIPostify Marketplace Developer Documentation.