πŸ›‘οΈ

Nomanur Laravel Starter Kit

A premium, highly secure, and pre-integrated Laravel blueprint for speed-of-light administrative development.

Filament v5 Shield v4 Pest v4 Livewire V3 Format PHP 8.4 Laravel 13 πŸ› οΈ Helpers Docs

πŸš€ Recent Improvements

Role Management

Integrated Filament Shield for dynamic, UI-driven permission and role management.

Queue Monitoring

Added Filament Jobs Monitor to track background job execution and failures in real-time.

SEO Management

Integrated Filament SEO Pro for real-time SEO analysis, readability scoring, and meta tags rendering.

Modern Livewire

Standardized on the Livewire V3 class format for all dynamic components.

User Resource

Refactored User administration with multi-role support and styled status badges.

πŸ› οΈ Global Helper Functions & Utility Classes

The starter kit includes a robust suite of custom helper classes and global wrapper functions to simplify date formatting, sanitize rich text input, format locale-aware currency, process image uploads/resizes, and optimize page-level SEO metadata. All utility helpers are centralized and fully documented.

Date Formatting HTML Sanitization SEO Meta Tools Image Resizing & Uploads Currency Formatting

See the dedicated helpers.html (or HELPERS.md) page for full signatures, parameter definitions, and clean PHP code examples.

⚑ Quick Installation & Seeding

Setting up your new application is completely automated. Run a single command to touch databases, install packages, and seed administrative access control:

# Create and boot a new project blueprint
composer create-project nomanur/nomanur-starter-kit my-app

# Boot up the concurrent dev environment (HTTP server, queues, pail log tailing)
composer run dev

πŸ”‘ Admin Login

The installation seeder creates a pre-configured Super Admin account for instant administrative dashboard access.

Login URL /admin
Username admin@admin.com
Password 12345678

*Click any value above to copy it instantly to your clipboard.

πŸ“¦ Built-in Stack Features

The starter kit combines modern packages configured with security best practices:

  • Filament PHP Panel

    A responsive dashboard designed with Filament v5.

  • Filament Shield Integration

    Dynamic role & permission management. Secured by Spatie under the hood.

  • Jobs & Queue Monitor

    Real-time queue job monitoring using Croustibat Jobs Monitor.

  • Premium User Resource

    Form-level role management and table display with primary badges.

πŸ›‘οΈ Standard Auditing & Verification

We ensure that the starter kit stays perfectly healthy, styled, and secure. Run composer test to trigger all audits:

βœ“
Pint Linting
Clean style structures
βœ“
Rector Upgrades
PHP 8.4 compliance
βœ“
PHPStan
0 errors level analysis
βœ“
Pest Tests
100% type coverage

πŸ“Έ Spatie Media Library Integration

Spatie Media Library is fully configured and integrated into the starter kit. The storage symlink is automatically generated on installation via automated composer scripts, making media immediately visualizable.

Public Previews Enabled Autolinked Symlink Demo Route: /photo

1. Enable Your Model

Implement HasMedia and use InteractsWithMedia on any Eloquent model:

// app/Models/User.php
class User extends Authenticatable implements HasMedia {
    use InteractsWithMedia;

    public function registerMediaCollections(): void {
        $this->addMediaCollection('avatars')
            ->singleFile();
    }
}

2. Upload Files via Livewire

Handle temporary files easily and attach them directly to media collections:

// app/Livewire/Test.php
class Test extends Component {
    use WithFileUploads;
    public $photo;

    public function save(): void {
        $this->validate(['photo' => 'image|max:5120']);
        $this->user->addMedia($this->photo->getRealPath())
            ->toMediaCollection('avatars');
    }
}

βœ‚οΈ Image Cropping System

The starter kit ships with a fully integrated client-side image cropping system powered by Cropper.js and Alpine.js. Users can select an image, crop it to a desired aspect ratio, and upload the cropped result β€” all before the file ever touches the server.

Client-Side Cropping Cropper.js v1.6 Alpine.js Plugin Livewire Upload Ready

How It Works

The cropping pipeline runs entirely on the client side:

  • File Selection

    User picks an image via a file input.

  • Crop Interface

    A glassmorphic modal opens with the image loaded into Cropper.js. User adjusts the crop area.

  • Canvas Extraction

    On "Apply Crop", getCroppedCanvas() extracts the selection as a canvas, then toBlob() produces a JPEG File blob.

  • Livewire Upload

    An image-cropped custom event dispatches the file. Livewire's @this.upload() receives it as a temporary upload.

  • Media Library Save

    The Livewire component validates and persists the cropped file to Spatie Media Library.

