Weave Code
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
Skills Skills
agenticmorf/fluxui-avatar
claude-code
laravel
avatar
file-upload
livewire
flux-ui
Install
php artisan boost:add-skill agenticmorf/fluxui-avatar

Save this content to: .claude/skills/skills-skills/SKILL.md

---
package: agenticmorf/fluxui-avatar
source_path: SKILLS.md
repo: https://github.com/AgenticMorf/fluxui-avatars
---

# SKILLS.md — Required Technical Context for AI Agents

This file documents the prerequisite skills and architectural context an AI agent needs to contribute to this repository effectively.

---

## 1. Livewire 4 Lifecycle & Key Differences from v3

| Topic | v3 | v4 (Required) |
|-------|-----|---------------|
| Component registration | `Livewire::component(...)` | Same, but v4 supports auto-discovery |
| Property attributes | `#[LivewireProperty]` | Remove annotation — public props are reactive by default |
| Validation | `protected $rules = []` | `#[Validate]` attribute **or** `protected function rules(): array` |
| File uploads | `WithFileUploads` trait | Same, but `TemporaryUploadedFile` is namespaced under `Livewire\Features\SupportFileUploads` |
| Dependency injection | Not supported in `mount()` args | `boot(MyService $service)` for DI; `mount()` for URL params |
| `wire:model.lazy` | Available | Use `wire:model.live` or `wire:model.blur` in v4 |

**Important for this package**: Always inject `AvatarStorageInterface` via `boot(AvatarStorageInterface $storage)` in the Livewire component, NOT via `mount()`.

---

## 2. Flux UI Component Structures

Flux UI provides Blade components under the `flux::` namespace. Key components used:

```blade
{{-- Avatar display --}}
<flux:avatar src="..." initials="JD" size="lg" shape="circle" />

{{-- File upload --}}
<flux:file-upload wire:model="photo" accept="image/*" />

{{-- Button --}}
<flux:button variant="danger" wire:click="removePhoto">Remove</flux:button>

{{-- Badge for status --}}
<flux:badge color="blue" size="sm">Uploading…</flux:badge>
```

### View Namespace Shadowing

Flux UI registers its views under the `flux` namespace. Laravel resolves namespaced views by searching through all registered paths for that namespace **in registration order**. By calling `$viewFactory->prependNamespace('flux', ...)` in our `ServiceProvider::boot()`, our version of `avatar.blade.php` is checked first.

**Critical:** The shadow view must **not** render `<flux:avatar>` internally — that resolves to the same prepended file and causes infinite recursion. Delegate with `@include('flux::avatar.index', ...)` (Flux’s real template under `stubs/resources/views/flux/avatar/index.blade.php`).

---

## 3. Laravel Service Provider Boot Order

```
Register phase (all providers)
  → ServiceProvider::register()  ← bind things in IoC here

Boot phase (all providers, in dependency order)
  → ServiceProvider::boot()      ← register views, routes, components here
```

The `FluxuiAvatarServiceProvider::boot()` must run **after** Flux UI's provider has registered its namespace. Using `prependNamespace` ensures our path is inserted at the front of the existing namespace paths array, regardless of provider registration order.

---

## 4. Spatie Media Library Patterns

When using `SpatieMediaLibraryAdapter`:

```php
// Model must implement HasMedia and use InteractsWithMedia
class User extends Authenticatable implements HasMedia
{
    use InteractsWithMedia;

public function registerMediaCollections(): void
    {
        $this->addMediaCollection('avatars')
             ->singleFile(); // ensures old avatar is replaced
    }
}
```

The `singleFile()` call on the collection registration in the **User model** (not in the adapter) ensures Spatie automatically removes old media when a new one is added to the same collection.

---

## 5. Laravel Service Container Binding

The `AvatarStorageInterface` is bound in `register()`:

```php
$this->app->bind(AvatarStorageInterface::class, function (): AvatarStorageInterface {
    return match (config('fluxui-avatar.driver')) {
        'spatie' => new SpatieMediaLibraryAdapter(...),
        default  => new LaravelDiskAdapter(...),
    };
});
```

Livewire resolves `boot()` method dependencies via the container automatically. No manual resolution required in the component.

---

## 6. PestPHP Conventions

```php
// Test file structure
test('it does something', function (): void {
    // Arrange
    // Act
    // Assert
});

// Arch tests
arch('no debugging functions')->expect(['dd', 'dump'])->not->toBeUsed();

// Livewire tests
Livewire::test(AvatarManager::class)
    ->set('photo', $file)
    ->assertHasErrors(['photo']);
```

