zofe/rapyd-admin

rapyd admin for laravel

Maintainers

Package info

github.com/zofe/rapyd-admin

Language:CSS

pkg:composer/zofe/rapyd-admin

Transparency log

Fund package maintenance!

zofe

Other

Statistics

Installs: 151

Dependents: 1

Suggesters: 0

Stars: 6

Open Issues: 0


README

Build Status Total Downloads Latest Stable Version

rapyd.dev

Rapyd Admin is an open-source admin panel for Laravel — a light alternative to Nova, Filament and Backpack, designed for teams building SaaS products and for development with AI agents.

Live demo →

Why Rapyd Admin

Consistent patterns, plain code. No DSL, no proprietary resource classes. Unlike Nova or Filament, Rapyd Admin generates plain Livewire + Blade files that live in your codebase and are yours to edit. It gives you the structure you'd write anyway — consistent module layout, a unified x-rpd:: field component API, auth and multi-tenancy included — then stays out of the way.

Built for SaaS. Auth (Fortify, Socialite, 2FA), roles & permissions, and multi-tenant Companies (1–3 tiers, optional UUID keys) are bundled. One command sets up a production-ready starting point.

Agent-friendly. Flat, self-contained module folders with consistent naming. LLMs can scaffold and extend without reverse-engineering proprietary abstractions.

Requirements

  • PHP 8.2+
  • Laravel 11 / 12 / 13
  • Livewire 4

Installation

composer create-project --prefer-dist laravel/laravel myapp
cd myapp
composer require zofe/rapyd-admin

Run the setup command to configure the database, publish configs, and seed the default admin user:

php artisan rpd:make:setup
php artisan serve

Login with the default admin account:

email:    admin@laravel
password: admin

What's included

Rapyd Admin ships three bundled modules — no extra packages needed:

  • Layout — navbar/sidebar based on SBAdmin 3, updated to Bootstrap 5.3, SCSS customizable, anonymous Blade components.
  • Auth — authentication via Laravel Fortify, Socialite, 2FA, and role/permission management via spatie/laravel-permission.
  • Companies — multi-tenant company hierarchy (1–3 tiers), with optional UUID primary keys.

Generators

Livewire component

php artisan rpd:make UserTable User

Generates app/Livewire/UserTable.php and its blade view.

Module (Table + View + Edit)

php artisan rpd:make Articles Article --module=Blog

Creates app/Modules/Blog/ with:

app/Modules/Blog/
├── Livewire/
│   ├── ArticlesEdit.php
│   ├── ArticlesTable.php
│   └── ArticlesView.php
├── Views/
│   ├── articles_edit.blade.php
│   ├── articles_table.blade.php
│   └── articles_view.blade.php
└── routes.php

Blade Components

Table

Datatable with filters, sorting, and pagination:

<x-rpd::table title="Articles" :items="$items">

    <x-slot name="filters">
        <x-rpd::input col="col-8" debounce="350" model="search" placeholder="search..." />
        <x-rpd::select col="col-4" model="author_id" :options="$authors" placeholder="author..." addempty />
    </x-slot>

    <table class="table">
        <thead><tr>
            <th><x-rpd::sort model="id" label="id" /></th>
            <th>title</th>
        </tr></thead>
        <tbody>
        @foreach ($items as $article)
        <tr>
            <td><a href="{{ route('articles.view', $article->id) }}">{{ $article->id }}</a></td>
            <td>{{ $article->title }}</td>
        </tr>
        @endforeach
        </tbody>
    </table>

</x-rpd::table>

View

Detail page with buttons and actions:

<x-rpd::view title="Article Detail">
    <x-slot name="buttons">
        <x-rpd::button route="articles" color="outline-primary" label="list" />
        <x-rpd::button :route="['articles.edit', $model->getKey()]" color="outline-primary" label="edit" />
    </x-slot>
    <div>Title: {{ $article->title }}</div>
</x-rpd::view>

Edit

Form bound to a Livewire model:

<x-rpd::edit title="Article Edit">
    <x-rpd::input model="article.title" label="Title" />
    <x-rpd::rich-text model="article.body" label="Body" />
</x-rpd::edit>

Form Fields

All field components use wire:model.live.debounce.150ms by default. Pass :lazy="true" to switch to wire:model.blur.

<x-rpd::input model="search" debounce="350" placeholder="search..." />

<x-rpd::select model="author_id" :options="$authors" />

<!-- TomSelect dropdown, supports remote endpoint -->
<x-rpd::select-list model="roles" multiple :options="$available_roles" label="Roles" />
<x-rpd::select-list model="roles" multiple endpoint="/ajax/roles" label="Roles" />

<x-rpd::date model="date" format="dd/MM/yyyy" value-format="yyyy-MM-dd" label="Date" />
<x-rpd::datetime model="date_time" format="dd/MM/yyyy HH:mm" value-format="yyyy-MM-dd HH:mm:ss" label="DateTime" />

<x-rpd::textarea model="body" label="Body" rows="5" />

<!-- Quill WYSIWYG -->
<x-rpd::rich-text model="body" label="Body" />

<x-rpd::upload model="file" label="Upload" />

<x-rpd::checkbox model="active" label="Active" />

<x-rpd::radiogroup model="status" :options="['active','inactive']" label="Status" />

Common props: label, placeholder, model, options, debounce, prepend, append, help, icon, size, multiple, endpoint, format, value-format, rows.

Navigation Components

<!-- Sort link inside a datatable -->
<x-rpd::sort model="id" label="id" />

<!-- Nav tabs -->
<ul class="nav nav-tabs">
    <x-rpd::nav-link label="Home" route="home" />
    <x-rpd::nav-link label="Articles" route="articles" />
</ul>

<!-- Sidebar with grouped items -->
<x-rpd::sidebar title="Rapyd.dev" class="p-3 text-white border-end">
    <x-rpd::nav-item label="Demo" route="demo" active="/rapyd-demo" />
</x-rpd::sidebar>

<!-- Collapsible dropdown in sidebar -->
<x-rpd::nav-dropdown icon="fas fa-fw fa-book" label="KnowledgeBase" active="/kb">
    <x-rpd::nav-link label="Edit Articles" route="kb.admin.articles.table" type="collapse-item" />
</x-rpd::nav-dropdown>

Companies / Multi-tenancy

Enable Companies in your .env:

RPD_TIERS=2
RPD_TIER1_LABEL=partner
RPD_TIER2_LABEL=customer

Run php artisan rpd:make:setup — it will seed a root company and a demo tenant automatically.

To enable company scoping on your User model, run:

php artisan rpd:install --companies

Livewire 4 notes

  • wire:model.lazy has been removed in LW4. All x-rpd:: field components default to wire:model.live.debounce.150ms. Pass :lazy="true" to use wire:model.blur.
  • Module components referenced in Blade views use . as directory separator in the namespace: livewire:mymodule::subdir.component-name.
  • LW4 ships Alpine.js 3.14 internally — do not include a separate Alpine bundle.

Credits

Inspired by:

License

MIT — http://opensource.org/licenses/MIT