nowakadmin / novasettings
A Laravel Nova tool.
Installs: 23
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/nowakadmin/novasettings
Requires
- php: ^8.1
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- laravel/nova: ^5.0
- laravel/nova-devtool: ^1.7
This package is auto-updated.
Last update: 2026-01-11 18:26:21 UTC
README
A modern, tab-based settings management tool for Laravel Nova with conditional field visibility, real-time validation, and multi-tenancy support.
Features
✨ Tab-Based Organization — Group settings into logical tabs that adapt dynamically
🎨 Light & Dark Theme — Fully supports Nova's light and dark modes
🔄 Conditional Visibility — Show/hide fields based on other field values
📝 Real-Time Validation — Instant feedback with Laravel validation rules
🏢 Multi-Tenancy Ready — Tenant-scoped settings via Spatie Multitenancy
💾 Smart Saving — Only saves changed values, not entire form
🚀 Modern UI — Built with Vue 3, Inertia.js, and Tailwind CSS
Installation
1. Install via Composer
composer require nowakadmin/nova-settings
2. Publish Configuration
php artisan vendor:publish --tag=nova-settings-config
This creates config/nova-settings.php where you define your settings schema.
3. Publish and Run Migration
# Publish the settings table migration php artisan vendor:publish --tag=nova-settings-migration # Run the migration php artisan migrate
The migration creates a settings table with:
4. Database Setup (Legacy/Manual)
Ensure you have a settings table with at minimum:
keycolumn (string) — Setting name/identifiervaluecolumn (string/text) — Setting value- Tenant-scoped if using multi-tenancy
Example migration:
Schema::create('settings', function (Blueprint $table) { $table->id(); $table->string('key')->unique(); $table->text('value')->nullable(); $table->timestamps(); });
4. Register Tool in Nova
In app/Providers/NovaServiceProvider.php:
use NowakAdmin\NovaSettings\NovaSettings; public function tools() { return [ new NovaSettings, ]; }
Configuration
Basic Setup
Edit config/nova-settings.php:
return [ 'model' => 'App\\Models\\Setting', // Your settings model 'keycol' => 'key', // Column storing setting name 'valuecol' => 'value', // Column storing setting value 'settings' => [ // Define your settings here ], ];
Defining Settings
Each setting is an array with these properties:
| Property | Type | Required | Description |
|---|---|---|---|
name |
string | ✅ | Unique identifier (stored in database) |
label |
string | ✅ | Human-readable label shown in UI |
type |
string | ✅ | Field type: text, email, number, textarea, boolean, select |
group |
string | ✅ | Tab/group name for organization |
validation |
string | ✅ | Laravel validation rules |
placeholder |
string | ❌ | Placeholder text for inputs |
help |
string | ❌ | Helper text displayed below field |
options |
array | ❌ | Array of ['label' => '', 'value' => ''] for select type |
vif |
array | ❌ | Conditional visibility: ['field_name', 'expected_value'] |
Field Types
Text Input
[
'name' => 'company_name',
'label' => 'Company Name',
'type' => 'text',
'group' => 'Company Info',
'validation' => 'required|string|max:255',
'placeholder' => 'Enter company name',
]
Email Input
[
'name' => 'contact_email',
'label' => 'Contact Email',
'type' => 'email',
'group' => 'Contact',
'validation' => 'nullable|email|max:255',
'placeholder' => 'email@example.com',
]
Number Input
[
'name' => 'max_users',
'label' => 'Maximum Users',
'type' => 'number',
'group' => 'Limits',
'validation' => 'nullable|integer|min:1|max:1000',
]
Textarea
[
'name' => 'company_description',
'label' => 'Company Description',
'type' => 'textarea',
'group' => 'Company Info',
'validation' => 'nullable|string|max:2000',
'placeholder' => 'Describe your company...',
]
Boolean / Checkbox
[
'name' => 'maintenance_mode',
'label' => 'Enable Maintenance Mode',
'type' => 'boolean',
'group' => 'System',
'validation' => 'nullable|in:0,1',
]
Select / Dropdown
[
'name' => 'notification_provider',
'label' => 'Notification Provider',
'type' => 'select',
'group' => 'Integrations',
'validation' => 'required|in:email,sms,slack',
'options' => [
['label' => 'Email', 'value' => 'email'],
['label' => 'SMS', 'value' => 'sms'],
['label' => 'Slack', 'value' => 'slack'],
],
'placeholder' => 'Choose provider',
'help' => 'Select which system handles notifications.',
]
Conditional Visibility
Show or hide fields based on other field values using the vif option.
Example: Provider-Specific Settings
'settings' => [ // Provider selector [ 'name' => 'payment_gateway', 'label' => 'Payment Gateway', 'type' => 'select', 'group' => 'Payments', 'validation' => 'required|in:stripe,paypal,manual', 'options' => [ ['label' => 'Stripe', 'value' => 'stripe'], ['label' => 'PayPal', 'value' => 'paypal'], ['label' => 'Manual', 'value' => 'manual'], ], ], // Stripe-specific fields (only visible when Stripe is selected) [ 'name' => 'stripe_api_key', 'label' => 'Stripe API Key', 'type' => 'text', 'group' => 'Payments - Stripe', 'validation' => 'nullable|string|max:255', 'vif' => ['payment_gateway', 'stripe'], // Show only when payment_gateway = stripe ], [ 'name' => 'stripe_secret', 'label' => 'Stripe Secret', 'type' => 'text', 'group' => 'Payments - Stripe', 'validation' => 'nullable|string|max:255', 'vif' => ['payment_gateway', 'stripe'], ], // PayPal-specific fields [ 'name' => 'paypal_client_id', 'label' => 'PayPal Client ID', 'type' => 'text', 'group' => 'Payments - PayPal', 'validation' => 'nullable|string|max:255', 'vif' => ['payment_gateway', 'paypal'], // Show only when payment_gateway = paypal ], ];
How vif Works
- Format:
'vif' => ['field_name', 'expected_value'] - Behavior:
- Field is shown when
field_nameequalsexpected_value - Field is hidden otherwise
- Changes are reactive — fields appear/disappear as you change the controlling field
- If all fields in a group are hidden, the tab disappears too
- If you're on a hidden tab, you're automatically switched to the first visible tab
- Field is shown when
Validation Best Practices with vif
When using conditional fields, always use nullable validation for optional fields:
// ✅ Correct — nullable allows field to be skipped when hidden 'validation' => 'nullable|email|max:255', // ❌ Avoid — required will fail validation when field is hidden 'validation' => 'required|email|max:255',
Multi-Tenancy Support
NovaSettings works seamlessly with Spatie Multitenancy. Ensure your settings model uses the tenant connection:
use Spatie\Multitenancy\Models\Concerns\UsesTenantConnection; class Setting extends Model { use UsesTenantConnection; protected $fillable = ['key', 'value']; }
Accessing Settings in Code
Reading Settings
use App\Models\Setting; // Get a single setting $companyName = Setting::where('key', 'company_name')->value('value'); // Get with default value $maxUsers = Setting::where('key', 'max_users')->value('value') ?? 100; // Get boolean setting $maintenanceMode = (bool) Setting::where('key', 'maintenance_mode')->value('value');
Setting Values Programmatically
use App\Models\Setting; // Create or update Setting::updateOrCreate( ['key' => 'company_name'], ['value' => 'Acme Corporation'] ); // Bulk update $settings = [ 'company_name' => 'Acme Corp', 'company_email' => 'info@acme.com', ]; foreach ($settings as $key => $value) { Setting::updateOrCreate(['key' => $key], ['value' => $value]); }
Helper Function (Optional)
Create a helper for easy access:
// app/Helpers/settings.php if (!function_exists('setting')) { function setting(string $key, $default = null) { return \App\Models\Setting::where('key', $key)->value('value') ?? $default; } } // Usage $companyName = setting('company_name', 'Default Company');
UI Features
Smart Saving
- Only changed values are sent to the server
- Prevents unnecessary validation errors on untouched fields
- Shows "No changes to save" message if nothing changed
- Auto-hides success messages after 5 seconds
Real-Time Validation
- Server-side validation rules applied on save
- Clear error messages with field names
- Errors displayed at the top of the form
Tab Behavior
- Tabs are sorted alphabetically
- Empty tabs (all fields hidden via
vif) automatically disappear - Active tab switches to first available if current tab becomes hidden
- Mobile-responsive with scrollable tabs
Button States
- Save button disabled while saving
- Spinner icon during save operation
- Reset button clears form to original values
Advanced Usage
Grouping Related Settings
Use descriptive group names to organize settings logically:
'settings' => [ // Company Info [...], // company_name, company_address, etc. // Integrations [...], // payment_gateway, shipping_provider, etc. // Security [...], // 2fa_enabled, session_timeout, etc. // Notifications [...], // email_notifications, sms_enabled, etc. ],
Cascading Conditional Fields
You can chain vif conditions across multiple fields:
[
'name' => 'level_1',
'type' => 'select',
'group' => 'Settings',
// ... options
],
[
'name' => 'level_2',
'type' => 'select',
'group' => 'Settings',
'vif' => ['level_1', 'option_a'],
// ... options
],
[
'name' => 'level_3',
'type' => 'text',
'group' => 'Settings',
'vif' => ['level_2', 'option_b'], // Only visible when level_1=option_a AND level_2=option_b
],
Custom Model Column Names
If your settings table uses different column names:
'model' => 'App\\Models\\Config', 'keycol' => 'setting_name', // Instead of 'key' 'valuecol' => 'setting_data', // Instead of 'value'
Troubleshooting
Settings Not Showing
- Verify the tool is registered in
NovaServiceProvider - Check that your settings model exists and is accessible
- Run
php artisan config:clearafter changing config
Validation Errors on Hidden Fields
- Ensure hidden/conditional fields use
nullablevalidation - Check that
vifreferences the correct field name (not label)
Tab Not Appearing
- Verify
groupname matches across related fields - Check if all fields in the group have
vifconditions that hide them
Dark Mode Issues
- Ensure you've compiled assets:
npm run production - Clear browser cache
- Verify Nova's dark mode is enabled in Nova settings
Development
Building Assets
cd vendor/nowakadmin/nova-settings npm install npm run production # For production npm run dev # For development with watch
File Structure
nova-settings/
├── config/
│ └── nova-settings.php # Default config (published)
├── resources/
│ ├── js/
│ │ └── pages/
│ │ └── Tool.vue # Main Vue component
│ └── views/
│ └── navigation.blade.php
├── src/
│ ├── Http/
│ │ └── Controllers/
│ │ └── SettingsController.php
│ ├── NovaSettings.php # Tool class
│ └── ToolServiceProvider.php
└── routes/
└── inertia.php # Tool routes
Requirements
- PHP 8.1+
- Laravel 10+
- Laravel Nova 4+
- Vue 3
- Inertia.js
License
MIT License — free to use and modify.
Support
For issues, feature requests, or contributions open an issue in the repository.
Built with ❤️ for Laravel Nova