lc:generate-table
Generator tool that creates standardized data table components following your project's specific Livewire and Blade conventions.
Install
mkdir -p .claude/skills/lc-generate-table && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/19560" && unzip -o skill.zip -d .claude/skills/lc-generate-table && rm skill.zipInstalls to .claude/skills/lc-generate-table
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Generate a table component with filters, sorting, infinite scroll using the project's TableComponent base.Key capabilities
- →Generate Volt table components
- →Implement server-side filtering and sorting
- →Configure infinite scroll with x-intersect
- →Integrate row action dropdowns
- →Apply dark mode styling to UI elements
How it works
The skill inspects the project's existing TableComponent and model structure to generate a single-file Volt component that includes query logic, filtering, and UI templates.
Inputs & outputs
When to use lc:generate-table
- →Create a new table view for the User model
- →Generate an invoice list component with server-side sorting
- →Build a filterable data table for property listings
- →Standardize existing UI components using project patterns
About this skill
Subcommands
| Subcommand | Description |
|---|---|
<ModelName> | Generate a table Volt component for the given model (e.g., Property, Client, User, Invoice) |
Overview
This is a generator skill. It creates a complete table Volt component with filtering, sorting, infinite scroll, and row actions, following the project's established TableComponent pattern and UI conventions.
Instructions
Step 1: Understand the project's table patterns
Before generating, read existing table implementations to match conventions exactly:
-
Read the base
TableComponentclass:- Search for
class TableComponentusing Grep - Understand: base properties, methods (
loadMore,loadInitial,sortBy), traits used
- Search for
-
Read 1-2 existing table components for reference:
- Use Glob:
resources/views/livewire/**/*.blade.php - Look for components that extend
TableComponent - Note the exact structure, column definitions, filter setup, and action dropdowns
- Use Glob:
-
Read the table-related Blade components:
resources/views/components/tables/table.blade.php(or search forx-tables.table)resources/views/components/tables/dropdown.blade.php(row action dropdown)resources/views/components/filters.blade.php(or search forx-filters)
Step 2: Parse the argument and determine paths
Convert the ModelName to file paths:
Property->resources/views/livewire/properties/index.blade.phpClient->resources/views/livewire/clients/index.blade.phpInvoice->resources/views/livewire/invoices/index.blade.php
Pluralize the model name for the directory. Use index.blade.php as the filename.
Step 3: Inspect the model
Read the model file to understand:
- Table name and fillable fields
- Available relationships (for eager loading)
- Scopes that could be useful for filtering
- Casts (dates, enums, booleans) that affect display
- Soft deletes (if present, may need trash filter)
app/Models/ModelName.php
Step 4: Ask the user (if needed)
If the model has many fields, ask which columns to display in the table. If the context makes it clear, infer sensible defaults:
- Show 4-7 columns maximum
- Prioritize: name/title, status, key relationships, dates
- Always include a date column (created_at or relevant date)
Step 5: Generate the Volt component
Create the file using Write tool.
Template structure:
<?php
use App\Models\ModelName;
use App\Http\Controllers\TableComponent;
use Livewire\Volt\Component;
new class extends TableComponent {
public string $search = '';
public string $sortField = 'created_at';
public string $sortDirection = 'desc';
public string $statusFilter = '';
protected function query()
{
$query = ModelName::query()
->with(['relationship1', 'relationship2']);
if ($this->search) {
$query->where(function ($q) {
$q->where('name', 'like', '%' . $this->search . '%')
->orWhere('email', 'like', '%' . $this->search . '%');
});
}
if ($this->statusFilter) {
$query->where('status', $this->statusFilter);
}
return $query->orderBy($this->sortField, $this->sortDirection);
}
}; ?>
<div>
<x-filters>
<x-filters.search wire:model.live.debounce.300ms="search" />
<x-filters.select wire:model.live="statusFilter">
<option value="">@text('all_statuses', 'All Statuses')</option>
<option value="active">@text('active', 'Active')</option>
<option value="inactive">@text('inactive', 'Inactive')</option>
</x-filters.select>
</x-filters>
<x-tables.table
:columns="[
text('name', 'Name'),
text('email', 'Email'),
text('status', 'Status'),
text('created_at', 'Created'),
]"
:sortField="$sortField"
:sortDirection="$sortDirection"
:sortableColumns="['name', 'email', 'status', 'created_at']"
>
@forelse($this->items as $item)
<tr wire:key="model-{{ $item->id }}">
<td class="px-4 py-3 text-sm text-gray-900 dark:text-white">
{{ $item->name }}
</td>
<td class="px-4 py-3 text-sm text-gray-500 dark:text-gray-400">
{{ $item->email }}
</td>
<td class="px-4 py-3 text-sm">
<span class="px-2 py-1 text-xs font-medium rounded-full
{{ $item->status === 'active'
? 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'
: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300' }}">
{{ $item->status }}
</span>
</td>
<td class="px-4 py-3 text-sm text-gray-500 dark:text-gray-400">
{{ $item->created_at->format('d/m/Y') }}
</td>
<td class="px-4 py-3 text-sm text-right">
<x-tables.dropdown>
<x-tables.dropdown-item
href="{{ route('models.show', $item) }}"
wire:navigate
>
@text('view', 'View')
</x-tables.dropdown-item>
<x-tables.dropdown-item
@click="$dispatch('open-edit-model', { id: {{ $item->id }} })"
>
@text('edit', 'Edit')
</x-tables.dropdown-item>
<x-tables.dropdown-item
@click="$dispatch('confirm-delete-model', { id: {{ $item->id }} })"
class="text-red-600 dark:text-red-400"
>
@text('delete', 'Delete')
</x-tables.dropdown-item>
</x-tables.dropdown>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
@text('no_records_found', 'No records found')
</td>
</tr>
@endforelse
</x-tables.table>
<div x-intersect="$wire.loadMore()">
</div>
</div>
Step 6: Key conventions to follow
-
NEVER include "Actions" in the columns array - The actions column is automatically handled by
x-tables.dropdown. Only list data columns in the:columnsarray. -
ALWAYS use
wire:keyon each<tr>- Use a unique key likemodel-{{ $item->id }}to prevent DOM diffing bugs. -
Use
@text()for all user-visible text - Column headers, status labels, filter labels, empty state messages. Defaults must be English. -
Infinite scroll with
x-intersect- Place<div x-intersect="$wire.loadMore()">after the table for automatic loading. -
Filters use
wire:model.live.debounce.300msfor search andwire:model.livefor selects. -
Eager load relationships - Always use
->with([...])in the query to avoid N+1 problems. -
Dark mode support - Every visual element must have both light and dark variants.
-
Volt single-file pattern - PHP at top, blade below, never separate class files.
-
Model imports - Use
use App\Models\ModelName;at the top. -
Sort defaults - Default sort by
created_at descunless another field makes more sense for the model.
Step 7: Adapt to the existing TableComponent
The generated component MUST match the exact interface of the project's TableComponent. After reading the base class in Step 1:
- Match the exact method signatures (
query(),loadMore(),loadInitial(), etc.) - Use the correct property names for items (might be
$items,$this->items, or a computed property) - Follow the same pagination/infinite scroll mechanism
- Match any trait usage
If the base class uses a different pattern than shown in the template above, adapt the template to match.
Step 8: Show usage instructions
After generating, display:
## Generated: resources/views/livewire/invoices/index.blade.php
### Add route in routes/app.php:
Route::get('/invoices', function () {
return view('invoices.index');
})->name('invoices.index');
### Create the wrapper view (resources/views/invoices/index.blade.php):
<x-app-layout>
<livewire:invoices.index />
</x-app-layout>
### Or use directly in another component:
<livewire:invoices.index />
### Columns displayed: name, email, status, created_at
### Filters: search (name, email), status
### Sorting: all columns sortable
### Actions: view, edit (opens modal), delete (opens confirmation)
Prerequisites
Limitations
- →Requires adherence to existing TableComponent interface
- →Limited to 4-7 columns for optimal display
- →Requires English defaults for user-visible text
How it compares
It automates the boilerplate creation of complex table views by strictly adhering to established project patterns and conventions rather than manual implementation.
Compared to similar skills
lc:generate-table side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| lc:generate-table (this skill) | 0 | 3mo | No flags | Intermediate |
| pennant-development | 2 | 4mo | No flags | Intermediate |
| developing-with-turbo-streams | 1 | 4mo | No flags | Intermediate |
| developing-with-turbo-frames | 1 | 4mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
pennant-development
laravel
Manages feature flags with Laravel Pennant. Activates when creating, checking, or toggling feature flags; showing or hiding features conditionally; implementing A/B testing; working with @feature directive; or when the user mentions feature flags, feature toggles, Pennant, conditional features, rollouts, or gradually enabling features.
developing-with-turbo-streams
hotwired-laravel
Basics of developing with Turbo Streams in web applications. Activate when working on projects that utilize Turbo Streams for enhancing user experience through real-time updates, dynamic content changes, and partial page updates without full reloads.
developing-with-turbo-frames
hotwired-laravel
Basics of developing with Turbo Frames in web applications. Activate when working on projects that utilize Turbo Frames for enhancing user experience through partial page updates, scoped navigation, and lazy loading of content within specific sections of a web page.
extending-shopper
shopperlabs
Provides patterns for extending Laravel Shopper with custom sidebar items, component overrides, event listeners, and domain features like stock, pricing, and media. Use when customizing Shopper behavior.
migration
JaguarJack
Generate database migration file for CatchAdmin module.
developing-with-turbo-basics
hotwired-laravel
Basics of developing with Turbo in web applications. Activate when working on projects that utilize Turbo for enhancing user experience through partial page updates, real-time interactions, and seamless navigation without full page reloads.