Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Settings Laravel Package

epigra/nova-settings

Epigra Nova Settings adds a settings management tool to Laravel Nova, letting you create, organize, and edit application settings from a dedicated interface. Store key/value settings in the database and access them easily throughout your Laravel app.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets first — the tool ships with a config file and a migration that are both required before anything renders in Nova.

composer require epigra/nova-settings
php artisan vendor:publish --provider="Epigra\NovaSettings\ToolServiceProvider"
php artisan migrate

Then register the tool in app/Providers/NovaServiceProvider.php:

public function tools()
{
    return [
        new \Epigra\NovaSettings\NovaSettings,
    ];
}

Where to look first: open config/nova-settings.php after publishing. That file is the source of truth for which setting groups/tabs appear, their labels, and often the storage/cache behaviour. Read it before writing any code — most "the tool is empty" confusion is a config registration problem, not a code problem.

First use case: site-wide editable values that non-developers need to change without a deploy — support email, social links, a maintenance-mode toggle, footer copy. Define a settings class (or a config entry, depending on your version) that returns native Nova fields:

// app/Nova/Settings/GeneralSettings.php
class GeneralSettings
{
    public static function fields(): array
    {
        return [
            Text::make('Support Email', 'support_email')
                ->rules('required', 'email'),
            Boolean::make('Maintenance Mode', 'maintenance_mode'),
            Image::make('Logo', 'logo')->disk('public'),
        ];
    }
}

Register it in the config, reload Nova, and you have an editable panel. Read the values back in your app through the package's helper/facade (commonly settings('support_email') or Settings::get('support_email')) — check the package's README for the exact accessor name, since it has changed across releases.

Implementation Patterns

One settings class per domain, not one giant form. Group related values — GeneralSettings, SocialSettings, SeoSettings — and map each to a tab in the config. Nova renders them as separate panes, which keeps the tool navigable as the number of values grows and lets you scope authorization per group later.

Treat the field definitions as the schema. Because fields are native Nova fields, you get the full field API for free: validation ->rules(), ->help(), ->placeholder(), conditional display via ->dependsOn(), and ->readonly(). Lean on that instead of building custom form logic. For a select whose options are dynamic, compute them in fields() rather than hardcoding:

Select::make('Currency', 'currency')
    ->options(collect(config('app.currencies'))->pluck('name', 'code'))
    ->default('USD'),

Always define defaults and fall back in the reader. Settings rows may not exist yet on a fresh environment. Wrap reads:

$email = settings('support_email') ?? config('mail.from.address');

Better: centralise this in a small typed accessor class (app/Support/SiteSettings.php) so business logic never hits the raw package helper. That gives you one place to change when the package's API shifts and one place to add casting (JSON → array, "1" → true).

Cache aggressively and invalidate on save. These values are read on nearly every request; a DB hit per key adds up. If the package doesn't cache automatically (check the config — there's usually a cache toggle and TTL), wrap your accessor in Cache::rememberForever() and flush on the tool's save event, or override the model/save hook to call Cache::forget().

Keep secrets out of it. This is a convenience store for human-editable values, not a vault. API keys and tokens belong in .env/your secrets manager. If you must store one, at minimum encrypt it in the accessor and gate the group behind a policy.

Expose it to the frontend deliberately. Don't dump the whole settings payload into every Blade view via a global composer. Pass individual keys from the controller, or add a small SettingsResource endpoint returning only public keys — settings tables drift into accidental data leaks otherwise.

Test with the store, not the UI. In feature tests, seed values by writing directly through the package's model/facade in setUp(), then assert on your app's output. Don't test the Nova tool itself; test the read path your application depends on.

Gotchas and Tips

  • Stale values after saving. The single most common complaint. If caching is on, a save from the Nova UI must bust the cache. If you add your own cache layer on top, double-check that your key is invalidated too — the package won't know about it.
  • Migration already run. vendor:publish won't overwrite an existing migration or config without --force. If you upgrade the package and a migration is missing, publish with --force into a scratch dir and diff it by hand rather than overwriting your config.
  • Key naming collisions. Keys are effectively flat strings. If group A and group B both define title, decide up front whether they're namespaced (general.title vs seo.title) and be consistent — silently overwriting each other's values is easy to miss.
  • Boolean false vs missing. A Boolean field that was never saved returns null, not false. Use (bool) settings('maintenance_mode') or the field's ->default(false) plus a null-coalescing read, otherwise a "missing" flag will read as off when you meant "unset" — or worse, as on.
  • File uploads don't clean up after themselves. Replacing a logo with the Image field leaves the old file on disk. Listen for the save/update event and delete the previous path if orphaned files matter to you. Also confirm the disk is in config/filesystems.php and publicly linked (php artisan storage:link).
  • Registration order in Nova. Tools are loaded in NovaServiceProvider::tools(); if a custom policy or menu override depends on the settings tool existing, register it after. And remember nova-components/tool routes are cached with Nova — after changing config, run php artisan nova:cache (or clear it) if the panel doesn't update.
  • Authorization is coarse by default. Restrict who can open the tool with ->canSee(fn ($request) => $request->user()->isAdmin()) in tools(), and push finer-grained control into Nova policies if a group is sensitive (e.g. billing details hidden from editors).
  • Extension point: override the model. Most Epigra packages let you swap the underlying model via config ('model' => App\Models\Settings::class). Subclass it when you need casts, observers, or a custom get() so you don't fight the package in service providers.
  • Debugging in tinker. When the UI shows one value and your code shows another, dump the raw row (Settings::all() or DB::table('settings')->get()) and the raw cache entry. The mismatch is almost always (a) cache, or (b) two reads using different group names.
  • Locale-aware values. If your site is multilingual, plain Text fields store one string. Either define one field per locale (title_en, title_fr) — simple and predictable — or wrap the field with a translatable field package. Mixing the two approaches across the app gets messy fast.
  • Lockfile churn / abandonment risk. With zero dependents and a small maintainer surface, pin the version in composer.json and check the package's PHP/Laravel constraints before a framework upgrade. Keep a thin accessor class in front of it so swapping to a plain settings table implementation later is a one-file change rather than a hundred call-site edits.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle