Vertex Theme for Pterodactyl — A premium panel theme with drag-and-drop page builder, live color editor, multi-language support, and 5 powerful addons (Plugin Installer, Version Changer, Subdomain Manager, Properties Manager, Icon Changer).
  • TypeScript 37.8%
  • PHP 36.3%
  • Blade 14.2%
  • CSS 10.6%
  • JavaScript 0.7%
  • Other 0.4%
Find a file
2026-05-22 15:41:11 +00:00
config design: update defaults to crashcrafts.com neon green palette 2026-05-21 20:40:59 +00:00
database/migrations feat(modpacks): create installed_modpacks table migration 2026-05-21 11:57:00 +00:00
private Add Blueprint compatibility: private/remove.sh 2026-05-22 15:38:35 +00:00
public
resources fix: replace CSS Modules composes directives with plain CSS for browser compatibility 2026-05-22 04:17:55 +00:00
routes fix: add missing API routes for settings export/import, fonts, and console messages 2026-05-21 12:43:22 +00:00
screenshots Remove old 30-vertex-v6-interaction-gradient-border.png 2026-05-22 04:38:23 +00:00
src design: crashcrafts-inspired color presets with neon green default 2026-05-21 20:41:19 +00:00
.gitignore
admin.css Add Blueprint compatibility: admin.css 2026-05-22 15:38:39 +00:00
admin.wrapper.blade.php Add Blueprint compatibility: admin.wrapper.blade.php 2026-05-22 15:38:06 +00:00
CHANGELOG.md
composer.json
conf.yml Add Blueprint compatibility: conf.yml 2026-05-22 15:37:45 +00:00
CONTRIBUTING.md
dashboard.wrapper.blade.php Add Blueprint compatibility: dashboard.wrapper.blade.php 2026-05-22 15:38:03 +00:00
LICENSE
package.json
postcss.config.js
README.md docs: add Blueprint installation instructions to README 2026-05-22 15:41:11 +00:00
root.css Add Blueprint compatibility: root.css 2026-05-22 15:37:55 +00:00
SECURITY.md
tailwind.config.js design: update tailwind to crashcrafts green+Inter tokens 2026-05-21 20:41:06 +00:00
tsconfig.json
view.blade.php Add Blueprint compatibility: view.blade.php 2026-05-22 15:38:21 +00:00
webpack.config.js

🎨 Vertex Theme — A Modern Pterodactyl Panel Theme

Version: 1.0.0
Status: Stable

Vertex is a feature-rich theme package for the Pterodactyl game panel that adds dark mode, drag-and-drop server sorting, a live color editor, floating windows, a plugin installer with live marketplace APIs, announcement management, and more — all without modifying any core Pterodactyl files.


v6.0 Complete UI/UX Redesign

Vertex v6.0 brings a complete visual overhaul inspired by premium design systems (uupm.cc, arix.gg):

Glass Hierarchy (4 Tiers):

  • glass-heavy (92% opacity / 32px blur) — modals, overlays
  • glass (85% / 24px blur) — primary cards, panels
  • glass-light (70% / 16px blur) — nav bars, sub-panels
  • glass-subtle (50% / 12px blur) — tabs, inline elements

Background System: 5 animated radial gradient blobs + noise texture + scanline overlay for glass depth

Typography: Gradient display headings, letter-spacing hierarchy, gradient text utilities

Buttons: Gradient primary with glow, asymmetric corners, 3 size variants, icon buttons, loading states

Card Variants: Stat cards (icon + metric + trend), feature cards, plugin cards (name + rating + install), server cards (status + resources), image cards, gradient border cards

Navigation: Icon+text items, section headers, collapsible trees, gradient active indicators, badges, sidebar search

Input System: Glass inputs, icon wrappers, animated focus glow, floating labels, custom selects, toggles, checkboxes

Progress & Metrics: Gradient progress bars with glow, large gradient metric numbers

Micro-interactions: Skeleton loading, hover glow intensification, animated gradient borders, fade-in/slide-in animations, pulsing status indicators

Dark Mode

Component Preview
Full Page Dark Full Page
Glass Hierarchy Dark Glass Hierarchy
Typography Dark Typography
Buttons Dark Buttons
Cards Dark Cards
Navigation Dark Navigation
Inputs Dark Inputs
Progress & Metrics Dark Progress
Micro-interactions Dark Micro-interactions
Announcements Dark Announcements

Light Mode

Component Preview
Full Page Light Full Page
Glass Hierarchy Light Glass Hierarchy
Typography Light Typography
Buttons Light Buttons
Cards Light Cards
Navigation Light Navigation
Inputs Light Inputs
Progress & Metrics Light Progress
Micro-interactions Light Micro-interactions
Announcements Light Announcements

Mobile & Interaction States

Component Preview
Mobile Full (Dark) Mobile Full
Mobile Cards (Dark) Mobile Cards
Hover Glass Card Hover Glass Card
Hover Primary Button Hover Primary Button
Focus Input Focus Input
Hover Gradient Border Hover Gradient Border

📸 Screenshots

Plugin Installer Color Editor Floating Windows
Plugin Installer Color Editor Floating Windows
Announcements Properties Manager Subdomain Manager
Announcements Properties Manager Subdomain Manager

Icon & Version Changer


🧩 Blueprint Installation

Vertex can be installed via Blueprint, the Pterodactyl extension framework.

One-Click Install

cd /var/www/pterodactyl
blueprint -install vertex

This installs the Vertex CSS theme (glass hierarchy, dark/light mode, all visual components). The theme will be active immediately on your client dashboard and admin panel.

Full Feature Install (Composer)

For access to ALL Vertex features — live color editor, announcements, plugin installer, floating windows, subdomain manager and more — install the full Composer package:

cd /var/www/pterodactyl
composer require crashmedia/vertex-theme
php artisan vertex:install
php artisan migrate
php artisan optimize:clear

Then visit /admin/vertex to configure the theme.

Requirements

Requirement Blueprint (CSS) Full Package
Pterodactyl 1.12.2+
Blueprint beta-2025-09+
PHP 8.2+
Composer 2+
Node.js 20+
Redis (recommended)

What Blueprint Installs

  • root.css — Color palette and CSS custom properties (bundled with React)
  • vertex.css — Full glass-morphism theme (1,620 lines)
  • vertex-dark.css — Dark mode overrides
  • vertex-admin.css — Admin panel styling
  • vertex-floating.css — Floating window styles
  • Scanline + noise overlays — Glass depth effects

What Full Package Adds

  • Live HSL color editor with 12 presets
  • Announcement system with scheduling
  • Drag-and-drop server sorting
  • Floating window multitasking
  • Plugin installer (4 marketplaces)
  • Minecraft version changer
  • Subdomain manager (Cloudflare DNS)
  • Icon changer, properties manager, modpack installer
  • 5 layout variants, 4 login screen variants
  • PWA support, Cloudflare Turnstile
  • Custom email templates
  • 10 language translations

Features

Feature Status
v6.0 Glass UI Redesign Stable
Dark/Light Mode Toggle Stable
Live Color Editor (HSL presets) Stable
Drag-and-Drop Server Sorting Stable
Floating Window Multitasking Stable
Announcement Manager Stable
Privacy Mode (IP/data blurring) Stable
Multi-Language Support (5 languages) ⚠️ Partial
Minecraft Version Changer Stable
Plugin Installer (4 marketplaces) Stable
Subdomain Manager ⚠️ Partial
Icon Changer ⚠️ Partial
Custom CSS Injection Stable
Custom Logo Upload Stable
5 Layout CSS Classes Stable
PWA Support 📋 Planned
Cloudflare Turnstile 📋 Planned
Page Builder 📋 Planned

Feature Details

Color Editor Stable

Vertex Color Editor

What it does: A live color editor that lets administrators customize the entire theme palette from the admin panel. Choose a primary color and the system generates a full HSL-shaded palette (50900). Changes preview live before applying.

Presets: 12 named presets are available — blue, purple, emerald, rose, amber, cyan, indigo, pink, teal, violet, slate, and orange.

Implementation: ColorService::generatePalette() takes a hex color and produces 10 HSL-derived shades. The palette is rendered as CSS custom properties on :root. ColorPresetService provides the 12 named presets. The editor UI is in ColorEditor.tsx with preview/apply/preset API endpoints.

API endpoints: POST /api/client/vertex/editor/preview, POST /api/client/vertex/editor/apply, POST /api/client/vertex/editor/preset/{name}

Files: src/Services/ColorService.php, src/Services/ColorPresetService.php, resources/scripts/vertex/components/ColorEditor.tsx


Announcements Stable

Vertex Announcements

What it does: A full CRUD announcement system with scheduling. Administrators can create announcements that appear as banners across the panel. Each announcement supports:

  • Schedulingstarts_at and ends_at timestamps for time-boxed announcements
  • Type badgesinfo, warning, success, error with color-coded styling
  • Dismissible — Users can dismiss announcements (stored in session)
  • Active/inactive — Toggle without deleting
  • Dark/light mode — Automatically adapts to the current theme mode

Implementation: The Announcement model uses starts_at and ends_at to determine active status. The AnnouncementBanner.tsx component renders banners. AnnouncementProvider.tsx provides announcements via React Context.

Files: src/Models/Announcement.php, src/Http/Controllers/AnnouncementController.php, resources/scripts/vertex/components/AnnouncementBanner.tsx, resources/scripts/vertex/providers/AnnouncementProvider.tsx


Server Sorting Stable

What it does: Drag-and-drop reordering of servers on the client dashboard. Supports 5 sort methods:

  1. Custom — Drag servers into any order
  2. Alphabetical (A-Z) — By server name
  3. Alphabetical (Z-A) — Reverse alphabetical
  4. Date Created — Newest first
  5. By Status — Online servers first, then offline, suspended, installing

The sort order is persisted per-user in the server_sort_preferences database table. The API (at GET/POST /api/client/vertex/servers/sort) stores an ordered array of server IDs and the selected sort method.

Implementation: ServerSorter.tsx uses DndContext, SortableContext, KeyboardSensor, and PointerSensor from @dnd-kit. Each server is rendered as a SortableItem with a drag handle. The useServerSort hook handles API persistence and optimistic UI updates.

Files: src/Http/Controllers/ServerSortController.php, src/Models/ServerSortPreference.php, resources/scripts/vertex/components/ServerSorter.tsx, resources/scripts/vertex/components/SortableItem.tsx, resources/scripts/vertex/hooks/useServerSort.ts, database/migrations/2026_05_20_000003_create_server_sort_preferences_table.php


Floating Windows Stable

Vertex Floating Windows

