christyoga123/vuelament

Lightning-fast Admin Dashboard & CRUD Generator for Laravel (VILT Stack)

Maintainers

Package info

github.com/ChristYoga123/vuelament

Homepage

pkg:composer/christyoga123/vuelament

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.2.8 2026-03-06 04:00 UTC

This package is auto-updated.

Last update: 2026-03-06 04:01:03 UTC


README

🚀 Vuelament

A lightning-fast, lightweight, and modern Admin Dashboard & CRUD Generator for Laravel.
Built on the VILT stack (Vue 3, Inertia.js, Laravel, Tailwind CSS) and powered by Shadcn Vue for a gorgeous UI.

Latest Version on Packagist License PHP Version

✨ Features

  • Ultra Lightweight: Minimal dependencies, split code-chunking, and no bloat.
  • Beautiful UI: Uses Tailwind CSS v4 and Shadcn-Vue for a premium, accessible, and easily customizable design.
  • VILT Stack: Seamless SPA experience powered by Laravel, Inertia, Vue 3, and Tailwind.
  • Filament-Inspired Architecture: Panel-first, module-based structure with page classes, header actions, and service-based action handling.
  • No Per-Model Controllers: Generic ResourceRouteController handles all CRUD routing automatically — zero boilerplate.
  • Complete Form Builder: Supports Rich Editor (Vue Quill), Date/Time Pickers (VueDatePicker), File Uploads, Selects, Toggles, Checkboxes, Radios, and responsive Grid Layouts.
  • Client-Side Form Reactivity: Show/hide, enable/disable, and change required state of fields instantly without server requests.
  • Robust Table Builder: Supports filtering, search, pagination, bulk actions, column toggling, and rich column types (Text, Badge, Toggle, Checkbox, Image, Icon).
  • Service-Based Actions: Business logic lives in dedicated Service classes — testable, reusable, and separated from framework concerns.
  • Dynamic Modals: Conditional Action dialogs, flexible modal widths, click-away handling, and dangerous action confirmations.
  • Multi-Panel Support: Run multiple isolated admin panels (Admin, Sales, etc.) with zero conflict.

📦 Requirements

  • PHP 8.2+
  • Laravel 11.x / 12.x
  • Node.js 18+ & NPM

🛠️ Installation (Step-by-Step Manual)

Due to frequent issues with automated Shadcn-Vue installations and Tailwind CSS versions, we highly recommend setting up Vuelament and Shadcn-Vue manually following these best practices. Let's build your panel step-by-step!

1. Install via Composer

composer require christyoga123/vuelament

2. Scaffold Configuration & Base Layouts

Run the install command to automatically publish configurations, generate the panel provider, register it, and scaffold Vite and Inertia configurations.

php artisan vuelament:install

3. Install NPM Dependencies

Install Inertia, Vue, Tailwind plugins, and other essential Vuelament dependencies:

npm install @inertiajs/vue3 @vitejs/plugin-vue @vueuse/core @vueup/vue-quill @vuepic/vue-datepicker lucide-vue-next vue-sonner reka-ui class-variance-authority clsx tailwind-merge tw-animate-css
npm install -D typescript vue-tsc

4. Setup Shadcn-Vue (Manual Initialization)

Run the Shadcn-Vue initialization wizard:

npx shadcn-vue@latest init

Choose your preferred settings. Make sure to match this components.json layout, specifically setting "typescript": false and your aliases to @/components and @/lib/utils:

{
  "$schema": "https://shadcn-vue.com/schema.json",
  "style": "new-york",
  "typescript": false,
  "tailwind": {
    "config": "",
    "css": "resources/css/app.css",
    "baseColor": "neutral",
    "cssVariables": true,
    "prefix": ""
  },
  "iconLibrary": "lucide",
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "composables": "@/composables"
  }
}

5. Install Shadcn-Vue Required Components

Vuelament relies on several key components. Install them in one go:

npx shadcn-vue@latest add alert-dialog avatar breadcrumb button card checkbox dialog dropdown-menu input label pagination popover radio-group scroll-area select separator sheet sidebar skeleton sonner switch table textarea tooltip