Quick Usage

Drop the Alpine component into any Livewire Blade view. The minimal setup:

<!-- resources/views/livewire/test.blade.php -->
<div
    x-data="imageCropper({ cropping: true, aspectRatio: 1 })"
    @image-cropped.window="@this.upload('photo', $event.detail.file)"
    wire:ignore
>
    <input type="file" x-ref="fileInput" @change="onFileChange" />

    <x-cropping-modal />
</div>

Click Copy full code above to copy the complete code including the reusable <x-cropping-modal /> component.

Alpine Component API

The imageCropper component accepts a config object:

// Config properties
{
  cropping: true,      // bool, default false
  aspectRatio: 1,      // number, default NaN (freeform)
}
// Methods
onFileChange(event)  // Read file & show modal
saveCrop()             // Apply, dispatch event, close
cancelCrop()           // Discard, close, clear input
clearInput()            // Reset file input value
// Events
@image-cropped="handler"
// $event.detail = { file: File, dataUrl: string }

Livewire Component

Listen for the cropped file and save to Spatie Media Library:

// app/Livewire/Test.php
class Test extends Component
{
    use WithFileUploads;

    public ?TemporaryUploadedFile $photo = null;

    public function save(): void
    {
        $this->validate([
            'photo' => ['required', 'image', 'max:5120'],
        ]);

        $this->user->addMedia($this->photo->getRealPath())
            ->toMediaCollection('avatars');
    }
}

Visit /photo on your local server to see the full cropping + upload workflow in action. The crop modal is a reusable Blade component β€” use <x-cropping-modal /> anywhere with customizable title, cancelText, and applyText props.

πŸͺ΅ Opcodes Log Viewer Integration

Opcodes Log Viewer provides a comprehensive, interactive administrative interface for inspecting application log files in real-time. Access is secured natively at the service level and dynamic in Filament sidebars.

Restricted to Super Admin Spatie Permissions Integration Sidebar Link: System > Log Viewer

1. Route Authorization

Authorized exclusively for the super_admin role inside the AppServiceProvider class:

// app/Providers/AppServiceProvider.php
private function configureLogViewer(): void {
    LogViewer::auth(function (Request $request): bool {
        return $request->user()?->hasRole('super_admin') ?? false;
    });
}

2. Filament Sidebar Permission

Visible in Filament via the view_log_viewer custom permission inside the admin panel provider:

// app/Providers/Filament/AdminPanelProvider.php
NavigationItem::make('Log Viewer')
    ->url(fn (): string => url('log-viewer'))
    ->icon('heroicon-o-document-text')
    ->group('System')
    ->visible(fn (): bool => auth()->user()?->can('view_log_viewer') ?? false)

🌐 Laravel Socialite OAuth Integration

The starter kit is fully integrated with Laravel Socialite to enable passwordless OAuth logins. The system dynamically auto-detects active providers via the SocialiteProvider enum and renders a styled list of options using a premium Livewire component.

⚠️ Important: The <livewire:socialite /> component automatically hides itself when no integrations are active. You must uncomment the provider blocks in config/services.php and set their credentials in .env for the buttons to appear in the UI.

Dynamic Auto-Detection Passwordless Login Ready Component: <livewire:socialite />

1. Add Credentials & Config

Fill in credentials inside your .env file, then uncomment the matching array inside config/services.php:

// config/services.php
'github' => [
    'client_id' => env('GITHUB_CLIENT_ID'),
    'client_secret' => env('GITHUB_CLIENT_SECRET'),
    'redirect' => '/auth/github/callback',
],

2. Drop Into Any Blade View

Use the Livewire component anywhere on your login/register pages with options to customize columns, size, and labels:

// resources/views/auth/login.blade.php
<livewire:socialite
    heading="Or continue with"
    :columns="2"
    size="md"
    :showLabels="true"
/>

🌍 Multilingual Translation & Localization System

The starter kit features a pre-configured, end-to-end multilingual and geo-location translation architecture. Combining Spatie's laravel-translatable with local Geo-IP services, administrators can manage content across multiple languages in the Filament Panel, while visitors are automatically served pages in their native tongue based on their geolocation or browser preference.

Multi-Language Tabs Geo-IP Detection Locale-Scoped Search Settings-Driven Locales Manual Switch Overrides

1. Define Translatable Models

Implement Spatie's HasTranslations trait on your Eloquent model and list the translatable columns in the $translatable property:

// app/Models/Post.php
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;

class Post extends Model {
    use HasTranslations;

    protected $fillable = ['title', 'content'];
    public array $translatable = ['title', 'content'];
}

2. Build Tabbed Forms & Search

Wrap your input schema using the custom Translatable helper. It generates beautiful, localized tabs based on active locales:

// app/Filament/Resources/Posts/Schemas/PostForm.php
use App\Filament\Forms\Components\Translatable;
use Filament\Forms\Components\TextInput;

Translatable::make(function (string $locale): array {
    return [
        TextInput::make("title.{$locale}")
            ->required(),
    ];
})

3. Geo-IP & Browser Locale Detection

The global SetLocaleMiddleware automatically intercepts web requests, queries the user's IP address, and maps country codes to active languages:

// app/Http/Middleware/SetLocaleMiddleware.php
// 1. Checks session for active locale override.
// 2. Uses laravelGeoGenius() to detect country:
$countryCode = laravelGeoGenius()->geo()
    ->getCountryCode(); // e.g., 'BD'

// 3. Fallback: Browser headers or config default.
$locale = $this->countryToLocaleMap[$countryCode]
    ?? $request->getPreferredLanguage();

4. Dynamic Admin Settings

Locales are entirely dynamic. Manage supported languages via System > Settings > Translatable Locales in the Filament Sidebar:

// Updates .env key in the dashboard
TRANSLATABLE_LOCALES=en,bn,es,fr

// Handled via AppServiceProvider & SettingsPage
config('app.translatable_locales');

// Renders locale tabs instantly in forms!

5. Implementing a Manual Language Selector

Provide manual language selection anywhere on the frontend. Define a session-setting route and display selector links:

// routes/web.php
Route::get('/language/{locale}', function ($locale) {
    if (in_array($locale, config('app.translatable_locales', ['en']))) {
        session(['locale' => $locale]);
    }
    return back();
})->name('language.switch');
// resources/views/welcome.blade.php
<div class="flex gap-4">
    <a href="{{ route('language.switch', 'en') }}">English</a>
    <a href="{{ route('language.switch', 'bn') }}">Bengali</a>
</div>

// The SetLocaleMiddleware respects this session override
// across all requests automatically!

πŸ” Search Engine Optimization (SEO)

The starter kit integrates the premium filament-seo-pro package to provide real-time search engine optimization, keywords optimization, readability analysis, and live previews of search results directly in Filament resource panels. The application's main layout file (resources/views/layouts/app.blade.php) is already pre-configured to render these SEO meta codes dynamically.

Polymorphic HasSeo Trait Real-Time Readability & Score Google & Social Previews Automatic Head Metadata

1. Add HasSeo Trait to Models

Attach the trait to any Eloquent model to connect it with polymorphic SEO metadata:

// app/Models/Post.php
use Nomanur\FilamentSeoPro\Traits\HasSeo;

class Post extends Model {
    use HasSeo;
}

2. Register Filament Component

Add the prebuilt SEO tab component to resource form schemas to unlock the analysis editor:

// app/Filament/Resources/Posts/Schemas/PostForm.php
use Nomanur\FilamentSeoPro\Forms\SeoTab;

public static function configure(Form $form): Form {
    return $form->schema([
        Tabs::make('Heading')->tabs([
            SeoTab::make(),
        ]),
    ]);
}

3. Automatic Layout Rendering

The global HTML <head> renders SEO tags, Open Graph properties, Twitter cards, and Schema.org JSON-LD dynamically with clean fallbacks for static pages:

// resources/views/layouts/app.blade.php
<!-- Basic Meta Tags -->
<title>{{ $seoModel?->seo?->title ?? $seoModel?->title ?? $title ?? config('app.name', 'Laravel Starter') }}</title>
<meta name="description" content="{{ $seoModel?->seo?->description ?? ($seoModel?->content ? Str::limit(strip_tags($seoModel->content), 150) : '') }}">
<meta name="robots" content="{{ $seoModel?->seo?->robots ?? 'index, follow' }}">
<link rel="canonical" href="{{ $seoModel?->seo?->canonical_url ?? request()->url() }}">

4. Automated Sitemap Generation

Generate a structured XML sitemap using the integrated spatie/laravel-sitemap console command, scheduled daily:

# Generate the sitemap manually
php artisan sitemap:generate

// routes/console.php (Scheduled daily updates)
Schedule::command('sitemap:generate')->daily();

5. Crawling Controls (robots.txt)

Managed via public/robots.txt, directing search engines away from admin paths while indexing layouts:

# public/robots.txt content
User-agent: *
Disallow: /admin/
Disallow: /log-viewer/

Sitemap: http://starterkit.test/sitemap.xml

