.claude/skills/klytos-admin-sidebar/SKILL.md
Guide for adding items to the admin sidebar, creating admin pages for plugins, and building admin UI in Klytos CMS. Use when adding menu items to the admin panel sidebar, creating admin pages for plugins, building admin forms, working with admin templates, implementing admin styling, creating AJAX endpoints, or understanding the admin panel structure and design patterns.
npx skillsauth add joseconti/klytos klytos-admin-sidebarInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this reference when you need to add your plugin to the admin panel sidebar, create settings pages, or build admin UI that follows the Klytos design patterns.
IMPORTANT: If your plugin has an admin page, it MUST also have equivalent MCP tools. MCP is the primary interface; admin is secondary.
[
'id' => string, // Unique identifier (e.g. 'my-plugin')
'title' => string, // Display label
'url' => string, // Link href (relative to admin/)
'icon' => string, // FontAwesome class: 'fa-solid fa-star'
'position' => int, // Sort order (lower = higher in menu)
'section' => string, // 'dashboard', 'content', 'design', 'users', 'tools', or 'settings'
'capability' => string|null, // Permission required (null = all users)
'children' => array|null, // Submenu items (same structure)
]
The sidebar is organized into 6 sections. Dashboard is standalone (no section header).
| Position | Item | Section | |---|---|---| | 1 | Dashboard | dashboard (standalone, no header) | | Content | | | | 10 | Pages | content | | 11+ | Custom Post Types (auto-generated) | content | | 12 | Post Types | content | | 15 | Tasks | content | | Design | | | | 20 | Design (Theme) | design | | 22 | Assets | design | | 24 | AI Images | design | | Users | | | | 30 | Users | users | | 32 | Consent Manager | users | | 34 | Privacy | users | | Tools | | | | 40 | Analytics | tools | | 42 | MCP | tools | | 44 | Webhooks | tools | | 46 | Scheduled Actions | tools | | 48 | Terminal | tools | | Settings | | | | 50 | Settings | settings | | 52 | Security | settings | | 54 | Integrity | settings | | 56 | System Options | settings | | 58 | Translations | settings | | 60 | Logs | settings | | 62 | Plugins | settings | | 64 | Updates | settings |
Plugin position guide: Use tools section (positions 43-49) for tool/integration plugins, or settings section (positions 61-63) for admin/config plugins. Content-related plugins should use content section (positions 13-19).
// In your plugin's init.php
klytos_add_filter('admin.sidebar_items', function (array $items): array {
$items[] = [
'id' => 'my-plugin',
'title' => 'My Plugin',
'url' => klytos_admin_url('plugins/my-plugin/admin/settings.php'),
'icon' => 'fa-solid fa-gear',
'position' => 45,
'section' => 'tools',
'capability' => 'site.configure',
];
return $items;
});
klytos_add_filter('admin.sidebar_items', function (array $items): array {
$items[] = [
'id' => 'my-plugin',
'title' => 'My Plugin',
'url' => klytos_admin_url('plugins/my-plugin/admin/dashboard.php'),
'icon' => 'fa-solid fa-chart-line',
'position' => 45,
'section' => 'tools',
'capability' => 'site.configure',
'children' => [
[
'id' => 'my-plugin-dashboard',
'title' => 'Dashboard',
'url' => klytos_admin_url('plugins/my-plugin/admin/dashboard.php'),
],
[
'id' => 'my-plugin-settings',
'title' => 'Settings',
'url' => klytos_admin_url('plugins/my-plugin/admin/settings.php'),
],
],
];
return $items;
});
<?php
// plugins/my-plugin/admin/settings.php
declare(strict_types=1);
// 1. Bootstrap (loads App, Auth, session, runs cron)
require_once __DIR__ . '/../../../admin/bootstrap.php';
use Klytos\Core\Helpers;
// 2. Page setup
$pageTitle = 'My Plugin Settings';
$currentPage = 'my-plugin'; // Must match sidebar item 'id'
$auth = $app->getAuth();
$error = '';
$success = '';
// 3. Handle POST form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && klytos_verify_csrf()) {
try {
// Sanitize ALL inputs
$apiKey = klytos_sanitize_text($_POST['api_key'] ?? '');
$enabled = isset($_POST['enabled']);
$columns = klytos_sanitize_int($_POST['columns'] ?? 3);
$email = klytos_sanitize_email($_POST['email'] ?? '');
// Validate
if ($apiKey === '') {
throw new \RuntimeException('API key is required');
}
// Save options
klytos_set_option('my-plugin.api_key', $apiKey);
klytos_set_option('my-plugin.enabled', $enabled);
klytos_set_option('my-plugin.columns', $columns);
klytos_set_option('my-plugin.email', $email);
$success = 'Settings saved successfully.';
} catch (\RuntimeException $e) {
$error = $e->getMessage();
}
}
// 4. Read current values for form
$apiKey = klytos_get_option('my-plugin.api_key', '');
$enabled = klytos_get_option('my-plugin.enabled', false);
$columns = klytos_get_option('my-plugin.columns', 3);
$email = klytos_get_option('my-plugin.email', '');
// 5. Include header and sidebar templates
require_once __DIR__ . '/../../../admin/templates/header.php';
require_once __DIR__ . '/../../../admin/templates/sidebar.php';
?>
<!-- 6. Page content -->
<?php if ($error): ?>
<div class="alert alert-error"><?php echo klytos_esc_html($error); ?></div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success"><?php echo klytos_esc_html($success); ?></div>
<?php endif; ?>
<div class="card">
<div class="card-header">
<h2>My Plugin Settings</h2>
</div>
<div class="card-body">
<form method="POST">
<?php echo klytos_csrf_field(); ?>
<div class="form-group">
<label class="form-label">API Key</label>
<input type="text" name="api_key" class="form-control"
value="<?php echo klytos_esc_attr($apiKey); ?>" required>
</div>
<div class="form-group">
<label class="form-label">Columns</label>
<select name="columns" class="form-control">
<?php for ($i = 1; $i <= 6; $i++): ?>
<option value="<?php echo $i; ?>"
<?php echo $columns === $i ? 'selected' : ''; ?>>
<?php echo $i; ?>
</option>
<?php endfor; ?>
</select>
</div>
<div class="form-group">
<label class="form-label">Notification Email</label>
<input type="email" name="email" class="form-control"
value="<?php echo klytos_esc_attr($email); ?>">
</div>
<div class="form-check">
<input type="checkbox" name="enabled" id="enabled" class="form-check-input"
<?php echo $enabled ? 'checked' : ''; ?>>
<label for="enabled" class="form-check-label">Enable Plugin</label>
</div>
<button type="submit" class="btn btn-primary">Save Settings</button>
</form>
</div>
</div>
<?php
// 7. Include footer template
require_once __DIR__ . '/../../../admin/templates/footer.php';
?>
| Class | Description |
|---|---|
| .card | Card container (white bg, border, shadow) |
| .card-header | Card title area |
| .card-body | Card content area |
| Class | Description |
|---|---|
| .btn | Button base |
| .btn-primary | Blue primary action |
| .btn-secondary | Gray secondary action |
| .btn-danger | Red destructive action |
| .btn-sm | Small button |
| .btn-outline | Outline variant |
| Class | Description |
|---|---|
| .form-group | Field wrapper (margin-bottom) |
| .form-label | Input label |
| .form-control | Input, textarea, select |
| .form-check | Checkbox/radio wrapper |
| .form-check-input | Checkbox/radio input |
| .form-check-label | Checkbox/radio label |
| Class | Description |
|---|---|
| .alert | Base alert |
| .alert-success | Green success message |
| .alert-error | Red error message |
| .alert-warning | Orange warning message |
| .alert-info | Blue info message |
| Class | Description |
|---|---|
| .badge | Status badge |
| .badge-published | Green (published) |
| .badge-draft | Gray (draft) |
| .badge-active | Green (active) |
| .badge-inactive | Red (inactive) |
| Class | Description |
|---|---|
| .table | Data table (full width, borders) |
| thead | Table header (bold, bg color) |
| tr:hover td | Row hover highlight |
| Class | Description |
|---|---|
| .modal | Modal dialog |
| .modal-overlay | Backdrop |
| .modal-content | Modal body |
| .modal-header | Modal title |
| .modal-footer | Modal buttons |
--admin-primary: #2563eb;
--admin-primary-hover: #1d4ed8;
--admin-bg: #f1f5f9;
--admin-surface: #ffffff;
--admin-sidebar: #1e293b;
--admin-sidebar-text: #cbd5e1;
--admin-sidebar-active: #2563eb;
--admin-text: #1e293b;
--admin-text-muted: #64748b;
--admin-border: #e2e8f0;
--admin-success: #22c55e;
--admin-warning: #f59e0b;
--admin-error: #ef4444;
--admin-radius: 8px;
--admin-card-bg: #ffffff;
Dark mode is available via data-theme="dark" on the <html> element.
The admin panel includes FontAwesome 6. Use fa-solid fa-* classes for icons. Common choices:
| Icon | Class |
|---|---|
| Settings gear | fa-solid fa-gear |
| Chart | fa-solid fa-chart-line |
| Star | fa-solid fa-star |
| Plugin/puzzle | fa-solid fa-puzzle-piece |
| Shield | fa-solid fa-shield |
| Envelope | fa-solid fa-envelope |
| Image | fa-solid fa-image |
| Box/package | fa-solid fa-box |
| Users | fa-solid fa-users |
| Code | fa-solid fa-code |
For dynamic admin functionality, use the existing AJAX patterns:
| Endpoint | Method | Purpose |
|---|---|---|
| admin/api/autosave.php | POST | Auto-save draft pages |
| admin/api/inline-edit.php | POST | Quick edit in page list |
| admin/api/tasks.php | POST | Update task status |
| admin/api/media-upload.php | POST | Upload files |
All AJAX calls must include the CSRF token in the request body or X-CSRF-Token header.
| admin/api/sidebar-order.php | POST/GET | Save/reset/get per-user sidebar order |
Users can customize the sidebar order per-user via drag-and-drop.
admin/api/sidebar-order.phpOrder is stored as user meta via MetaManager:
// Key: klytos.sidebar_order
// Structure:
[
'sections' => ['content', 'system'], // section display order
'items' => [
'content' => ['dashboard', 'pages', 'theme', ...],
'system' => ['settings', 'plugins', ...],
],
]
Custom order is read from user meta after the admin.sidebar_items filter and before rendering. Items not in the saved order (e.g., new plugin items) are appended at their default position.
| Hook | Type | Args |
|---|---|---|
| admin.sidebar_section_order | Filter | $sectionOrder (array of section names) |
| admin.sidebar_section_label | Filter | $label, $sectionName |
| admin.sidebar_order.saved | Action | $userId, $sections, $items |
| admin.sidebar_order.reset | Action | $userId |
| admin.sidebar.before_sections | Action | — |
| admin.sidebar.after_sections | Action | — |
admin/assets/vendor/sortable/Sortable.min.jsadmin/assets/js/klytos-sidebar-sort.jsadmin/api/sidebar-order.phpadmin/assets/css/klytos-sidebar.cssklytos_csrf_field())klytos_verify_csrf())klytos_has_permission()) if page is role-restrictedadmin/templates/sidebar.phpadmin/templates/header.phpadmin/templates/footer.phpadmin/bootstrap.phpadmin/templates/header.phpdevelopment
Guide for working with dates, times, and timezones in Klytos CMS. Use when formatting dates, converting timezones, scheduling actions with timestamps, displaying local time, working with UTC storage, building timezone selectors, or using any klytos_date/klytos_gmdate/klytos_timezone functions.
tools
Guide for developing and extending the Klytos web terminal. Use when modifying terminal commands, adding terminal commands from plugins, fixing terminal bugs, extending the pseudo-terminal, working with TerminalExecutor class, registering custom permissions, adding custom category labels, or managing terminal UI and security.
development
--- name: klytos-site-builder description: Guide for building a complete website from scratch with Klytos CMS. Use when creating a new site, configuring a site after installation, setting up design/content/SEO/navigation, or when the user pastes the post-install prompt. Covers 9 phases: discovery, design reference, global config, theme, content structure, templates, content creation, additional features, and launch. --- # Klytos Site Builder ## Overview The Site Builder is a conversational AI
development
Use when creating or editing page content in Klytos CMS. Ensures every page has proper SEO structure, HTML semantics, meta tags, structured data, accessibility for maximum search engine visibility. Apply when writing page titles, descriptions, content, headings, images, internal links, JSON-LD schema, or following the SEO checklist before publishing pages.