Tip: If you encounter an error trying to pull the sidebar component (due to strict typescript rules), temporarily change "typescript": true inside components.json, run the add command again, and revert back to false.

6. Run Migrations & Create Admin

Finally, finish the setup by running your migrations, creating an initial user, and starting your dev server:

php artisan migrate
php artisan vuelament:user
npm run dev
php artisan serve

Visit http://localhost:8000/admin/login to access your dashboard!

📁 Architecture — Panel-First, Module-Based

app/Vuelament/{Panel}/{Model}/
    ├── Resources/              ← CRUD page classes (like Filament)
    │    ├── List{Model}s.php        → getHeaderActions(): [CreateAction::make()]
    │    ├── Create{Model}.php       → getHeaderActions(), getFormActions()
    │    └── Edit{Model}.php         → getHeaderActions(), getFormActions()
    │
    ├── Pages/                  ← Custom pages (non-CRUD)
    │
    ├── Services/               ← Business logic (service-based actions)
    │    └── {Model}Service.php
    │
    ├── Widgets/                ← Dashboard widgets
    │
    └── {Model}Resource.php     ← Form schema, table schema, getPages()

No per-model controller needed! The framework's generic ResourceRouteController handles all CRUD routing automatically. You only need Resource + Page classes + Services.

🧩 Artisan Commands

Generate a Resource (full module)

# Multi-page mode (default) — generates List, Create, Edit pages
php artisan vuelament:resource Product --panel=Admin

# Single mode — modal-based create/edit (ManageProducts)
php artisan vuelament:resource Product --panel=Admin --simple

# Auto-generate form/table from database columns
php artisan vuelament:resource Product --panel=Admin --generate

This generates the full module structure:

app/Vuelament/Admin/Product/
    ├── Resources/
    │    ├── ListProducts.php       ← with CreateAction in getHeaderActions()
    │    ├── CreateProduct.php
    │    └── EditProduct.php
    ├── Pages/
    ├── Services/
    │    └── ProductService.php
    ├── Widgets/
    └── ProductResource.php         ← with getPages() referencing page classes

Generate a Service

# Basic — creates ProductService in the Product module
php artisan vuelament:service Product --panel=Admin

# With explicit resource module
php artisan vuelament:service Payment --panel=Admin --resource=Order

Generate a Custom Page

# Standalone page
php artisan vuelament:page Analytics --panel=Admin

# Page attached to a resource
php artisan vuelament:page Report --panel=Admin --resource=User

Generate a Panel

php artisan vuelament:panel Sales --id=sales

Create Admin User

php artisan vuelament:user

🚀 Usage Guide

Page Classes — Like Filament

Page classes define page-level actions via getHeaderActions(). This is identical to Filament's pattern.

// app/Vuelament/Admin/User/Resources/ListUsers.php
use ChristYoga123\Vuelament\Core\Pages\ListRecords;
use ChristYoga123\Vuelament\Components\Actions\CreateAction;

class ListUsers extends ListRecords
{
    protected static ?string $resource = UserResource::class;

    public static function getHeaderActions(): array
    {
        return [
            CreateAction::make(),
            // ExportAction::make(),
            // ImportAction::make(),
        ];
    }
}

Resource Registration — getPages()

Resources register their CRUD page classes and custom pages in getPages():

public static function getPages(): array
{
    return [
        // CRUD page classes — framework reads getHeaderActions() from these
        'index'  => Resources\ListUsers::class,
        'create' => Resources\CreateUser::class,
        'edit'   => Resources\EditUser::class,

        // Custom pages
        'report' => Pages\ReportPage::route('/{record}/report'),
    ];
}

Table Schema — Row-Level Actions Only

Table schemas contain only row-level inline actions. Page-level actions (like "Create") belong in getHeaderActions() on the page class.

public static function tableSchema(): PageSchema
{
    return PageSchema::make()
        ->components([
            Table::make()
                ->query(fn() => User::query()->latest())
                ->columns([
                    TextColumn::make('name')->searchable()->sortable(),
                    TextColumn::make('email')->sortable()->searchable(),
                    ToggleColumn::make('is_active')->label('Active'),
                ])
                ->actions([
                    // ✅ Row-level actions (inline in table)
                    Action::make('deactivate')
                        ->icon('user-x')
                        ->color('warning')
                        ->requiresConfirmation('Deactivate User', 'Are you sure?')
                        ->action([UserService::class, 'deactivate']),
                    EditAction::make(),
                    DeleteAction::make(),
                ])
                ->bulkActions([
                    ActionGroup::make('Bulk Actions')
                        ->icon('list')
                        ->actions([
                            DeleteBulkAction::make(),
                            RestoreBulkAction::make(),
                        ]),
                ])
                ->filters([
                    TrashFilter::make(),
                ])
                ->searchable()
                ->paginated()
                ->selectable(),
        ]);
}

Defining Forms

use ChristYoga123\Vuelament\Components\Layout\Grid;
use ChristYoga123\Vuelament\Components\Layout\Section;
use ChristYoga123\Vuelament\Components\Form\TextInput;
use ChristYoga123\Vuelament\Components\Form\Toggle;

public static function formSchema(): PageSchema
{
    return PageSchema::make()
        ->components([
            Section::make('General Information')
                ->components([
                    Grid::make(2)->components([
                        TextInput::make('name')->required()->uniqueIgnoreRecord(),
                        TextInput::make('email')->email()->required()->uniqueIgnoreRecord(),
                    ]),
                    Toggle::make('is_active')
                        ->label('Status Active')
                        ->hint('Turn off to prevent user login.'),
                    TextInput::make('password')
                        ->password()
                        ->revealable()
                        ->dehydrateStateUsing(fn (string $state): string => Hash::make($state))
                        ->saved(fn (?string $state): bool => filled($state))
                        ->required(fn (string $operation): bool => $operation === 'create'),
                ])
        ]);
}

Available Form Controls

  • TextInput — text, email, password, number, with prefix/suffix and revealable support
  • Textarea — multi-line text input
  • RichEditor — Rich text editor (powered by VueQuill)
  • DatePicker, TimePicker, DateRangePicker — Date/time selection (powered by VuePic)
  • Select — Dropdown selection
  • Checkbox — Single or multiple checkbox group
  • Radio — Radio button group with horizontal/vertical layout
  • Toggle — Switch toggle (powered by Shadcn Switch)
  • FileInput — File upload with drag & drop, preview, and reorder support
  • Repeater — Dynamic repeatable field groups

⚡ Service-Based Actions

Unlike Filament (where actions use Livewire Closures), Vuelament uses dedicated Service classes for business logic. This makes actions testable, reusable, and framework-agnostic.

Flow

Resource   →  defines actions with form + service callable
   ↓
Action     →  captures form data, resolves service from container
   ↓
Service    →  executes business logic (pure PHP, testable)
   ↓
Database   →  Eloquent operations

Action in Resource

Action::make('deactivate')
    ->icon('user-x')
    ->color('warning')
    ->requiresConfirmation('Deactivate User', 'Are you sure?')
    ->action([UserService::class, 'deactivate'])

Service Class

// app/Vuelament/Admin/User/Services/UserService.php
class UserService
{
    public function deactivate(User $user, array $data = []): void
    {
        $user->update(['is_active' => false]);
    }
}

How It Works

The framework resolves the service instance from the container and injects dependencies:

$instance = app(UserService::class);

app()->call([$instance, 'deactivate'], [
    'user'   => $record,    // injected by lowercase model basename
    'record' => $record,    // also available as generic 'record'
    'data'   => $formData,  // form data from modal
]);

Actions with Forms

Action::make('assign_role')
    ->icon('shield')
    ->color('success')
    ->form([
        Select::make('role')->options([
            'admin' => 'Admin',
            'editor' => 'Editor',
        ])->required(),
    ])
    ->action([UserService::class, 'assignRole'])

🎯 Form Reactivity (Client-Side)

Vuelament evaluates form visibility, disabled, and required states entirely on the client — no server requests needed.

⚔️ Vuelament vs Filament

Interaction Filament (Livewire) Vuelament (Vue 3 + Inertia)
Toggle field to show another 🛑 Network request, re-renders component Instant. JavaScript only
Change required state based on selection 🛑 Requires network request Instant. No server overhead
Simple validation visibility 🛑 Network round-trip, can feel sluggish Instant. Zero latency
Toggle::make('is_active')->label('Active Status'),

// Shows INSTANTLY when is_active is toggled on (no server request!)
TextInput::make('activation_code')
    ->visibleWhen('is_active', true)
    ->requiredWhen('is_active', true),

Select::make('type')->options([
    'standard' => 'Standard',
    'premium'  => 'Premium',
]),

// Shows only when type = 'premium'
TextInput::make('premium_code')
    ->visibleWhen('type', 'premium'),

Available Reactivity Methods

Method Description
->visibleWhen('field', value) Show when field equals value
->hiddenWhen('field', value) Hide when field equals value
->disabledWhen('field', value) Disable when field equals value
->enabledWhen('field', value) Enable when field equals value
->requiredWhen('field', value) Required when field equals value
->visibleWhenAll([...]) Show when ALL conditions match (AND logic)
->visibleWhenAny([...]) Show when ANY condition matches (OR logic)

Supported Operators

===, !==, in, notIn, filled, blank, >, <, >=, <=

⚡ Custom Actions & Modals

use ChristYoga123\Vuelament\Components\Table\Actions\Action;

Action::make('form')
    ->icon('form')
    ->color('success')
    ->label('Fill Form')
    ->modalHeading('Detailed User Form')
    ->modalWidth('4xl')
    ->modalCloseByClickingAway(false)
    ->modalCancelActionLabel('Close')
    ->form([
        TextInput::make('reference_id')->required(),
        Radio::make('type')->options([
            'a' => 'Type A',
            'b' => 'Type B',
        ])
    ])
    ->action([SomeService::class, 'processForm'])

Action Configuration Methods

  • ->requiresConfirmation(): Auto-converts the form into a danger Action/Alert Dialog.
  • ->modalWidth('2xl'): Defines the modal width dynamically.
  • ->modalCancelAction(false) / ->modalSubmitAction(false): Hide specific modal buttons.
  • ->modalCloseByClickingAway(false): Prevents accidental closure from outside clicks.

🏢 Multi-Panel Support

Vuelament supports multiple isolated admin panels by default.

Creating a new panel:

php artisan vuelament:panel Sales --id=sales

This creates App\Vuelament\Providers\SalesPanelProvider. Register in bootstrap/providers.php.

Creating resources for a specific panel:

php artisan vuelament:resource Invoice --panel=Sales

Vuelament isolates backend and frontend files into separate silos:

Backend: app/Vuelament/Sales/Invoice/InvoiceResource.php

  • Frontend: resources/js/Pages/Vuelament/Sales/Resource/Invoice/...

AdminPanelProvider and SalesPanelProvider have zero conflict.

Restricting Access via User Model

By default, any authenticated user can access any panel. To restrict access (e.g., using roles), add a hasPanelAccess (or canAccessPanel) method your User model (app/Models/User.php):

use ChristYoga123\Vuelament\Core\Panel;

class User extends Authenticatable
{
    public function hasPanelAccess(Panel $panel): bool
    {
        // Example: Only let users with role 'admin' access the Admin panel
        if ($panel->getId() === 'admin') {
            return $this->role === 'admin';
        }

        // Example: Only let 'sales' role access the Sales panel
        if ($panel->getId() === 'sales') {
            return $this->role === 'sales';
        }

        return true; // Default access
    }
}

If a user tries to log in to a Panel they do not possess access to, Vuelament will gracefully prevent login and securely show a "You cannot access this panel" error.

🎨 Custom Pages & Widgets

Generate completely custom pages for charts, widgets, or dashboards:

php artisan vuelament:page Analytics --panel=Admin

This generates two files:

  • app/Vuelament/Admin/Pages/AnalyticsPage.php
  • resources/js/Pages/Vuelament/Admin/Pages/AnalyticsPage.vue
