| name | vendra-user-profile-development |
| description | Create, modify, review, or test the Vendra User Profile package in packages/vendra-user-profile. Use for UserProfile, dynamic User relations registered by the service provider, TenantTableRegistry wiring, profile traits, migrations, factories, policies, Filament resources, configuration, translations, permission integration, package wiring, and tests. |
Vendra User Profile
Workflow
Translatable Persistence
- Making a persisted model field translatable is an explicit domain choice unless this package already requires it.
- Every field listed in a model's
$translatable array must definitely use a JSON database column. Keep its model traits/casts, factories, validation, Filament locale UI, API serialization, and tests translation-aware.
- A field not listed in
$translatable must use the appropriate scalar database type and must not use Spatie Translatable, translatable slug traits, locale switchers, translated callbacks, or translation-shaped array data.
Always use this skill together with laravel-best-practices for Laravel PHP and pest-testing when tests are added or changed. Use tailwindcss-development only when editing Blade or Tailwind UI.
Before code changes, use Laravel Boost application-info and search-docs for the relevant packages. Prefer Boost database and browser tools over ad hoc debugging.
Module Boundary
Treat packages/vendra-user-profile as the source of user-profile domain behavior and Filament admin UI.
- Use namespace
Misaf\VendraUserProfile.
- Keep domain models, factories, seeders, policies, observers, console commands, Filament classes, config, migrations, translations, and tests inside this module.
- Do not place user-profile domain code in the host app unless the host app is only integrating the module.
- Keep cross-module dependencies explicit in
composer.json; do not introduce a dependency without approval.
Domain Model Standards
Follow the existing UserProfile patterns for new user-profile entities.
- Use
declare(strict_types=1), final classes, typed method signatures, and PHPDoc generics for relationships.
- Follow Laravel comment style: document with PHPDoc (array shapes, generics,
@see) and reserve inline comments for genuinely complex logic. Match the surrounding file's density and do not add comments that restate the code.
- Prefer only the Laravel attributes already used by the affected sibling model; do not add model attributes merely because another package uses them.
- Keep the module tenant-agnostic: derive tenant awareness purely from the bound
TenantResolver in misaf/vendra-support (TenantAwareness, BelongsToTenant, TenantSchema, RequiresCurrentTenant). The module must build and run whether or not a tenant provider is installed, so never reference a concrete provider such as Misaf\VendraTenant anywhere — models, migrations, factories, seeders, or fixtures. There is no tenant_aware config toggle.
- Hide
tenant_id and keep tenant behavior centralized in the support layer; do not duplicate tenant scoping or tenant_id assignment in models, Filament resources, factories, or seeders. BelongsToTenant assigns tenant_id on creating from the current tenant.
- Reuse only the traits and conventions present on the affected sibling model; do not infer translations, media, slugs, sorting, or soft deletes from another package.
- Registers
profiles / userProfiles on the User model via User::resolveRelationUsing(...) in the service provider; do not hard-code the relation on the User class.
- Own only the generic
UserProfileRelationManagers extension registry. Address, Phone, Document, and Verification are optional packages that depend on User Profile; User Profile must not import or require them.
Filament Standards
Keep every resource that declares a $cluster, including its complete supporting tree, under src/Filament/Clusters/Resources/ with the matching Misaf\VendraUserProfile\Filament\Clusters\Resources namespace and plugin discovery path. Resources without a cluster belong under src/Filament/Resources/.
- Register module UI through the module
Plugin and ServiceProvider; do not manually wire resources in unrelated panel providers.
- Resolve resource relation managers from
UserProfileRelationManagers so independently installed providers can contribute UI without reverse dependencies.
- Keep resource classes thin. Delegate form schemas to
Schemas/*Form.php and table configuration to Tables/*Table.php.
- Use Filament v5 namespaces: form fields from
Filament\Forms\Components, layout from Filament\Schemas\Components, table columns from Filament\Tables\Columns, filters from Filament\Tables\Filters, actions from Filament\Actions, and icons from Filament\Support\Icons\Heroicon.
- Use this module's translation keys (
vendra-user-profile::attributes, vendra-user-profile::navigation) for labels, breadcrumbs, and navigation.
- Keep
UserProfileResource ungrouped in CustomersCluster and immediately after Users through NavigationPriority::UserProfiles.
- Provide separate singular and plural resource labels in
en, de, and fa: model labels use the singular key, while navigation and plural model labels use the plural key. Keep navigation labels at 24 characters or fewer.
- Prevent N+1 issues in tables and relation managers with eager loading,
withCount, or computed state based on loaded relationships.
- Use public media visibility only when public access is actually required.
Permissions And Navigation
Use policy enums and policies as the permission source.
- Add enum cases for every resource action the panel exposes.
- Keep policy method names aligned with Filament actions:
viewAny, view, create, update, delete, deleteAny, restore, restoreAny, forceDelete, forceDeleteAny, replicate, and reorder as applicable.
- Update
PermissionPolicySeeder when new permissions are introduced.
- Keep navigation labels and groups configurable through the module
Plugin and config/vendra-user-profile.php. Do not add a tenant_aware config value; tenant awareness derives from the bound TenantResolver.
- Keep feature configuration flat with
features_enabled, features_discover, and module_enabled; do not introduce nested features.* keys. Default an installed module to enabled so User Profiles appears beside Users, but preserve explicit environment overrides. Check access through Features\ModuleEnabled::class, whose Pennant before() hook applies the global switches before persisted tenant values.
Data And Localization
Migrations, factories, seeders, and translation files are part of the contract.
- Use package migrations in
database/migrations, with stubs only when the install flow expects publishing.
- Register
user_profiles with TenantTableRegistry in UserProfileServiceProvider whenever its migration uses TenantSchema::addTenantColumn(). If the table was migrated before tenancy was enabled, use php artisan vendra-tenant:enable {tenant} to add and backfill tenant ownership explicitly.
- Use factories under
database/factories and seeders under database/seeders. Keep them tenant-safe: import no concrete tenant provider and set no tenant_id directly; let BelongsToTenant assign it from the current tenant so they work with tenancy on or off.
- Keep demo fixtures deterministic and tenant-safe.
- Update all supported locales together and keep translation keys sorted.
- Preserve translation key parity tests when adding labels or attributes.
Testing And Verification
Prefer focused Pest tests in the module.
- Keep tests purposeful and prevent unnecessary ones: cover behavior, contracts, and edge cases — not framework internals or trivially typed code. Do not duplicate coverage a focused test already proves, and do not add throwaway verification scripts (or
tinker) when a test fits.
- Add or update unit tests for model contracts, policy permission coverage, resolver-derived tenant awareness, navigation/config behavior, and translation parity.
- Keep Pest architecture tests in
tests/ArchTest.php: the php, security, and laravel presets, plus an expectation that the module stays tenant-agnostic, e.g. arch()->expect('Misaf\VendraUserProfile')->not->toUse('Misaf\VendraTenant').
- Add feature or Livewire tests when changing Filament behavior with meaningful user-visible effects.
- Run module checks from the package when possible:
composer --working-dir=packages/vendra-user-profile test and composer --working-dir=packages/vendra-user-profile analyse.
- If PHP files changed, run Pint for the touched code:
vendor/bin/pint --dirty --format agent from the host app, or the module formatter if working only inside the package.