See the official package repository and documentation at filament-seo-pro Documentation for advanced usage, custom checks, and configurations.

πŸ“₯ CSV/Excel Export & Import

The starter kit ships with a reusable ExportImport trait that adds export and import buttons to any Filament resource table. It supports CSV and Excel (XLSX) formats with styled output and column selectionβ€”no additional setup required for CSV.

Zero-Dependency CSV Column Selection Modal Styled XLSX Headers Auto-Sized Columns

1. Add Trait to Resource

Use the trait in any Filament resource and override columns/query if needed:

// app/Filament/Resources/Posts/PostResource.php
class PostResource extends Resource {
    use ExportImport;

    public static function getExportColumns(): array {
        return [
            'id' => 'ID',
            'title' => 'Title',
            'content' => 'Content',
        ];
    }
}

2. Wire Actions to Table

Add export and import action buttons to the table toolbar in your table schema:

// app/Filament/Resources/Posts/Tables/PostsTable.php
public static function configure(Table $table): Table {
    return $table
        ->toolbarActions([
            PostResource::getExportAction(),
            PostResource::getImportAction(),
        ]);
}

See EXPORT_IMPORT_TRAIT.md for full documentation, including custom query filters, import file format specs, and handling translatable columns.

πŸ” Two-Factor Authentication (2FA)

The starter kit features a secure, industry-standard Time-based One-time Password (TOTP) Two-Factor Authentication system for admin panel protection. Unverified users with 2FA enabled are locked to the challenge page while keeping their Laravel sessions intact.

Secure SVG QR Code Encrypted Recovery Codes TwoFactorMiddleware Pest Test Covered

1. Toggle 2FA in Users Resource

Admin users can enable/disable 2FA from the edit user interface. Opening the modal generates a persistent secret and renders a scanable SVG QR code inline:

// app/Filament/Resources/Users/Pages/EditUser.php
Hidden::make('two_factor_secret')
    ->default(fn () => (new Google2FA)->generateSecretKey());

Placeholder::make('qr_code')
    ->content(fn ($get) => new HtmlString(...));

2. Protection Middleware

The custom TwoFactorMiddleware intercepts all panel requests for users who have 2FA enabled, redirecting them to verification if not verified in their session:

// app/Http/Middleware/TwoFactorMiddleware.php
if ($user->hasTwoFactorEnabled() &&
    ! session()->has('two_factor_verified_at')) {
    return redirect()->route('filament.admin.pages.two-factor-challenge');
}

πŸ“ Profile Validation Rules Trait

The ProfileValidationRules trait centralizes common email and password validation rules across registration, edit profile, and password reset interfaces to ensure consistent architecture and security policies.

Centralized Validation Dynamic ID Ignoring Saves Boilerplate

1. Define Trait

Centralizes email and password rules (e.g. required, length, unique check, confirmation matching):

// app/Traits/ProfileValidationRules.php
trait ProfileValidationRules {
    protected function emailRules(?int $userId = null): array;
    protected function passwordRules(): array;
}

2. Usage Example

Import and use validation helper methods in form requests, controllers, or livewire components:

// Any Controller or Component
use App\Traits\ProfileValidationRules;
class RegisterController extends Controller {
    use ProfileValidationRules;

    public function save() {
        $this->validate(['email' => $this->emailRules()]);
    }
}

βš™οΈ Core Application Configurations

The AppServiceProvider is meticulously tuned for developer productivity, data integrity, and production safety. We encapsulate these configurations into dedicated, descriptive methods (configureModels, configureCommands, configureDates) to ensure global application behavior is predictable, centralized, and easy to maintain.

  • Strict Eloquent Models

    Enforced via Model::shouldBeStrict(). This prevents lazy loading, accessing missing attributes, and silent failures, catching common bugs early in development.

  • Unguarded Models

    Models are unguarded to streamline data handling. We shift safety responsibility to the entry points like Form Requests and Filament Schemas.

  • Super Admin Permissions

    An implicit Gate::before check ensures that any user with the super_admin role bypasses all permission checks, simplifying admin access management.

  • Production Protection

    We use DB::prohibitDestructiveCommands() to lock down commands like migrate:fresh in production, adding a critical safety layer against data loss.

  • Immutable Dates

    By defaulting to CarbonImmutable, we eliminate entire classes of bugs where date objects are accidentally mutated during formatting or math.

  • Architectural Clarity

    Centralizing these defaults in AppServiceProvider ensures every developer on the team follows the same rigorous standards without manual overhead.

Copied to clipboard! πŸ“‹