use ChristYoga123\Vuelament\Core\BasePage;

class AnalyticsPage extends BasePage
{
    protected static ?string $navigationIcon = 'activity';
    protected static ?string $navigationLabel = 'Live Analytics';
    protected static string $slug = 'analytics';

    public static function getData(?\Illuminate\Database\Eloquent\Model $record = null): array
    {
        return [
            'totalUsers' => User::count(),
            'revenue' => 5000000,
        ];
    }
}

🛠️ Performance & Optimizations

  • Automatic Code Splitting: Large libraries (vue-quill, vue-datepicker) are isolated into chunks via Vite.
  • Inertia.js Driven: Lightning-fast SPA page transitions, no full browser reloads.
  • Client-Side Reactivity: Form states evaluated in Vue without server requests.
  • Interactive Column Loading States: Toggle/Checkbox columns disable during server requests, preventing spam.
  • No Per-Model Controllers: Zero boilerplate controllers — framework handles routing.

📁 Frontend Architecture

resources/js/components/vuelament/
├── Table.vue                           # Main table orchestrator
├── table/
│   ├── utils.js                        # Pure helpers (resolveIcon, formatCell)
│   ├── composables/
│   │   └── useTableState.js            # All reactive table state & logic
│   ├── columns/
│   │   ├── ColumnCell.vue              # Dispatcher (selects by col.type)
│   │   ├── TextCell.vue                # Text + prefix/suffix/color
│   │   ├── BadgeCell.vue               # Badge with colors
│   │   ├── ToggleCell.vue              # Shadcn Switch + loading
│   │   ├── CheckboxCell.vue            # Checkbox + loading
│   │   ├── ImageCell.vue               # Image with circle/thumbnail
│   │   └── IconCell.vue                # Dynamic Lucide icon
│   ├── TableToolbar.vue                # Search + filters + column toggle
│   ├── TableFiltersAbove.vue           # Filters above table
│   ├── TableRowActions.vue             # Row actions (edit, delete, custom)
│   ├── TablePagination.vue             # Pagination + per page
│   ├── TableConfirmDialog.vue          # Confirmation dialog
│   └── TableActionFormDialog.vue       # Custom action form dialog
├── form/
│   ├── RichEditor.vue                  # Rich text editor wrapper
│   ├── DatePicker.vue                  # Date/time picker wrapper
│   └── composables/
│       └── useFormReactivity.js         # Client-side form reactivity

Key Design Patterns

  • Composables (useTableState, useFormReactivity) — extract all reactive logic from components
  • Provide/Inject — table sub-components access shared state without prop drilling
  • Column Cell DispatcherColumnCell.vue routes to correct sub-component based on col.type
  • HasReactivity Trait (PHP) — provides visibleWhen(), disabledWhen(), requiredWhen() methods serialized to JSON rules

🔧 Configuration

Publish the config file:

php artisan vendor:publish --tag=vuelament-config
// config/vuelament.php
return [
    'default_panel' => 'admin',
    'user_model' => \App\Models\User::class,
    'app_path' => 'Vuelament',
    'assets' => [
        'auto_publish' => true,
    ],
];

Customizing Stubs

You can publish and customize the code generation stubs:

php artisan vendor:publish --tag=vuelament-stubs

Stubs will be published to stubs/vuelament/. The framework will prioritize custom stubs over package defaults.

📋 All Available Commands

Command Description
vuelament:install Install Vuelament — publish assets, scaffold, setup
vuelament:resource {Name} Generate full CRUD module (Resource + Pages + Service)
vuelament:service {Name} Generate a Service class for action business logic
vuelament:page {Name} Generate a custom page (PHP class + Vue component)
vuelament:panel {Name} Generate a new panel provider
vuelament:user Create an admin user

Common Options

Option Description Available On
--panel=Admin Target panel (default: Admin) resource, service, page
--resource=User Attach to resource module service, page
--simple Single-mode (modal create/edit) resource
--generate Auto-generate from database resource
--force Overwrite existing files all

📄 License

Vuelament is open-sourced software licensed under the MIT License.

Happy Coding! 🎉