Always use function-based Pest tests. Never use class-based PHPUnit test cases.

---

## 7. Package Discovery

This package uses Laravel's auto-discovery via `extra.laravel.providers` in `composer.json`. No manual registration is required in the host application's `config/app.php`.

package: agenticmorf/fluxui-avatar source_path: SKILLS.md repo: https://github.com/AgenticMorf/fluxui-avatars

SKILLS.md — Required Technical Context for AI Agents

This file documents the prerequisite skills and architectural context an AI agent needs to contribute to this repository effectively.


1. Livewire 4 Lifecycle & Key Differences from v3

Topic v3 v4 (Required)
Component registration Livewire::component(...) Same, but v4 supports auto-discovery
Property attributes #[LivewireProperty] Remove annotation — public props are reactive by default
Validation protected $rules = [] #[Validate] attribute or protected function rules(): array
File uploads WithFileUploads trait Same, but TemporaryUploadedFile is namespaced under Livewire\Features\SupportFileUploads
Dependency injection Not supported in mount() args boot(MyService $service) for DI; mount() for URL params
wire:model.lazy Available Use wire:model.live or wire:model.blur in v4

Important for this package: Always inject AvatarStorageInterface via boot(AvatarStorageInterface $storage) in the Livewire component, NOT via mount().


2. Flux UI Component Structures

Flux UI provides Blade components under the flux:: namespace. Key components used:

{{-- Avatar display --}}
<flux:avatar src="..." initials="JD" size="lg" shape="circle" />

{{-- File upload --}}
<flux:file-upload wire:model="photo" accept="image/*" />

{{-- Button --}}
<flux:button variant="danger" wire:click="removePhoto">Remove</flux:button>

{{-- Badge for status --}}
<flux:badge color="blue" size="sm">Uploading…</flux:badge>

View Namespace Shadowing

Flux UI registers its views under the flux namespace. Laravel resolves namespaced views by searching through all registered paths for that namespace in registration order. By calling $viewFactory->prependNamespace('flux', ...) in our ServiceProvider::boot(), our version of avatar.blade.php is checked first.

Critical: The shadow view must not render <flux:avatar> internally — that resolves to the same prepended file and causes infinite recursion. Delegate with @include('flux::avatar.index', ...) (Flux’s real template under stubs/resources/views/flux/avatar/index.blade.php).


3. Laravel Service Provider Boot Order

Register phase (all providers)
  → ServiceProvider::register()  ← bind things in IoC here

Boot phase (all providers, in dependency order)
  → ServiceProvider::boot()      ← register views, routes, components here

The FluxuiAvatarServiceProvider::boot() must run after Flux UI's provider has registered its namespace. Using prependNamespace ensures our path is inserted at the front of the existing namespace paths array, regardless of provider registration order.


4. Spatie Media Library Patterns

When using SpatieMediaLibraryAdapter:

// Model must implement HasMedia and use InteractsWithMedia
class User extends Authenticatable implements HasMedia
{
    use InteractsWithMedia;

public function registerMediaCollections(): void
    {
        $this->addMediaCollection('avatars')
             ->singleFile(); // ensures old avatar is replaced
    }
}

The singleFile() call on the collection registration in the User model (not in the adapter) ensures Spatie automatically removes old media when a new one is added to the same collection.


5. Laravel Service Container Binding

The AvatarStorageInterface is bound in register():

$this->app->bind(AvatarStorageInterface::class, function (): AvatarStorageInterface {
    return match (config('fluxui-avatar.driver')) {
        'spatie' => new SpatieMediaLibraryAdapter(...),
        default  => new LaravelDiskAdapter(...),
    };
});

Livewire resolves boot() method dependencies via the container automatically. No manual resolution required in the component.


6. PestPHP Conventions

// Test file structure
test('it does something', function (): void {
    // Arrange
    // Act
    // Assert
});

// Arch tests
arch('no debugging functions')->expect(['dd', 'dump'])->not->toBeUsed();

// Livewire tests
Livewire::test(AvatarManager::class)
    ->set('photo', $file)
    ->assertHasErrors(['photo']);

Always use function-based Pest tests. Never use class-based PHPUnit test cases.


7. Package Discovery

This package uses Laravel's auto-discovery via extra.laravel.providers in composer.json. No manual registration is required in the host application's config/app.php.

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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui