cyanide / hydrodactyl-themes
Per-user color theme customization for Hydrodactyl. Six accent color themes: blue, green, red, yellow, pink, purple.
Package info
github.com/Fabatax/hydrodactyl-themes
Language:Shell
pkg:composer/cyanide/hydrodactyl-themes
Requires
- php: ^8.2
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Per-user accent color customization for Hydrodactyl — six color themes: Blue, Green, Red, Yellow, Pink, Purple.
This package adds a theme selector to the Account Overview page. Each user picks their own accent color, which overrides the panel's sidebar highlight, buttons, links, focus states, and other branded elements. Changes apply immediately on save with a page reload.
Requires Hydrodactyl v6.
Themes
| Theme | Color | Description |
|---|---|---|
| Blue | #3b82f6 |
Hydrodactyl's default look (no-op stylesheet) |
| Green | #22c55e |
Fresh green accent |
| Red | #ef4444 |
Warmer red accent (vs Hydrodactyl's orange-red) |
| Yellow | #eab308 |
Amber — good for dark-mode legibility |
| Pink | #ec4899 |
Hot pink accent |
| Purple | #a855f7 |
Rich purple accent |
Requirements
- Hydrodactyl v6 (Pterodactyl v6 fork — BlueprintFramework/hydrodactyl)
- PHP 8.2+
- Laravel 11 or 12 (included in Hydrodactyl v6)
- Composer
Installation
Option A — Automated (recommended)
curl -sL https://raw.githubusercontent.com/Fabatax/hydrodactyl-themes/main/install.sh | bash
The script will detect your panel directory, install the package, publish assets, register routes, run the migration, and clear caches.
Option B — Manual
Step 1 — Install the Composer package
From inside your Hydrodactyl panel directory:
composer require cyanide/hydrodactyl-themes
Step 2 — Publish theme CSS assets
php artisan vendor:publish --tag=hydrodactyl-themes-assets --force
This copies the theme CSS files to public/vendor/hydrodactyl-themes/css/.
Step 3 — Register the API routes
Open routes/api-client.php in your Hydrodactyl installation and add this line just before the closing }); of the Route::prefix('/account') group:
require __DIR__ . '/../../vendor/cyanide/hydrodactyl-themes/routes/api-client-theme.php';
This places the theme routes inside Hydrodactyl's existing /api/client/account middleware group, so authentication and subject verification are handled automatically. The theme route is intentionally placed inside the section that does not require 2FA, so users can change their theme even before setting up two-factor authentication.
Step 4 — Run the database migration
php artisan migrate
This adds a theme column (varchar 32, default blue) to the users table. Existing users keep the default blue accent.
Step 5 — Clear caches
php artisan cache:clear php artisan config:clear php artisan route:clear
Step 6 — Integrate the React component
Copy the theme picker component into your Hydrodactyl frontend:
cp vendor/cyanide/hydrodactyl-themes/resources/views/settings/ThemeSettings.tsx \ resources/scripts/components/dashboard/ThemeSettings.tsx
Copy the API helper file:
cp vendor/cyanide/hydrodactyl-themes/resources/views/api/updateAccountTheme.ts \ resources/scripts/api/account/updateAccountTheme.ts
Then register the component in resources/scripts/components/dashboard/AccountOverviewContainer.tsx:
-
Add the import near the top:
import ThemeSettings from '@/components/dashboard/ThemeSettings';
-
Insert
<ThemeSettings />between the MFA section and the Panel Version section:{/* MFA ContentBox ends here */} <ThemeSettings /> {/* Panel Version ContentBox starts here */}
Step 7 — Rebuild the frontend
npm run build
Step 8 — Done
- Log out and log back in to refresh your session.
- Go to Account (the Overview tab).
- Find the Accent Color Theme section.
- Pick a color and click Reload Theme. The page will reload with your new accent.
Uninstallation
# Remove the package composer remove cyanide/hydrodactyl-themes # Roll back the migration (optional — the column will remain harmless) php artisan migrate:rollback --path=database/migrations/2026_01_01_000000_add_theme_to_users_table.php
Also remove the require line from routes/api-client.php that you added in Step 3, and delete the copied React files from resources/scripts/components/dashboard/ThemeSettings.tsx and resources/scripts/api/account/updateAccountTheme.ts.
How it works
Backend
themecolumn on theuserstable — stores the active theme slug (blue,green,red,yellow,pink,purple).ThemeControlleratsrc/Http/Controllers/Api/ThemeController.php— handlesGET /api/client/account/theme(read) andPUT /api/client/account/theme(update).InjectThemeStylesheetmiddleware — fires on every HTML page load (skips/api/*JSON routes). If the user has a non-blue theme, it injects a<link>tag pointing to their theme CSS file before</head>.ThemeServiceProvider— registers the middleware in thewebgroup, publishes assets, and loads migrations.
Frontend
ThemeSettings.tsx— a React component that renders the color swatch grid on the Account Overview page. Reads the current theme from the user store and saves changes viaupdateAccountTheme(). After saving, it reloads the page so the new stylesheet is applied.
CSS override strategy
Each theme CSS file overrides:
- CSS custom properties —
--color-brand,--color-cream-400,--color-cream-300,--color-cream-500. These drive the sidebar active/hover text and icon colors. - Sidebar selectors —
.sidebar-container li:hover a,.sidebar-container:not(:has(li:hover)) li[data-active="true"] a— the sliding pill indicator and active nav item color. - UI polish —
::selectioncolor, focus ring colors, command palette caret color, Sonner toast accent borders.
Troubleshooting
The theme selector doesn't appear on the Account page
- Make sure you rebuilt the frontend after copying
ThemeSettings.tsx(npm run build). - Verify the component is properly imported in
AccountOverviewContainer.tsxand placed inside the JSX. - Check the browser console for any import errors.
Theme changes don't apply after saving
- Clear your browser cache — the stylesheet URL includes a version cache-buster, but the browser may have cached the old stylesheet.
- Check the browser DevTools Network tab for the theme CSS file (e.g.
vendor/hydrodactyl-themes/css/green.css) and verify it returns HTTP 200. - Check that
public/vendor/hydrodactyl-themes/css/contains all six CSS files. If not, re-runphp artisan vendor:publish --tag=hydrodactyl-themes-assets --force.
Route returns 401 Unauthorized
Make sure the require statement in routes/api-client.php is placed inside the account route group (before the closing });). The theme routes rely on AccountSubject middleware applied by the parent group.
Migration fails — "duplicate column" or "duplicate key"
The migration has already run. This is safe to ignore.
File structure
hydrodactyl-themes/
├── composer.json
├── config/
│ └── themes.php # Theme list, default, version
├── database/migrations/
│ └── 2026_01_01_000000_add_theme_to_users_table.php
├── resources/
│ ├── css/themes/
│ │ ├── blue.css # No-op (matches default)
│ │ ├── green.css
│ │ ├── red.css
│ │ ├── yellow.css
│ │ ├── pink.css
│ │ └── purple.css
│ └── views/
│ ├── api/
│ │ └── updateAccountTheme.ts # API helper
│ └── settings/
│ └── ThemeSettings.tsx # React component
├── routes/
│ └── api-client-theme.php
└── src/
├── Http/
│ ├── Controllers/
│ │ └── Api/
│ │ └── ThemeController.php
│ └── Middleware/
│ └── InjectThemeStylesheet.php
└── ThemeServiceProvider.php