What it does: Right-clicking any server opens a context menu (ServerContextMenu.tsx) with options to open console, files, databases, and settings in floating windows. Each window is:

  • Draggable — Click and drag the title bar to reposition
  • Resizable — Drag the corner/edge handles
  • Minimizable — Collapses to the floating taskbar
  • Stackable — Z-index management brings focused windows to front
  • Mobile responsive — Windows adapt to smaller viewports

Implementation: FloatingWindowManager.tsx provides a React context (FloatingWindowContext) that tracks all open windows with their position, size, z-index, minimize state, and content type. The FloatingWindow component renders each window at its tracked position. The FloatingTaskbar shows minimized windows. Each new window cascades its position by 32px offsets.

Windows support these content types: console, files, settings, terminal, database, schedules. Default size is 800×520px, minimum is 400×300px. Z-index starts at 100 and increments per new window. The feature is gated by the floating_windows config flag.

Files: resources/scripts/vertex/components/FloatingWindowManager.tsx, resources/scripts/vertex/components/FloatingWindow.tsx, resources/scripts/vertex/components/FloatingTaskbar.tsx, resources/scripts/vertex/components/ServerContextMenu.tsx, resources/scripts/vertex/hooks/useServerContextMenu.ts, resources/css/vertex-floating.css


Minecraft Version Changer Stable

Vertex Icon & Version Changer

What it does: Fetches the Minecraft version manifest from https://launchermeta.mojang.com/mc/game/version_manifest_v2.json and caches it for 1 hour. Versions are categorized by type (release, snapshot, beta, alpha). When a user selects a version, the system updates the Pterodactyl egg variable (default variable name: MC_VERSION, configurable via config/vertex.phpminecraft_version_variable). An optional reinstall can be triggered.

Fallback: If the Mojang API is unreachable, a hardcoded list of 15 release versions and 3 snapshot versions is used (defined in VersionService.php as FALLBACK_VERSIONS).

Implementation: VersionService::changeVersion() validates the requested version against the manifest, updates the egg variable via Pterodactyl's Eloquent relations, and optionally calls $server->reinstall(). The $server->eggVariables() relation is filtered by the configured variable name.

Files: src/Services/VersionService.php, src/Http/Controllers/VersionChangerController.php, resources/scripts/vertex/components/VersionChanger.tsx, config/vertex.php (minecraft_version_variable)


Properties Manager Stable

Vertex Properties Manager

What it does: Provides a visual editor for server.properties on Minecraft servers. It reads the current properties file via the Wings daemon API and presents them in categorized tabs. Each property definition includes:

  • key — The server.properties key (e.g., gamemode)
  • typestring, boolean, enum, or int
  • default — Minecraft's default value
  • category — Tab grouping (World, Gameplay, Network, Performance, Chat, Misc)
  • docUrl — Link to the Minecraft Wiki documentation page
  • description — Human-readable explanation

The frontend renders type-specific inputs:

  • Boolean → toggle switch with green indicator
  • Enum → dropdown select
  • Int → number field with increment/decrement buttons
  • String → text input

Changed properties that require a restart (port, level-name, online-mode, etc.) are flagged with a warning. A restart-required list of 18 property keys is maintained in PropertiesController::requiresRestart().

Implementation: PropertiesService::getProperties() fetches the current server.properties file from the Wings daemon HTTP API. getPropertyDefinitions() returns a 55+ item array of property metadata. updateProperties() writes changes back via the Wings API. The controller checks server ownership via the ChecksServerAccess trait and verifies the server is online before reading.

Files: src/Services/PropertiesService.php, src/Http/Controllers/PropertiesController.php, resources/scripts/vertex/components/PropertiesManager.tsx


5 Layout CSS Classes Stable

The following layout names are applied as CSS classes on the <body> element (e.g., <body class="vertex-layout-sidebar-right">). The InjectThemeSettings middleware reads the active layout from the theme settings and shares it with Blade views via View::share('vertexConfig', $config).

Config Key CSS Class Description
default vertex-layout-default Sidebar on the left (AdminLTE default)
sidebar-right vertex-layout-sidebar-right Sidebar on the right
topnav vertex-layout-topnav Top navigation bar, no sidebar
compact vertex-layout-compact Compact view with reduced padding
combined vertex-layout-combined Sidebar + horizontal top navigation

Note: The CSS classes are applied, but the actual CSS rules for each layout are still being refined in vertex.css. The class names serve as hooks for theme styling.


Subdomain Manager ⚠️ Partial

Vertex Subdomain Manager

What it does: Full CRUD for subdomain records linked to server allocations. Each subdomain has:

  • subdomain — The subdomain label (e.g., mc)
  • domain — The parent domain (e.g., crashmedia.ca)
  • allocation_id — Links to a Pterodactyl server allocation (IP:port)
  • record_typeA, CNAME, or ANAME
  • target — The DNS target value
  • ssl — Boolean flag for SSL (not automated yet)
  • active — Enable/disable toggle

