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

ferdiunal/nova-settings

A Laravel Nova package for managing application settings from the Nova admin panel. It provides a settings UI and storage for editable configuration values, making runtime settings easy to view and update without code changes.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Confirm the baseline. You need Laravel + Laravel Nova already installed — this package is a Nova screen over Spatie's settings layer, so it is worth zero without Nova. Check the package's composer.json constraints against your Nova major version before you install; Nova majors move fast and the package is at v1.0.x with a thin maintainer bench.

    composer require ferdiunal/nova-settings
    
  2. Publish config and migration separately. Publish by tag so config changes are reviewable in a PR without dragging migrations along (and vice versa):

    php artisan vendor:publish --provider="Ferdiunal\NovaSettings\NovaSettingsServiceProvider" --tag=nova-settings-config
    php artisan vendor:publish --provider="Ferdiunal\NovaSettings\NovaSettingsServiceProvider" --tag=nova-settings-migrations
    php artisan migrate
    

    Read the published migration before running it. If your app already owns a settings table (another package, or your own legacy one), edit the migration now — renaming afterwards means a rename migration plus data copy.

  3. Register the settings surface in Nova. Add the package's tool/page (or field) in app/Providers/NovaServiceProvider.php. Start with three scalar fields — a site name (text), a support email (text), and one boolean feature flag — so you can prove the full round trip: render → edit → save → read.

  4. Prove the read path. Read the value back in a Blade view or a tinker session. Confirm the accessor against the published config and README rather than assuming — it is typically a settings('key') style helper or a Spatie settings class accessor. Do this before wiring it into business logic; a typo'd key silently returns your default and looks like a save bug.

Where to look first, in order: the published config (key registry, groups, cache defaults) → the migration (table shape, whether it's Spatie's group/name/payload layout) → the Nova registration (what actually renders). Those three answer 90% of day-one questions.

Implementation Patterns

  • Treat config as the key registry. Declare every key, its group, type, and default in one config file. Then settings('mail.from') calls scattered across the codebase are readable against a manifest, and you can grep for orphaned keys during cleanup. This is the single highest-leverage habit with this package.

  • Always read with a default. Fresh environments, CI, and new tenants have no rows. Pass an explicit default at every call site (or rely on config-declared defaults) so a missing row degrades gracefully instead of throwing inside a request.

  • Cache reads; invalidate on write. Settings are read on nearly every request and written almost never — the textbook cache case. Verify whether the package caches internally and busts on save. If it does not, wrap reads:

    $from = Cache::rememberForever('settings.mail.from', fn () => settings('mail.from', config('mail.from.address')));
    

    and invalidate in the field's save path, an observer, or a model event. Unbounded per-request settings queries are the real performance trap here and they will not show up in dev.

  • Group by domain, not by one giant screen. Mail, branding, integrations, feature flags, pricing — one Nova group each. Navigable editing UI, and permissions are easier to reason about per group.

  • Read at the boundary, inject inward. Resolve settings in service providers (AppServiceProvider::boot() for mail/branding config overrides), feature-flag checks, or a thin Settings repository you own. Do not call the accessor deep inside Eloquent models — it makes tests slow and hides the coupling. Keeping reads behind your own service also makes swapping to spatie/laravel-settings, a config service, or a bespoke table a contained change later.

  • Custom field types. If a stakeholder needs a bespoke input (dependent dropdown, JSON blob with validation, prefilled value), subclass the package's Nova field and override resolve/fill rather than building a parallel storage layer. v1.0.12 exposing the current attribute value to the field is exactly the affordance that makes this practical — see the gotcha below about it being an internal API.

  • Testing. Use RefreshDatabase, seed only the settings rows the test depends on (or write them through the package's API), and flush the settings cache in setUp. Cached settings leaking between tests is the #1 source of "passes locally, fails in CI" in this setup.

  • Treat production-edited values as data, not code. They do not ship with a deploy. For anything that must be identical across environments (a flag that gates behavior), seed from config and treat the Nova editor as an override.

Gotchas and Tips

  • v1.0.12 is additive and internal. "Added current attribute value for internal use by the field" (PR #7, @joserick's first contribution) surfaces the field's current attribute during render/edit. No config or schema changes, no migration. Pin ^1.0 and take it on a patch bump — the only risk surface is custom field subclasses.

  • "Internal use" means internal. If you build a custom field on top of that attribute plumbing, expect it to move in a minor release. Depend on documented field methods where you can, and write a test that exercises your subclass so a future patch fails loudly instead of silently rendering stale values.

  • Cache staleness after out-of-band edits. Change a row in tinker, a seeder, or a data migration, and a cached value keeps serving the old data. Either go through the package's write path or explicitly flush after the change. This is the most common false "the package is broken" report.

  • Debug reads in this order: row exists in the table → cache key is fresh → the accessor's key string matches the config key exactly (typos silently return the default) → the Nova field actually saved (check updated_at). Skipping to step 3 costs people hours.

  • vendor:publish without a tag can overwrite customized config. Publish once, commit the result, and re-publish only when deliberately merging upstream — diff before accepting.

  • Secrets do not belong here. Integration API keys are tempting because the editor is convenient, but this is your application database with no rotation, KMS backing, or audited access beyond Nova's own gates. Store secrets in a vault and reference them from a settings field at most.

  • Multi-tenant scoping is yours to verify. Check what tenant isolation, if any, exists before designing around it. If it is absent, model tenant-aware settings as your own Eloquent model and reserve this package for genuinely global configuration.

  • Extension points beat forking. The package is small enough to read end-to-end in an afternoon. Before working around a limitation, skim the service provider and the field class — validation, grouping, and custom accessors are usually achievable via subclass or container binding, which keeps you on the upgrade path.

  • Assume replacement in 12–18 months. v1.0.x, one-to-two maintainers, tiny contributor base. Pin the version, watch the changelog, keep settings access behind your own boundary, and confirm you have a migration/export path for the settings data before you depend on it heavily.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
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