monorailphp/monorail

A Laravel package for monorail functionality

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

Language:TypeScript

pkg:composer/monorailphp/monorail

v0.2.0-alpha 2025-10-06 23:10 UTC

This package is not auto-updated.

Last update: 2025-10-07 01:47:32 UTC


README

A modern Laravel admin panel package built with Inertia.js, React, and shadcn/ui, featuring a beautiful UI and powerful resource management capabilities.

Features

  • 🎨 Modern UI: Built with React, Tailwind CSS, and Radix UI components
  • 📊 Resource Management: Automatic CRUD operations for your models
  • 🔍 Advanced Filtering: Built-in filters for text, dates, booleans, and more
  • 📋 Data Tables: Sortable, searchable tables with pagination
  • 🎯 Actions: Bulk actions, individual row actions, and custom actions
  • 🔐 Authentication: Integrated with Laravel Fortify
  • 📱 Responsive: Mobile-first design that works on all devices
  • Fast: Built with Inertia.js for SPA-like experience
  • 🎛️ Configurable: Highly customizable through configuration files

Requirements

  • PHP 8.1 or higher
  • Laravel 10, 11, or 12

Installation

1. Install via Composer

composer require monorailphp/monorail

2. Publish Configuration

php artisan vendor:publish --tag=monorail-config

This will publish the config/monorail.php file where you can configure:

  • Resource paths and namespaces
  • Model namespaces
  • Route prefixes and middleware
  • Admin panel settings

3. Publish Migrations

php artisan vendor:publish --tag=monorail-migrations
php artisan migrate

4. Publish Assets

Publish the built assets to your public directory:

php artisan vendor:publish --tag=monorail-assets

Quick Start

1. Create Your First Resource

Generate a resource for one of your models:

php artisan make:monorail-resource User

This will create a resource file at app/Monorail/Resources/UserResource.php.

2. Configure Your Resource

Edit the generated resource to define columns, fields, and filters using the new Table and Form classes:

<?php

namespace App\Monorail\Resources;

use App\Models\User;
use Monorailphp\Monorail\Actions\ViewAction;
use Monorailphp\Monorail\Actions\EditAction;
use Monorailphp\Monorail\Actions\DeleteAction;
use Monorailphp\Monorail\Actions\BulkDeleteAction;
use Monorailphp\Monorail\Columns\TextColumn;
use Monorailphp\Monorail\Columns\EmailColumn;
use Monorailphp\Monorail\Columns\DateTimeColumn;
use Monorailphp\Monorail\Fields\TextField;
use Monorailphp\Monorail\Fields\EmailField;
use Monorailphp\Monorail\Fields\PasswordField;
use Monorailphp\Monorail\Form;
use Monorailphp\Monorail\Resources\BaseResource;
use Monorailphp\Monorail\Table;

class UserResource extends BaseResource
{
    public function getModel(): string
    {
        return User::class;
    }

    public function getLabel(): string
    {
        return 'User';
    }

    public function getPluralLabel(): string
    {
        return 'Users';
    }

    public function getIcon(): ?string
    {
        return 'users';
    }

    public function table(): Table
    {
        return Table::make()
            ->columns([
                TextColumn::make('id')
                    ->label('ID')
                    ->sortable()
                    ->width('80px'),

                TextColumn::make('name')
                    ->label('Name')
                    ->sortable()
                    ->searchable(),

                EmailColumn::make('email')
                    ->label('Email')
                    ->sortable()
                    ->searchable(),

                DateTimeColumn::make('created_at')
                    ->label('Created At')
                    ->sortable()
                    ->since(),
            ])
            ->actions([
                new ViewAction,
                new EditAction,
                new DeleteAction,
            ])
            ->bulkActions([
                new BulkDeleteAction,
            ])
            ->perPage(20)
            ->emptyState(
                'No users found',
                'Get started by creating your first user.',
                'users',
                'Create User',
                route('admin.resources.create', ['resource' => 'users'])
            )
            ->perPageOptions([5, 10, 20, 50, 100])
            ->appearance(
                showHeader: true,
                showFooter: true,
                striped: true,
                hoverable: true,
                bordered: false,
                compact: false
            )
            ->filters([])
            ->defaultSort('created_at', 'desc');
    }

    public function form(): Form
    {
        return Form::make()
            ->fields([
                TextField::make('name')
                    ->label('Name')
                    ->required()
                    ->maxLength(255)
                    ->placeholder('Enter Name'),

                EmailField::make('email')
                    ->label('Email')
                    ->required()
                    ->createRules(['unique:users'])
                    ->updateRules(['unique:users,email,'.request()->route('id')])
                    ->placeholder('Enter Email'),

                PasswordField::make('password')
                    ->label('Password')
                    ->required()
                    ->minLength(8)
                    ->showToggle()
                    ->requireConfirmation()
                    ->placeholder('Enter Password'),
            ])
            ->submitLabel('Save User')
            ->cancelLabel('Cancel');
    }
}

3. Advanced Resource Example

Here's a more complex example showing relationships, filters, and advanced field types:

<?php

namespace App\Monorail\Resources;

use App\Models\Post;
use Monorailphp\Monorail\Actions\ViewAction;
use Monorailphp\Monorail\Actions\EditAction;
use Monorailphp\Monorail\Actions\DeleteAction;
use Monorailphp\Monorail\Actions\BulkDeleteAction;
use Monorailphp\Monorail\Columns\TextColumn;
use Monorailphp\Monorail\Columns\BooleanColumn;
use Monorailphp\Monorail\Columns\DateTimeColumn;
use Monorailphp\Monorail\Fields\TextField;
use Monorailphp\Monorail\Fields\TextareaField;
use Monorailphp\Monorail\Fields\SelectField;
use Monorailphp\Monorail\Fields\CheckboxField;
use Monorailphp\Monorail\Fields\DateTimeField;
use Monorailphp\Monorail\Filters\BooleanFilter;
use Monorailphp\Monorail\Form;
use Monorailphp\Monorail\Resources\BaseResource;
use Monorailphp\Monorail\Table;

class PostResource extends BaseResource
{
    public function getModel(): string
    {
        return Post::class;
    }

    public function getLabel(): string
    {
        return 'Post';
    }

    public function getPluralLabel(): string
    {
        return 'Posts';
    }

    public function getIcon(): ?string
    {
        return 'document-text';
    }

    public function table(): Table
    {
        return Table::make()
            ->columns([
                TextColumn::make('id')
                    ->label('ID')
                    ->sortable()
                    ->width('80px'),

                TextColumn::make('title')
                    ->label('Title')
                    ->sortable()
                    ->searchable(),

                TextColumn::make('content')
                    ->label('Content')
                    ->sortable()
                    ->searchable(),

                TextColumn::make('slug')
                    ->label('Slug')
                    ->sortable(),

                TextColumn::make('user.name')
                    ->label('Author')
                    ->sortable(),

                BooleanColumn::make('published')
                    ->label('Published')
                    ->filterable()
                    ->trueLabel('Yes')
                    ->falseLabel('No'),

                DateTimeColumn::make('published_at')
                    ->label('Published At')
                    ->sortable(),

                DateTimeColumn::make('created_at')
                    ->label('Created At')
                    ->sortable()
                    ->since(),

                DateTimeColumn::make('updated_at')
                    ->label('Updated At')
                    ->sortable()
                    ->since(),
            ])
            ->actions([
                new ViewAction,
                new EditAction,
                new DeleteAction,
            ])
            ->bulkActions([
                new BulkDeleteAction,
            ])
            ->perPage(20)
            ->emptyState(
                'No posts found',
                'Get started by creating your first post.',
                'document-text',
                'Create Post',
                route('admin.resources.create', ['resource' => 'posts'])
            )
            ->perPageOptions([5, 10, 20, 50, 100])
            ->appearance(
                showHeader: true,
                showFooter: true,
                striped: true,
                hoverable: true,
                bordered: false,
                compact: false
            )
            ->filters([
                BooleanFilter::make('published', 'Published')
                    ->placeholder('All Published statuses'),
            ])
            ->defaultSort('created_at', 'desc');
    }

    public function form(): Form
    {
        return Form::make()
            ->fields([
                TextField::make('title')
                    ->label('Title')
                    ->required()
                    ->maxLength(255)
                    ->placeholder('Enter post title'),

                TextareaField::make('content')
                    ->label('Content')
                    ->rows(6)
                    ->placeholder('Enter post content'),

                TextField::make('slug')
                    ->label('Slug')
                    ->maxLength(255)
                    ->placeholder('post-url-slug'),

                SelectField::make('user_id')
                    ->label('Author')
                    ->required()
                    ->searchable()
                    ->relation('user', 'name')
                    ->placeholder('Select an author'),

                CheckboxField::make('published')
                    ->label('Published'),

                DateTimeField::make('published_at')
                    ->label('Published At')
                    ->placeholder('Select publish date'),
            ])
            ->submitLabel('Save Post')
            ->cancelLabel('Cancel');
    }
}

4. Access the Admin Panel

Visit /admin in your browser to access the admin panel. You'll see your resources listed in the navigation.

Configuration

Environment Variables

Add these to your .env file to customize Monorail:

# Resource Configuration
MONORAIL_RESOURCES_PATH=Monorail/Resources
MONORAIL_RESOURCES_NAMESPACE=App\\Monorail\\Resources

# Model Configuration
MONORAIL_MODELS_NAMESPACE=App\\Models

# Route Configuration
MONORAIL_ROUTE_PREFIX=admin
MONORAIL_ROUTE_NAME_PREFIX=admin.
MONORAIL_MIDDLEWARE=web,auth,verified
MONORAIL_ROUTES_ENABLED=true

Resource Configuration

Resources are automatically discovered from the configured path. You can also manually register resources by adding them to your service provider.

Available Components

Table Configuration

The Table class provides comprehensive table configuration:

Table::make()
    ->columns([...])           // Define table columns
    ->actions([...])          // Row-level actions
    ->bulkActions([...])     // Bulk actions
    ->perPage(20)            // Items per page
    ->emptyState(              // Empty state configuration
        'No records found',
        'Get started by creating your first record.',
        'icon-name',
        'Create Record',
        route('admin.resources.create', ['resource' => 'resource-name'])
    )
    ->perPageOptions([5, 10, 20, 50, 100]) // Pagination options
    ->appearance(              // Table appearance
        showHeader: true,
        showFooter: true,
        striped: true,
        hoverable: true,
        bordered: false,
        compact: false
    )
    ->filters([...])          // Available filters
    ->defaultSort('created_at', 'desc'); // Default sorting

Columns

  • TextColumn - Display text data with sorting and searching
    • ->hidden() - Hide column from display
    • ->width('80px') - Set column width
  • EmailColumn - Display email addresses with mailto links
  • NumberColumn - Display numeric data with formatting
  • DateTimeColumn - Display dates and times
    • ->since() - Show relative time (e.g., "2 hours ago")
  • BooleanColumn - Display boolean values
    • ->trueLabel('Yes') - Custom label for true values
    • ->falseLabel('No') - Custom label for false values
    • ->filterable() - Enable filtering for this column

Form Configuration

The Form class provides comprehensive form configuration:

Form::make()
    ->fields([...])           // Define form fields
    ->submitLabel('Save')     // Submit button text
    ->cancelLabel('Cancel')   // Cancel button text
    ->showCancelButton(true)  // Show cancel button
    ->showSubmitButton(true); // Show submit button

Fields

  • TextField - Text input with validation rules
    • ->maxLength(255) - Set maximum length
    • ->placeholder('Enter text') - Set placeholder text
  • EmailField - Email input with validation
    • ->createRules(['unique:users']) - Validation rules for creation
    • ->updateRules(['unique:users,email,'.request()->route('id')]) - Validation rules for updates
  • NumberField - Numeric input with min/max
  • PasswordField - Password input with advanced options
    • ->minLength(8) - Set minimum length
    • ->showToggle() - Show password visibility toggle
    • ->requireConfirmation() - Require password confirmation
  • TextareaField - Multi-line text areas
    • ->rows(6) - Set number of rows
  • SelectField - Dropdown selections with relationship support
    • ->searchable() - Enable search functionality
    • ->relation('user', 'name') - Load options from relationship
  • CheckboxField - Checkbox inputs
  • DateTimeField - Date and time inputs

Filters

  • TextFilter - Text-based filtering
  • SelectFilter - Dropdown filtering
  • BooleanFilter - True/false filtering with custom labels
  • DateFilter - Date-based filtering
  • DateRangeFilter - Date range filtering

Actions

  • ViewAction - View individual records
  • EditAction - Edit individual records
  • DeleteAction - Delete individual records
  • BulkDeleteAction - Delete multiple records
  • UrlAction - Custom URL actions

Commands

Make Resource

Create a new resource for a model:

php artisan make:monorail-resource ModelName

Discover Resources

Automatically discover and register all resources:

php artisan monorail:discover-resources

Publish Assets

Publish the built frontend assets:

php artisan monorail:publish-assets

Customization

Custom Themes

You can customize the appearance by modifying the CSS variables in the published assets or by extending the base components.

Custom Components

Create custom columns, fields, and filters by extending the base classes:

use Monorailphp\Monorail\Columns\Column;

class CustomColumn extends Column
{
    public function render($record): string
    {
        // Your custom rendering logic
        return $record->custom_field;
    }
}

Custom Actions

Create custom actions by extending the base Action class:

use Monorailphp\Monorail\Actions\Action;

class CustomAction extends Action
{
    public function handle($records): void
    {
        // Your custom action logic
    }
}

Resource Methods

Override these methods in your resource class to customize behavior:

class UserResource extends BaseResource
{
    // Required methods
    public function getModel(): string
    public function getLabel(): string
    public function getPluralLabel(): string
    
    // Optional methods
    public function getIcon(): ?string
    public function table(): Table
    public function form(): Form
    
    // Customize table configuration
    public function table(): Table
    {
        return Table::make()
            ->columns([...])
            ->actions([...])
            ->bulkActions([...])
            ->perPage(20)
            ->emptyState(...)
            ->perPageOptions([5, 10, 20, 50, 100])
            ->appearance(...)
            ->filters([...])
            ->defaultSort('created_at', 'desc');
    }
    
    // Customize form configuration
    public function form(): Form
    {
        return Form::make()
            ->fields([...])
            ->submitLabel('Save')
            ->cancelLabel('Cancel');
    }
}

Development

Building Assets

To build the frontend assets for development:

npm run dev

To build for production:

npm run build

Testing

Run the test suite:

composer test

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This package is open-sourced software licensed under the MIT license.

Support

If you encounter any issues or have questions, please open an issue on the GitHub repository.