What's missing (⚠️ Partial):

  • DNS API integration — Records are stored in the database but are NOT automatically created on external DNS providers (Cloudflare, Route53, etc.). Operators must create the DNS records manually.
  • SSL automation — The ssl flag exists on the model but there is no ACME integration (Let's Encrypt, Certbot, etc.).
  • Unique constraint bug — The unique constraint on the subdomain column is global across all domains. It should be scoped per-domain (e.g., mc.example.com and mc.mydomain.com should both be valid). The validation rule in SubdomainController::store() attempts to do a composite unique check but may not be fully correct.

Files: src/Http/Controllers/SubdomainController.php, src/Models/Subdomain.php, resources/scripts/vertex/components/SubdomainManager.tsx, database/migrations/2026_05_20_000010_create_subdomains_table.php, routes/api.php


Icon Changer ⚠️ Partial

Vertex Icon & Version Changer

What it does: Allows users to upload a custom PNG icon for their Minecraft server. The icon is:

  • Validated as PNG (MIME type check)
  • Limited to 2MB maximum
  • Resized to 64×64 pixels using Intervention/Image
  • Stored in Laravel's filesystem (Storage::put())
  • Served via the Storage::url() helper
  • The previous icon is removed when a new one is uploaded

The frontend (IconChanger.tsx) provides a drag-and-drop upload zone.

What's missing (⚠️ Partial):

  • Missing Composer dependency — The code in IconService.php imports Intervention\Image\ImageManager and Intervention\Image\Drivers\Gd\Driver, but composer.json does NOT declare intervention/image as a dependency. This means composer install will not pull in the required library, and the icon upload will fail at runtime. The fix is to add "intervention/image": "^3.0" to composer.json and run composer update.

Files: src/Http/Controllers/IconController.php, src/Services/IconService.php, src/Models/ServerIcon.php, resources/scripts/vertex/components/IconChanger.tsx, database/migrations/2026_05_20_000013_create_server_icons_table.php


Multi-Language Support ⚠️ Partial

What it does: Provides translatable strings for the theme. English is fully translated with both messages.php (flash messages, API responses) and theme.php (UI labels like "Dark Mode", "Privacy Mode", etc.).

Language status:

Language messages.php theme.php (UI labels)
English (en)
Dutch (nl)
German (de)
French (fr)
Spanish (es)

What's missing (⚠️ Partial):

  • Dutch, German, French, and Spanish have translated flash/API messages but the theme.php file with UI labels (Dark Mode, Light Mode, Privacy Mode, Server Sort methods, etc.) does not exist for these languages. These labels fall back to English.

Files:

  • resources/lang/en/messages.php + resources/lang/en/theme.php
  • resources/lang/nl/messages.php (only)
  • resources/lang/de/messages.php (only)
  • resources/lang/fr/messages.php (only)
  • resources/lang/es/messages.php (only)

Plugin Installer Stable

Vertex Plugin Installer

What it does: A fully integrated plugin marketplace that connects to four live APIs to let users browse, search, install, and uninstall plugins directly from the Pterodactyl panel — no manual SFTP needed.

Marketplace Connections

Marketplace API Endpoint Auth Required
Modrinth https://api.modrinth.com/v2 None
Hangar https://hangar.papermc.io/api/v1 None
SpigotMC https://api.spiget.org/v2 (community wrapper) None
CurseForge https://api.curseforge.com/v1 CURSEFORGE_API_KEY in .env

Search and browsing: The frontend (PluginInstaller.tsx) presents a tabbed marketplace switcher. Users can search across any of the four connected marketplaces. Search results show the plugin name, author, description, rating, download count, and a one-click install button.

Install and uninstall: Installation uses the real Pterodactyl Wings daemon API to:

  • Download the plugin JAR from the selected marketplace
  • Upload the JAR to the server's plugins/ directory via the Wings file API
  • Create an InstalledPlugin database record to track the installation

Uninstallation removes the JAR file from the server via the Wings daemon file delete API and removes the database record.

CurseForge setup: To enable CurseForge browsing, add your API key to the panel's .env file:

CURSEFORGE_API_KEY=$2a$10$your-key-here

Modrinth, Hangar, and SpigotMC work out of the box with no configuration needed.

Implementation: PluginMarketplaceService.php handles API communication with all four marketplaces. PluginController.php manages search, install, uninstall, and toggle operations, communicating with the Wings daemon for file operations. The frontend is in PluginInstaller.tsx.

Files: src/Services/PluginMarketplaceService.php, src/Http/Controllers/PluginController.php, src/Models/InstalledPlugin.php, resources/scripts/vertex/components/PluginInstaller.tsx, database/migrations/2026_05_20_000012_create_installed_plugins_table.php


📋 Planned Features (Config Flags Only)

These features have configuration keys in config/vertex.php but no backend or frontend implementation beyond the flag itself.

Feature Config Key Current State
Login Screen Variants login_layouts (4 options: centered card, split screen, fullscreen, minimal) Config exists; Blade template variants not built
Email Templates — (no dedicated flag) Not started
Font & Icon Picker font_family default exists UI picker not built; the default font is applied via CSS variable
File Manager Enhancements — (no dedicated flag) Folder upload and Monaco editor integration not started
PWA Support pwa_support (default: false) Config flag exists; manifest.json and service worker not written
Cloudflare Turnstile turnstile (default: false) Config flag exists; Turnstile widget integration not built
Export & Import — (no dedicated flag) Settings backup/restore not started
Page Builder page_builder (default: true) Config flag exists but only server sorting uses dnd-kit; the dashboard widget builder is not implemented

Full API Reference

Base URL: /api/client/vertex

All client endpoints require authentication (auth middleware) and are throttled at 60 requests per minute. Server-scoped endpoints additionally verify ownership via the ChecksServerAccess trait.

Theme Configuration

Method Endpoint Description
GET /theme Get current theme config, palette, feature flags, and user preferences
POST /editor/preview Generate a color palette preview without saving
POST /editor/apply Apply color changes to the database
POST /editor/preset/{name} Apply a named preset (blue, purple, emerald, rose, amber, cyan, indigo, pink, teal, violet, slate, orange)

Request body for /editor/preview and /editor/apply:

{
  "primary_color": "#2563eb",
  "background_color": "#f8fafc",
  "surface_color": "#ffffff",
  "text_color": "#0f172a"
}

Response from /editor/preview:

{
  "palette": { "50": "#eff6ff", "100": "#dbeafe", ..., "900": "#1e3a5f" },
  "css_vars": { "--vertex-primary-50": "#eff6ff", ... },
  "contrast": "#ffffff",
  "preview": { "primary": "#2563eb", "background": "#f8fafc", "surface": "#ffffff", "text": "#0f172a" }
}

Public Endpoint (no auth)

Method Endpoint Description
GET /api/vertex/public/theme Public theme config for login/register pages

Announcements

Method Endpoint Description
GET /announcements Get all currently-active announcements
POST /announcements/{id}/dismiss Dismiss an announcement (stored in session)

Server Sorting

Method Endpoint Description
GET /servers/sort Get the current user's sort preference
POST /servers/sort Save a sort preference

Request body for POST /servers/sort:

{
  "sort_order": [5, 2, 8, 1, 3],
  "sort_method": "custom"
}

Subdomain Manager (Addon 1)

Method Endpoint Auth Description
GET /servers/{server}/subdomains Owner List subdomains for a server
POST /servers/{server}/subdomains Owner Create a new subdomain
PUT /servers/{server}/subdomains/{id} Owner Update a subdomain record
DELETE /servers/{server}/subdomains/{id} Owner Delete a subdomain record
POST /subdomains/check User Check subdomain availability

Request body for POST /servers/{server}/subdomains:

{
  "subdomain": "mc",
  "domain": "crashmedia.ca",
  "allocation_id": 42,
  "record_type": "A",
  "target": "192.168.1.100",
  "ssl": false,
  "active": true
}

Minecraft Version Changer (Addon 2)

Method Endpoint Auth Description
GET /version-changer/versions User List all available Minecraft versions (categorized)
GET /servers/{server}/version Owner Get the current version for a server
POST /servers/{server}/version Owner Change the Minecraft version

Request body for POST /servers/{server}/version:

{
  "version": "1.21.4",
  "reinstall": false
}

Plugin Installer (Addon 3) Stable

Method Endpoint Auth Description
GET /plugins/search?query=world&marketplace=spigot User Search plugins from live marketplace APIs
GET /plugins/popular?marketplace=spigot User Get popular plugins from live marketplace APIs
GET /servers/{server}/plugins Owner List installed plugins on a server
POST /servers/{server}/plugins Owner Install a plugin (downloads JAR via Wings API)
DELETE /servers/{server}/plugins/{id} Owner Uninstall a plugin (deletes JAR via Wings API)
POST /servers/{server}/plugins/{id}/toggle Owner Enable/disable a plugin

Note: All marketplace queries hit live APIs (Modrinth, Hangar, SpigotMC, CurseForge). Installation downloads the JAR and deploys it to the server's plugins/ directory via the Wings daemon API. CurseForge requires CURSEFORGE_API_KEY in .env; Modrinth, Hangar, and SpigotMC require no API key.

Properties Manager (Addon 4)

Method Endpoint Auth Description
GET /servers/{server}/properties Owner Get all server properties with definitions
POST /servers/{server}/properties Owner Update server properties
POST /servers/{server}/properties/reset Owner Reset all properties to Minecraft defaults

Request body for POST /servers/{server}/properties:

{
  "properties": {
    "gamemode": "creative",
    "difficulty": "hard",
    "pvp": false,
    "max-players": 50
  }
}

Icon Changer (Addon 5)

Method Endpoint Auth Description
GET /servers/{server}/icon Owner Get current server icon URL and metadata
POST /servers/{server}/icon Owner Upload a new server icon (PNG, max 2MB)
DELETE /servers/{server}/icon Owner Remove the server icon

Request for POST /servers/{server}/icon: Multipart form upload with field name icon.

Admin Panel Endpoints (/admin/vertex)

These require Pterodactyl's admin middleware and are throttled at 30 req/min.

Method Endpoint Description
GET /admin/vertex Theme settings page
POST /admin/vertex Update theme settings
POST /admin/vertex/reset Reset all theme settings to defaults
GET /admin/vertex/editor Color editor page
GET /admin/vertex/announcements List all announcements
POST /admin/vertex/announcements Create an announcement
PUT /admin/vertex/announcements/{id} Update an announcement
DELETE /admin/vertex/announcements/{id} Delete an announcement
GET /admin/vertex/subdomains List all subdomains (global)
GET /admin/vertex/subdomains/create Create subdomain form
POST /admin/vertex/subdomains Store a new subdomain
GET /admin/vertex/subdomains/{id}/edit Edit subdomain form
PUT /admin/vertex/subdomains/{id} Update a subdomain
DELETE /admin/vertex/subdomains/{id} Delete a subdomain

Total: 29 client API endpoints + 1 public endpoint + 10 admin web routes = 40 total endpoints.


Architecture

Integration Model

Vertex is a Laravel package that integrates with Pterodactyl Panel through standard Laravel mechanisms. No core Pterodactyl files are modified.

┌──────────────────────────────────────────────────────────────────┐
│ Pterodactyl Panel (Laravel Application)                          │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │ Vertex Theme Package (crashmedia/vertex-theme)             │  │
│  │                                                            │  │
│  │  composer.json → extra.providers:                          │  │
│  │    VertexServiceProvider (auto-discovery)                  │  │
│  │                                                            │  │
│  │  ┌──────────────────────┐  ┌───────────────────────────┐  │  │
│  │  │ HTTP Layer            │  │ Services                   │  │  │
│  │  │                      │  │                            │  │  │
│  │  │ Controllers (8)      │  │ ThemeService               │  │  │
│  │  │ Middleware (1)        │  │ ColorService               │  │  │
│  │  │ Traits (1)            │  │ ColorPresetService         │  │  │
│  │  │ Routes (2 files)      │  │ VersionService             │  │  │
│  │  │ Views (Blade + React) │  │ PropertiesService          │  │  │
│  │  └──────────────────────┘  │ IconService                 │  │  │
│  │                             │ PluginMarketplaceService    │  │  │
│  │  ┌──────────────────────┐  └───────────────────────────┘  │  │
│  │  │ Data Layer            │                                  │  │
│  │  │                      │  ┌───────────────────────────┐  │  │
│  │  │ Models (6)            │  │ Frontend                   │  │  │
│  │  │ Migrations (7)        │  │                            │  │  │
│  │  │ Redis Cache           │  │ React SPA bundle           │  │  │
│  │  └──────────────────────┘  │ (webpack-built, 15+         │  │  │
│  │                             │  components, 3 hooks,      │  │  │
│  │                             │  2 providers, 1 store)     │  │  │
│  │                             │                            │  │  │
│  │                             │ CSS (4 files)              │  │  │
│  │                             │ I18n (5 languages)         │  │  │
│  │                             └───────────────────────────┘  │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │ Pterodactyl Core (untouched)                                │  │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │  │
│  │  │ Server   │  │ User     │  │ Node     │  │ Egg      │   │  │
│  │  │ Model    │  │ Model    │  │ Model    │  │ Model    │   │  │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘   │  │
│  └────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘

Data Flow

User visits any Pterodactyl page
       │
       ▼
InjectThemeSettings Middleware (applied to all web routes)
       │
       ├── Cache::remember('vertex.injected_settings', 3600)
       │       └── ThemeSetting::pluck('value', 'key')
       │
       ├── Merge with config('vertex.defaults')
       │
       ├── ColorService::generatePalette(primary_color)
       │       └── HSL interpolation → shades 50-900
       │       └── Rendered as CSS custom properties on :root
       │
       ├── View::share('vertexConfig', $config)
       │       └── Available in all Blade templates via $vertexConfig
       │
       └── request->attributes->set('vertex_config', $config)
               └── Consumed by Blade layout → passes to React root
React SPA initialization:
       │
       ▼
index.ts → fetches GET /api/client/vertex/theme
       │
       ▼
ThemeProvider (React Context) receives:
  - config (colors, font, radius, layout, login_layout)
  - palette (50-900 shades)
  - features (all feature flags)
  - user preferences (dark_mode, privacy_mode)
       │
       ├── ColorEditor.tsx → preview/apply/preset endpoints
       ├── ThemeToggle.tsx → dark/light toggle
       ├── PrivacyFilter.tsx → blur sensitive data
       ├── ServerSorter.tsx → @dnd-kit drag-and-drop
       ├── FloatingWindowManager.tsx → context for windows
       ├── AnnouncementBanner.tsx → active announcements
       └── Addon components → VersionChanger, PropertiesManager,
            PluginInstaller, SubdomainManager, IconChanger

Caching Strategy

Cache Key TTL Purpose Invalidation
vertex.theme_config 3600s Merged theme settings Cleared on any setting update or reset
vertex.injected_settings 3600s Raw settings for middleware Same as above
vertex.settings N/A Legacy key (cleared on updates)
vertex.minecraft_versions 3600s Mojang manifest Expires naturally

Cache is invalidated by ThemeService::updateSettings(), resetToDefaults(), and model events.

Database Schema

Migration Table Purpose
2026_05_20_000001 theme_settings Key-value store for all theme configurations
2026_05_20_000002 announcements Announcement records with scheduling
2026_05_20_000003 server_sort_preferences Per-user server sort order
2026_05_20_000004 (alters users) Adds vertex_dark_mode and vertex_privacy_mode columns
2026_05_20_000010 subdomains Subdomain records linked to servers
2026_05_20_000012 installed_plugins Plugin installation records
2026_05_20_000013 server_icons Server icon metadata and file paths

Installation

Prerequisites

  • PHP 8.2+
  • Pterodactyl Panel v1.12.2+
  • Node.js 20+ (for building frontend assets)
  • Composer 2+
  • NPM 9+
  • Redis or Memcached (recommended for caching)
cd /var/www/pterodactyl

# Require the package via Composer
composer require crashmedia/vertex-theme

# Run the installer — publishes config, runs migrations, publishes assets
php artisan vertex:install

# Build frontend assets
cd vendor/crashmedia/vertex-theme
npm ci && npm run build:all

# Return to panel root and clear cache
cd /var/www/pterodactyl
php artisan optimize:clear

Manual Installation (Development)

cd /var/www/pterodactyl
git clone https://git.crashmedia.ca/crashmedia/vertex-pterodactyl.git app/extensions/vertex-theme

Add to your panel's composer.json:

{
  "repositories": [
    {
      "type": "path",
      "url": "app/extensions/vertex-theme"
    }
  ]
}

Then:

composer require crashmedia/vertex-theme "@dev"
php artisan vertex:install

Post-Installation

  1. Visit /admin/vertex in your Pterodactyl panel to configure the theme
  2. Set your primary color, choose a layout, and configure announcements
  3. The CSS and JS assets are automatically injected by the package — no manual Blade template edits are required
  4. Run migrations if prompted:
    php artisan migrate
    

Configuration

Feature Flags

All feature flags live in config/vertex.php under the features key:

'features' => [
    'announcements'     => true,  // ✅ Stable — Announcement manager
    'server_sorting'    => true,  // ✅ Stable — Drag-and-drop sorting
    'custom_css'        => true,  // ✅ Stable — Custom CSS injection (admin panel)
    'dark_mode_toggle'  => true,  // ✅ Stable — Dark/light mode toggle
    'custom_logo'       => true,  // ✅ Stable — Custom logo upload
    'page_builder'      => true,  // 📋 Planned — Dashboard widget system
    'privacy_mode'      => true,  // ✅ Stable — IP/sensitive data blurring
    'floating_windows'  => true,  // ✅ Stable — Floating window multitasking
    'pwa_support'       => false, // 📋 Planned — Service worker not written
    'turnstile'         => false, // 📋 Planned — Requires Cloudflare Turnstile keys
    'plugin_installer'  => true,  // ✅ Stable — 4 live marketplace APIs + Wings deployment
    'icon_changer'      => true,  // ⚠️ Partial — Needs intervention/image dep
    'subdomain_manager' => true,  // ⚠️ Partial — DNS/SSL automation missing
    'version_changer'   => true,  // ✅ Stable — Mojang manifest + egg variable update
],

Layout Options

'layouts' => [
    'default'       => 'Default Sidebar (Left)',
    'sidebar-right' => 'Sidebar Right',
    'topnav'        => 'Top Navigation',
    'compact'       => 'Compact View',
    'combined'      => 'Combined (Sidebar + Topnav)',
],

Login Layouts (📋 Planned)

'login_layouts' => [
    'default'    => 'Centered Card',
    'split'      => 'Split Screen',
    'fullscreen' => 'Full Screen Background',
    'minimal'    => 'Minimal',
],

Default Theme Values

'defaults' => [
    'primary_color'    => '#2563eb',
    'background_color' => '#f8fafc',
    'surface_color'    => '#ffffff',
    'text_color'       => '#0f172a',
    'font_family'      => "'IBM Plex Sans', system-ui, sans-serif",
    'border_radius'    => '0.5rem',
    'dark_mode'        => false,
    'layout'           => 'default',
    'login_layout'     => 'default',
],

Environment Variables

Variable Default Description
MC_VERSION_VARIABLE MC_VERSION Egg variable name for Minecraft version changer
CURSEFORGE_API_KEY API key for CurseForge marketplace (plugin installer)

Development

Setup

git clone https://git.crashmedia.ca/crashmedia/vertex-pterodactyl.git
cd vertex-pterodactyl

# Install dependencies
npm ci
composer install

# Build all assets
npm run build:all

# Development mode (watch for changes)
npm run dev

Build Commands

Command Description
npm run build Build the Webpack JS bundle (vertex.bundle.js)
npm run build:css Build the main stylesheet (vertex.css)
npm run build:css-dark Build dark mode overrides (vertex-dark.css)
npm run build:css-admin Build admin panel styles (vertex-admin.css)
npm run build:all Build all assets (JS + CSS + dark + admin + floating)
npm run dev Watch mode for development

Project Structure

vertex-pterodactyl/
├── config/
│   └── vertex.php                        # Package configuration
├── database/
│   └── migrations/                       # 7 migration files
├── resources/
│   ├── css/
│   │   ├── vertex.css                    # Main stylesheet
│   │   ├── vertex-dark.css               # Dark mode overrides
│   │   ├── vertex-admin.css              # Admin panel styles
│   │   └── vertex-floating.css           # Floating window styles
│   ├── lang/
│   │   ├── en/                           # English (full)
│   │   ├── nl/                           # Dutch (messages only)
│   │   ├── de/                           # German (messages only)
│   │   ├── fr/                           # French (messages only)
│   │   └── es/                           # Spanish (messages only)
│   ├── scripts/vertex/
│   │   ├── index.ts                      # React entry point
│   │   ├── components/                   # 15 React components
│   │   │   ├── AnnouncementBanner.tsx
│   │   │   ├── ColorEditor.tsx
│   │   │   ├── FloatingTaskbar.tsx
│   │   │   ├── FloatingWindow.tsx
│   │   │   ├── FloatingWindowManager.tsx
│   │   │   ├── IconChanger.tsx
│   │   │   ├── PluginInstaller.tsx
│   │   │   ├── PrivacyFilter.tsx
│   │   │   ├── PropertiesManager.tsx
│   │   │   ├── ServerContextMenu.tsx
│   │   │   ├── ServerSorter.tsx
│   │   │   ├── SortableItem.tsx
│   │   │   ├── SubdomainManager.tsx
│   │   │   ├── ThemeToggle.tsx
│   │   │   └── VersionChanger.tsx
│   │   ├── hooks/
│   │   │   ├── useLocalStorage.ts
│   │   │   ├── useServerContextMenu.ts
│   │   │   └── useServerSort.ts
│   │   ├── providers/
│   │   │   ├── AnnouncementProvider.tsx
│   │   │   └── ThemeProvider.tsx
│   │   ├── stores/
│   │   │   └── themeStore.ts
│   │   ├── layouts/
│   │   │   └── ThemeWrapper.tsx
│   │   └── types/
│   │       └── theme.ts
│   └── views/admin/                      # Blade templates for admin panel
├── routes/
│   ├── api.php                           # 29 client API routes
│   └── web.php                           # 10 admin web routes
├── src/
│   ├── Console/Commands/
│   │   └── ThemeInstallCommand.php       # php artisan vertex:install
│   ├── Http/
│   │   ├── Controllers/                  # 8 controllers
│   │   │   ├── AnnouncementController.php
│   │   │   ├── IconController.php
│   │   │   ├── PluginController.php
│   │   │   ├── PropertiesController.php
│   │   │   ├── ServerSortController.php
│   │   │   ├── SubdomainController.php
│   │   │   ├── ThemeController.php
│   │   │   └── VersionChangerController.php
│   │   ├── Middleware/
│   │   │   └── InjectThemeSettings.php
│   │   └── Traits/
│   │       └── ChecksServerAccess.php
│   ├── Models/                           # 6 Eloquent models
│   │   ├── Announcement.php
│   │   ├── InstalledPlugin.php
│   │   ├── ServerIcon.php
│   │   ├── ServerSortPreference.php
│   │   ├── Subdomain.php
│   │   └── ThemeSetting.php
│   ├── Providers/
│   │   └── VertexServiceProvider.php     # Laravel auto-discovery provider
│   └── Services/                         # 7 service classes
│       ├── ColorPresetService.php
│       ├── ColorService.php
│       ├── IconService.php
│       ├── PluginMarketplaceService.php
│       ├── PropertiesService.php
│       ├── ThemeService.php
│       └── VersionService.php
├── screenshots/
│   ├── 03-vertex-plugin-installer.png
│   ├── 04-vertex-color-editor.png
│   ├── 05-vertex-floating-windows.png
│   ├── 06-vertex-announcements.png
│   ├── 07-vertex-properties-manager.png
│   ├── 08-vertex-subdomain-manager.png
│   └── 09-vertex-icon-version-changer.png
├── composer.json
├── package.json
├── webpack.config.js
├── postcss.config.js
├── tailwind.config.js
├── tsconfig.json
└── .gitignore

Security

Access Control

  • Server-scoped authorization — All addon endpoints use the ChecksServerAccess trait to verify server ownership or subuser membership before any operation. Admin users bypass these checks via $user->root_admin.
  • Admin routes — Protected by Pterodactyl's auth + admin middleware and throttled at 30 requests/minute.
  • Client API — Protected by auth middleware and throttled at 60 requests/minute.
  • Public endpoint/api/vertex/public/theme requires no authentication and only exposes non-sensitive theme configuration.

Input Validation

  • Color values — Strict hex format validation (/^#[0-9a-fA-F]{6}$/)
  • Subdomains — Validated against DNS naming conventions (/^[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?$/)
  • File uploads — Icon uploads validated by MIME type (PNG only), and size (max 2MB). Server-side resizing to exactly 64×64 pixels.
  • Version strings — Validated against the Mojang version manifest before updating egg variables.

General Protections

  • CSRF — All web routes protected by Laravel CSRF middleware
  • XSS Prevention — Blade templates use {{ }} escaped output; React components are JSX (auto-escaped by React)
  • Error Handling — Exception messages are logged server-side and replaced with generic messages in API responses
  • SQL Injection — All queries use Eloquent ORM with parameter binding
  • Rate Limiting — Admin routes: 30 req/min; Client routes: 60 req/min

Package Scope

Vertex does not modify any Pterodactyl core files. It uses:

  • Laravel package auto-discovery (composer.json extra.providers)
  • Middleware injection (InjectThemeSettings)
  • View sharing (View::share())
  • Standard Eloquent relations on Pterodactyl models (no modifications)

Browser Support

Browser Minimum Version
Chrome / Edge 90+
Firefox 90+
Safari 15+
Opera 76+

License

MIT License — see LICENSE for details.

Copyright (c) 2026 CrashMedia


Known Issues & Roadmap

Immediate Priorities

  1. Add intervention/image to composer.json — Icon uploads will fail without it.
  2. Fix subdomain unique constraint — Should be scoped by domain, not global.
  3. Create theme.php translations — Dutch, German, French, and Spanish translations for UI labels.

Upcoming Features

Feature Target
DNS API integration (Cloudflare, Route53) for subdomain manager v1.1
SSL/ACME automation for subdomains v1.1
Login screen variants v1.1
PWA service worker and manifest v1.2
Cloudflare Turnstile integration v1.2
Page builder drag-and-drop widgets v1.2
File manager enhancements (folder upload, Monaco editor) v1.2
Font & icon picker UI v1.2
Email template customization v1.3
Settings export/import v1.3

Support