Xgenious/ docs
Products
Get support

Admin Menus

Define navigation items in the admin dashboard via plugin.json.

{
  "menus": [
    {
      "id": "my-plugin-main",
      "label": "My Plugin",
      "icon": "icon-plugin",
      "position": 25,
      "url": "/admin/my-plugin",
      "capability": "manage_plugin",
      "children": [
        {
          "id": "my-plugin-settings",
          "label": "Settings",
          "url": "/admin/my-plugin/settings",
          "capability": "manage_plugin_settings"
        },
        {
          "id": "my-plugin-logs",
          "label": "Logs",
          "url": "/admin/my-plugin/logs",
          "capability": "view_plugin_logs"
        }
      ]
    }
  ]
}
PropertyTypeRequiredDescription
idstringYesUnique menu identifier
labelstringYesDisplay text
iconstringNoIcon class (CSS class)
positionintegerNoMenu order (lower = higher)
urlstringNoMenu link URL
capabilitystringNoRequired capability to view
childrenarrayNoSubmenu items

Icon Classes

Use standard icon classes (e.g., from Font Awesome or Bootstrap Icons):

icon-settings    (gear/cog)
icon-dashboard   (chart)
icon-users       (people)
icon-file        (document)
icon-cog         (wrench)
icon-plugin      (puzzle piece)

Dynamic Menus

Register menus programmatically in your service provider:

<?php

namespace MyVendor\MyPlugin\Providers;

use Illuminate\Support\ServiceProvider;

class PluginServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Register menu items dynamically
        add_filter('fundorex:admin.menus', function($menus) {
            $menus[] = [
                'id' => 'my-plugin-main',
                'label' => 'My Plugin',
                'icon' => 'icon-plugin',
                'url' => '/admin/my-plugin',
                'capability' => 'manage_plugin',
            ];
            return $menus;
        });
    }
}

Static Assets

Define CSS and JavaScript files in plugin.json.

Asset Configuration

{
  "assets": {
    "css": [
      "resources/assets/css/style.css"
    ],
    "js": [
      "resources/assets/js/app.js",
      "resources/assets/js/dashboard.js"
    ]
  }
}

Asset Paths

  • Paths are relative to plugin root directory
  • Assets are copied to public/plugins/{plugin-name}/ during publication
  • Use asset('plugins/my-plugin/css/style.css') in views

Publishing Assets

Publish plugin assets via command:

php artisan vendor:publish --tag=my-plugin-assets

Or in your service provider:

public function boot()
{
    $this->publishes([
        __DIR__ . '/../../resources/assets' => public_path('plugins/my-plugin'),
    ], 'my-plugin-assets');
}

Asset Linking in Views

<link rel="stylesheet" href="{{ asset('plugins/my-plugin/css/style.css') }}">
<script src="{{ asset('plugins/my-plugin/js/app.js') }}"></script>

Versioning Assets

For cache busting, version assets:

<link rel="stylesheet"
  href="{{ asset('plugins/my-plugin/css/style.css?v=' . $plugin->getVersion()) }}">

Routes

Define plugin routes in routes/web.php.

Basic Routes

<?php

use Illuminate\Support\Facades\Route;

Route::prefix('admin/my-plugin')->middleware(['auth', 'admin'])->group(function () {
    Route::get('/', 'DashboardController@index')->name('dashboard');
    Route::get('/settings', 'SettingsController@index')->name('settings');
    Route::post('/settings', 'SettingsController@store')->name('settings.store');
});

Route Attributes

Define route attributes in plugin.json:

{
  "routes": {
    "web": "routes/web.php",
    "api": "routes/api.php"
  }
}

API Routes

<?php

use Illuminate\Support\Facades\Route;

Route::prefix('api/v1/my-plugin')->middleware(['api', 'auth:api'])->group(function () {
    Route::get('/campaigns', 'API\\CampaignController@index');
    Route::post('/campaigns', 'API\\CampaignController@store');
    Route::get('/campaigns/{id}', 'API\\CampaignController@show');
});

Route Parameters

Route::get('/campaigns/{campaign}', function(Campaign $campaign) {
    return view('my-plugin::campaign.show', ['campaign' => $campaign]);
});

Route Groups

Route::group([
    'prefix' => 'admin/my-plugin',
    'middleware' => ['auth', 'admin'],
    'as' => 'my-plugin.',
], function () {
    Route::get('/', 'DashboardController@index')->name('dashboard');
    Route::resource('campaigns', 'CampaignController');
});

View Blade Templates

Store templates in resources/views/. Load in service provider:

public function boot()
{
    $this->loadViewsFrom(
        __DIR__ . '/../../resources/views',
        'my-plugin'
    );
}

Using Views

return view('my-plugin::dashboard');
return view('my-plugin::campaign.show', ['campaign' => $campaign]);

View Inheritance

@extends('layouts.admin')

@section('title', 'My Plugin')

@section('content')
    <div class="plugin-content">
        <!-- Your content -->
    </div>
@endsection

JavaScript & Vue Components

If your plugin uses frontend frameworks:

Vue 3 Setup

// resources/assets/js/app.js
import { createApp } from 'vue';
import MyComponent from './components/MyComponent.vue';

const app = createApp({
    components: {
        MyComponent,
    },
});

app.mount('#app');

Alpine.js Setup

<script src="{{ asset('plugins/my-plugin/js/alpine.min.js') }}" defer></script>

<div x-data="pluginApp()">
    <button @click="openModal">Settings</button>
</div>

<script src="{{ asset('plugins/my-plugin/js/app.js') }}"></script>

Best Practices

Asset Organization

resources/
├── assets/
│   ├── css/
│   │   ├── app.css
│   │   └── admin.css
│   └── js/
│       ├── app.js
│       └── utils.js
└── views/
    ├── dashboard/
    ├── settings/
    └── layouts/

Use consistent icon classes across your plugin. Define a custom icon set if needed.

Route Security

Always protect admin routes with authentication and capability checks:

Route::middleware(['auth', 'admin', 'capability:manage_plugin'])->group(function () {
    // Protected routes
});

Asset Caching

Set proper cache headers in production:

header('Cache-Control: public, max-age=31536000, immutable');

Next Steps

Still stuck?
Our support team is ready to help you get set up.
Get support