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

Nova4 Seo Description Laravel Package

murdercode/nova4-seo-description

A Laravel Nova 4 field for adding and editing SEO meta descriptions directly in your resources, helping you keep search snippets concise and manage SEO content without leaving the admin panel.

View on GitHub
Deep Wiki
Context7

Getting Started

This package contributes one thing: a Nova 4 field type that renders an SEO-meta-description input with client-side affordances (character counter and over-limit warning; some builds also show a Google-style SERP preview). It is a field, not a full SEO suite — it gives you one well-behaved text input, nothing more.

Minimal path:

  1. Require it in a Nova 4 project. Nova 5 changed the field API and this package has no release after April 2022, so treat it as Nova-4-only until you've tested otherwise.
    composer require murdercode/nova4-seo-description
    
  2. Confirm the class name before writing imports. With a single release from 2022, don't guess — open vendor/murdercode/nova4-seo-description/src/ (or the README) and check the field class and namespace (expected to be under Murdercode\Nova4SeoDescription).
  3. Add the field to a resource:
    // use Murdercode\Nova4SeoDescription\SeoDescription; // verify class name
    
    public function fields(NovaRequest $request)
    {
        return [
            Text::make('Title', 'title'),
            SeoDescription::make('Meta Description', 'meta_description')
                ->rules('nullable', 'string', 'max:160'),
        ];
    }
    
  4. Make sure the column exists and is sized right: $table->string('meta_description', 160)->nullable(); (or text() if you allow long descriptions and clip for display only).
  5. Publish assets if the counter doesn't render: php artisan nova:publish, then hard-refresh. If the package ships compiled JS under dist/, this is the usual fix.

Where to look first: README → the field's src/*.php (for fluent methods) → resources/js/ (for how the counter and any preview are computed). First use case: drop it beside existing title/slug fields on any resource with a public URL (pages, posts, products) so editors can see the length before saving.

Implementation Patterns

Baseline field + validation parity. The counter is cosmetic; your validation rules are the real guardrail. Keep them in sync:

SeoDescription::make('Meta Description')
    ->rules('nullable', 'string', 'max:160')
    ->help('Aim for 120–160 characters.');

Pair with a title field for context. SEO descriptions are written against the title/topic, so keep them adjacent and use ->stacked()/->fullWidth() if the layout feels cramped.

Reuse across resources via a trait or base resource. Since this is one field, wrap the "SEO block" (title, description, slug, OG image) in a trait or a fieldsForSeo() method so you don't reconfigure limits in five resources:

protected function seoFields(): array
{
    return [
        SeoDescription::make('Meta Description', 'meta_description')
            ->rules('nullable', 'string', 'max:160'),
    ];
}

Then merge it wherever the model has an SEO block.

Store on the model or an SEO relation. If you use spatie/laravel-seo or a dedicated seo_meta table already, point this field at the existing attribute/relation column instead of introducing a second description column — otherwise you end up with two "descriptions" that drift.

Server-side trimming vs. hard rejection. Decide one policy and encode it in rules. max:160 rejects; ->rules('string') plus a FormRequest/saving() mutator that Str::limit(..., 160) accepts and trims. Pick one so editors aren't surprised by a red error after typing 170 chars.

Fluent extension (if the field supports it). Many Nova field packages expose ->maxLength() or ->recommendedLength(). If the README mentions one, prefer it over hardcoding max:160 in rules so the counter and validator share a single source of truth — and set the column length to match.

Gotchas and Tips

  • Version/compatibility is the headline risk. One star, zero dependents, last release 2022. Verify it loads under your Nova version before planning on it; budget time for a fork or a hand-rolled custom field if it breaks. Pin the exact version in composer.json.
  • Client-side counter ≠ validation. If the JS lets you type past the limit, the field will still submit it. Always add the server rule; never rely on the counter alone to enforce length.
  • Multibyte counting. JS string.length counts UTF-16 units and emoji as 2; Laravel's max:160 counts characters via mb_strlen. Your counter and validator can disagree on accented/emoji-heavy copy. If that matters, trim server-side and let the counter be advisory.
  • Column length vs. rule. A varchar(160) with max:160 is fine, but a varchar(255) with a max:160 rule means the DB silently permits what Nova rejects. Keep DB, rule, and counter aligned.
  • Asset publishing. Blank input / missing counter almost always means assets weren't published or the browser cached the old JS. Run php artisan nova:publish, npm run prod on your app if you've customized, and hard-refresh.
  • searchable()/sortable() only make sense if the underlying column is indexed; otherwise leave them off rather than exposing a slow sort to editors.
  • Don't assume "SEO" features. This is a description field. It does not generate meta tags, sitemaps, or canonical URLs — pair it with an actual SEO package and read it out in your Blade layout.
  • Extension points, when the base field is too thin: subclass the field to add your own recommendedLength, or write a Nova custom field (~one Vue component + one PHP class) — for a single counter, that's often less work than debugging an unmaintained dependency. Fork the repo if you need it maintained; nothing upstream will fix it for you.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource