Quick Start: Your First Plugin in 5 Minutes

Get a fully functional WordPress plugin running with an admin settings page, Vue.js frontend, and DaisyUI styling — all in under 5 minutes.

Prerequisites

RequirementVersion
PHP>= 8.1
Composer>= 2.0
WordPress>= 6.0
Node.js>= 18

Step 1: Create Your Plugin

composer create-project KYNetCode/wpzylos-scaffold my-awesome-plugin
cd my-awesome-plugin

This downloads the scaffold template with everything pre-configured.

Step 2: Initialize Your Plugin

Run the init script to personalize your plugin — it replaces all placeholders with your plugin's name, slug, namespace, and CSS prefix.

PowerShell (Windows):

.scripts/init-plugin.ps1 -PluginName "My Awesome Plugin"

Bash (Linux/Mac):

bash .scripts/init-plugin.sh --name "My Awesome Plugin"

The init script will:

  • Good: Set the plugin name, slug (my-awesome-plugin), and namespace (MyAwesomePlugin)
  • Good: Derive the CSS prefix from initials (e.g., "My Awesome Plugin" → map-)
  • Good: Update composer.json, the main plugin file, and all PHP classes
  • Good: Replace CSS placeholder __CSS_PREFIX__ in all stylesheets
  • Good: Configure the Vue mount point IDs

How the CSS prefix works: WPZylos takes the first letter of each word in your plugin name, adds a dash. So "My Awesome Plugin" becomes map-. This prefix scopes all DaisyUI and Tailwind classes to prevent conflicts with other plugins and WordPress itself.

Step 3: Install Dependencies

composer install
npm install

Step 4: Build the Frontend

# Production build (outputs to dist/)
npm run build

# Or development mode with hot module replacement
npm run dev

Step 5: Activate in WordPress

Copy or symlink your plugin to wp-content/plugins/ and activate it:

# Using WP-CLI
wp plugin activate my-awesome-plugin

# Or activate via WordPress Admin → Plugins

What You Get

Your new plugin comes with a full production-ready structure:

my-awesome-plugin/
+-- my-awesome-plugin.php    # Main plugin file (entry point)
+-- composer.json            # PHP dependencies
+-- package.json             # Node dependencies (Vite, Vue, DaisyUI)
+-- vite.config.js           # Vite build pipeline
+-- bootstrap/
|   +-- app.php              # Service provider registration & boot
+-- config/
|   +-- app.php              # Application configuration
+-- app/
|   +-- Core/
|   |   +-- PluginContext.php    # Plugin identity (slug, prefix, paths)
|   +-- Http/
|   |   +-- Shortcodes/         # Shortcode handlers
|   +-- Lifecycle/
|   |   +-- Activator.php       # Activation logic
|   |   +-- Deactivator.php     # Deactivation logic
|   |   +-- Uninstaller.php     # Uninstall cleanup
|   +-- Support/
|       +-- helpers.php         # Global helper functions
+-- resources/
|   +-- css/
|   |   +-- admin.css           # Admin CSS (scoped DaisyUI + Tailwind)
|   |   +-- app.css             # Frontend CSS
|   +-- js/
|   |   +-- admin.js            # Admin JS entry (Vue mount)
|   |   +-- app.js              # Frontend JS entry
|   |   +-- components/
|   |       +-- AdminApp.vue    # Vue admin settings panel
|   +-- views/
|       +-- admin/
|           +-- settings.blade.php  # Admin page template
+-- routes/
|   +-- web.php              # Frontend route definitions
+-- database/
|   +-- migrations/          # Database migration files
+-- tests/                   # PHPUnit tests

Out of the box, you get:

  • 🎨 Admin settings page with Vue.js + DaisyUI (dark mode toggle included!)
  • 🔒 CSS isolation — three-layer scoping prevents conflicts with WordPress and other plugins
  • Vite build pipeline — lightning-fast builds with HMR for development
  • 📦 Service providers — full dependency injection with PSR-11 container
  • 🗄️ Database & migrations — query builder, ORM models, migration system
  • 🛡️ Security — nonce verification, capability checks, sanitization
  • 🌐 Routing — frontend, REST API, and AJAX routers
  • 🌍 i18n ready — text domain and translation support

Verify It Works

After activation, check if the framework is loaded:

// In any PHP file within your plugin
$context = $GLOBALS['my_awesome_plugin_context'] ?? null;
if ($context) {
    echo $context->version(); // 1.0.0
    echo $context->slug();    // my-awesome-plugin
    echo $context->prefix();  // map_
}

Minimal Manual Setup

If you prefer to set things up by hand without the scaffold:

<?php
/**
 * Plugin Name: My Awesome Plugin
 * Version: 1.0.0
 * Requires PHP: 8.1
 * Text Domain: my-awesome-plugin
 */

declare(strict_types=1);

defined('ABSPATH') || exit;

require_once __DIR__ . '/vendor/autoload.php';

use MyAwesomePlugin\Core\PluginContext;

$context = PluginContext::create([
    'file'       => __FILE__,
    'slug'       => 'my-awesome-plugin',
    'prefix'     => 'map_',
    'textDomain' => 'my-awesome-plugin',
    'version'    => '1.0.0',
    'namespace'  => 'MyAwesomePlugin',
]);

// Bootstrap on plugins_loaded
add_action('plugins_loaded', static function () use ($context) {
    $bootstrap = require __DIR__ . '/bootstrap/app.php';
    if (is_callable($bootstrap)) {
        $bootstrap($context);
    }
});

Next Steps

Now that your plugin is running, explore what WPZylos can do: