Claude Code Plugins

Community-maintained marketplace

Feedback

Create and modify Laravel Nova 5.x resources with PCR Card patterns (tab panels, Badge fields with closures, Select fields with constants). Triggers include "nova resource", "nova badge", "nova tabs", "nova field".

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name Nova Resource Builder
description Create and modify Laravel Nova 5.x resources with PCR Card patterns (tab panels, Badge fields with closures, Select fields with constants). Triggers include "nova resource", "nova badge", "nova tabs", "nova field".
allowed-tools Read, Write, Edit, Grep, Glob, Bash

Nova Resource Builder

Build Nova 5.x resources following PCR Card's established patterns.

When to Use

  • Creating new Nova resources
  • Adding fields to existing resources
  • Implementing tab-based layouts
  • Configuring Badge/Select fields with constants
  • Setting up Nova search

Quick Commands

# Create resource
php artisan nova:resource ResourceName

# Validate Nova search configs
./scripts/dev.sh validate:nova-search

# Clear Nova cache
./scripts/dev.sh nova:publish

PCR Card Nova Patterns

1. Badge Fields (Closure Pattern)

CRITICAL: Badge fields use closures + hardcoded string maps, NOT constants.

use Laravel\Nova\Fields\Badge;

Badge::make('Status', function () {
    // Closure returns calculated value
    return $this->is_active ? 'active' : 'inactive';
})
->map([
    'active' => 'success',      // Hardcoded strings
    'inactive' => 'danger',
    'pending' => 'warning',
])
->label(function ($value) {
    return match ($value) {
        'active' => 'Active',
        'inactive' => 'Inactive',
        'pending' => 'Pending',
    };
});

2. Select Fields (Constants Pattern)

Use constant class options() method:

use App\Constants\PromoCodeType;
use Laravel\Nova\Fields\Select;

Select::make('Type')
    ->options(PromoCodeType::options())  // Returns ['fixed' => 'Fixed Amount', ...]
    ->displayUsingLabels()
    ->sortable()
    ->rules('required');

3. Tab-Based Layouts

Use Tab::group() with Heading::make() for sections:

use Laravel\Nova\Tabs\Tab;
use Laravel\Nova\Fields\Heading;

public function fields(NovaRequest $request): array
{
    return [
        ID::make()->sortable(),

        Tab::group('Resource Information', [
            Tab::make('Overview', [
                Heading::make('Basic Details'),
                Text::make('Name')->required(),

                Heading::make('Settings'),
                Boolean::make('Is Active'),
            ]),

            Tab::make('Details', [
                Heading::make('Additional Information'),
                Textarea::make('Description'),
            ]),
        ]),
    ];
}

Rules:

  • Use Tab::group('Title', [...]) for panel with heading
  • Use Heading::make('Name') for section dividers
  • NO Panel::make() inside tabs
  • HasMany relationships work in tabs

4. Search Configuration

public static $search = [
    'id',
    'name',
    'user.email',           // Relationship search
    'submission.submission_number',
];

// REQUIRED: Eager load relationships
public static $with = ['user', 'submission'];

Validate before commit:

./scripts/dev.sh validate:nova-search

Constants Reference

All constants follow this pattern:

class ConstantName
{
    public const PREFIX_VALUE = 'value';

    public static function all(): array;        // All values
    public static function label(string $value): string;  // Human label
    public static function options(): array;    // For Select fields
    public static function isValid(string $value): bool;  // Validation
}

Available Constants (18 total):

  • App\Constants\PromoCodeType - TYPE_FIXED, TYPE_PERCENTAGE
  • App\Constants\ManualPaymentMethod - METHOD_CASH, METHOD_CHECK, etc.
  • App\Constants\ManualPaymentStatus - STATUS_PENDING, STATUS_VERIFIED, etc.
  • App\Constants\SubmissionState - DRAFT, SUBMITTED, RECEIVED, etc. (stores ::class refs)
  • App\Constants\CardState - RECEIVED, ASSESSMENT, IN_PROGRESS, etc.
  • See app/Constants/ for all 18 classes

Common Pitfalls

❌ WRONG: Using NovaBadgeType constants in Badge fields

Badge::make('Status')
    ->map(fn($value) => NovaBadgeType::SUCCESS);  // ❌ Don't do this

✅ CORRECT: Use hardcoded strings

Badge::make('Status', function () {
    return $this->state;
})
->map([
    'active' => 'success',    // ✅ Hardcoded strings
    'inactive' => 'danger',
]);

❌ WRONG: Manual options array for Select

Select::make('Type')
    ->options([
        'fixed' => 'Fixed Amount',
        'percentage' => 'Percentage',
    ]);

✅ CORRECT: Use constant options() method

Select::make('Type')
    ->options(PromoCodeType::options());  // ✅ Centralized

Documentation Links

  • Nova Admin Guide: docs/development/NOVA-ADMIN-GUIDE.md
  • Nova Search Guide: docs/development/NOVA-SEARCH-GUIDE.md
  • Constants Pattern: CLAUDE.md "Constants Pattern & Nova Best Practices"
  • Laravel Nova Docs: https://nova.laravel.com/docs/5.0