resources/boost/skills/custom-fields-development/SKILL.md
Adds dynamic custom fields to Eloquent models without migrations using Filament integration. Use when adding the UsesCustomFields trait to models, integrating custom fields in Filament forms/tables/infolists, configuring field types, working with field validation, or managing feature flags for conditional visibility, encryption, and multi-tenancy.
npx skillsauth add relaticle/custom-fields custom-fields-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use when:
use Relaticle\CustomFields\Models\Concerns\UsesCustomFields;
use Relaticle\CustomFields\Models\Contracts\HasCustomFields;
class Contact extends Model implements HasCustomFields
{
use UsesCustomFields;
}
use Relaticle\CustomFields\CustomFieldsPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
CustomFieldsPlugin::make()
->authorize(fn () => auth()->user()->isAdmin()),
]);
}
php artisan vendor:publish --tag=custom-fields-migrations
php artisan migrate
Use the CustomFields facade to generate form/table/infolist components.
use Relaticle\CustomFields\Facades\CustomFields;
public static function form(Form $form): Form
{
return $form->schema([
TextInput::make('name')->required(),
// Add custom fields after regular fields
CustomFields::form()->forSchema($form)->build(),
]);
}
Builder methods:
forSchema(Schema $schema) - Auto-detect model from form/infolistforModel(Model|string $model) - Explicit model bindingonly(['code1', 'code2']) - Include only specific fieldsexcept(['code1']) - Exclude specific fieldswithoutSections() - Flatten fields without section groupinguse Relaticle\CustomFields\Facades\CustomFields;
public static function table(Table $table): Table
{
$customFields = CustomFields::table()->forModel(Contact::class);
return $table
->columns([
TextColumn::make('name'),
...$customFields->columns(),
])
->filters([
...$customFields->filters(),
]);
}
use Relaticle\CustomFields\Facades\CustomFields;
public static function infolist(Infolist $infolist): Infolist
{
return $infolist->schema([
TextEntry::make('name'),
CustomFields::infolist()->forSchema($infolist)->build(),
]);
}
use Relaticle\CustomFields\Facades\CustomFields;
// In Importer class
public function getColumns(): array
{
return [
ImportColumn::make('name'),
...CustomFields::importer()->forModel(Contact::class)->columns()->toArray(),
];
}
// In Exporter class
public function getColumns(): array
{
return [
ExportColumn::make('name'),
...CustomFields::exporter()->forModel(Contact::class)->columns()->toArray(),
];
}
| Type | Key | Data Storage |
|------|-----|--------------|
| Text | text | text_value |
| Email | email | json_value |
| Phone | phone | json_value |
| Textarea | textarea | text_value |
| Rich Editor | rich-editor | text_value |
| Markdown | markdown-editor | text_value |
| Link | link | json_value |
| Number | number | integer_value |
| Currency | currency | float_value |
| Date | date | date_value |
| DateTime | date-time | datetime_value |
| Select | select | string_value |
| Multi-Select | multi-select | json_value |
| Checkbox | checkbox | boolean_value |
| Checkbox List | checkbox-list | json_value |
| Radio | radio | string_value |
| Toggle | toggle | boolean_value |
| Toggle Buttons | toggle-buttons | string_value |
| Tags Input | tags-input | json_value |
| Color Picker | color-picker | text_value |
| File Upload | file-upload | string_value |
| Record Select | record | json_value |
Convention: Use kebab-case for all field type keys.
For custom field types, use a project prefix to avoid conflicts:
| Scenario | Pattern | Example |
|----------|---------|---------|
| New custom type | {project}-{name} | acme-star-rating |
| Extended built-in | {project}-{original} | acme-rich-editor |
| Replace built-in | Same key | rich-editor |
Why prefix?
Configure in config/custom-fields.php using FeatureConfigurator:
use Relaticle\CustomFields\Enums\CustomFieldsFeature;
use Relaticle\CustomFields\FeatureSystem\FeatureConfigurator;
'features' => FeatureConfigurator::configure()
->enable(
CustomFieldsFeature::FIELD_CONDITIONAL_VISIBILITY,
CustomFieldsFeature::FIELD_ENCRYPTION,
CustomFieldsFeature::FIELD_OPTION_COLORS,
CustomFieldsFeature::UI_TABLE_COLUMNS,
CustomFieldsFeature::UI_TABLE_FILTERS,
CustomFieldsFeature::SYSTEM_SECTIONS,
)
->disable(
CustomFieldsFeature::SYSTEM_MULTI_TENANCY,
),
Feature Categories:
| Feature | Purpose |
|---------|---------|
| FIELD_CONDITIONAL_VISIBILITY | Show/hide fields based on other field values |
| FIELD_ENCRYPTION | Encrypt sensitive field values |
| FIELD_OPTION_COLORS | Color badges for select/checkbox options |
| FIELD_VALIDATION_RULES | Enable validation rule configuration |
| UI_TABLE_COLUMNS | Show custom fields as table columns |
| UI_TABLE_FILTERS | Enable filtering by custom fields |
| UI_TOGGLEABLE_COLUMNS | Allow users to toggle column visibility |
| UI_FIELD_WIDTH_CONTROL | Control field width in forms |
| SYSTEM_MANAGEMENT_INTERFACE | Admin page for managing fields |
| SYSTEM_SECTIONS | Organize fields into sections |
| SYSTEM_MULTI_TENANCY | Tenant isolation for fields |
use Relaticle\CustomFields\EntitySystem\EntityConfigurator;
'entity_configuration' => EntityConfigurator::configure()
->discover(app_path('Models'))
->exclude(['User', 'Team'])
->cache(enabled: true, ttl: 3600),
use Relaticle\CustomFields\FieldTypeSystem\FieldTypeConfigurator;
'field_type_configuration' => FieldTypeConfigurator::configure()
->enabled(['text', 'email', 'select', 'number'])
->disabled(['file-upload'])
->discover(true)
->cache(enabled: true),
For multi-tenancy outside Filament panels:
use Relaticle\CustomFields\CustomFields;
// In AppServiceProvider::boot()
CustomFields::resolveTenantUsing(fn () => auth()->user()?->team_id);
// Get all custom fields for a model
$fields = $contact->customFields()->get();
// Get a specific field value
$value = $contact->getCustomFieldValue($customField);
// Save a field value
$contact->saveCustomFieldValue($customField, 'new value');
// Save multiple field values
$contact->saveCustomFields([
'industry' => 'Technology',
'company_size' => 'Enterprise',
]);
Four tables are created:
custom_field_sections - Optional grouping of fieldscustom_fields - Field definitions (name, code, type, validation)custom_field_options - Choice options for select/checkbox fieldscustom_field_values - Polymorphic storage of field valuesValues are stored in type-specific columns: string_value, text_value, integer_value, float_value, boolean_value, date_value, datetime_value, json_value.
Override default models for custom behavior:
use Relaticle\CustomFields\CustomFields;
// In AppServiceProvider::boot()
CustomFields::useCustomFieldModel(MyCustomField::class);
CustomFields::useValueModel(MyCustomFieldValue::class);
CustomFields::useOptionModel(MyCustomFieldOption::class);
CustomFields::useSectionModel(MyCustomFieldSection::class);
use Relaticle\CustomFields\CustomFieldsPlugin;
CustomFieldsPlugin::make()
->registerFieldTypes([
MyCustomFieldType::class,
])
Custom field types must extend Relaticle\CustomFields\FieldTypeSystem\BaseFieldType.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.