refatrar/dynamic-dashboard-design
Dynamic Dashboard Design
Reusable Laravel package for building configurable dynamic dashboards with Inertia.js, Vue 3, and Chart.js.
Packagist: refatrar/dynamic-dashboard-design
Source: github.com/refatrar/dynamic-dashboard-design
1. Introduction
refatrar/dynamic-dashboard-design extracts the Dynamic Dashboard Design module into a standalone Laravel package. It includes:
- Backend controllers, services, models, migrations, and routes
- Vue dashboard designer and live dashboard pages
- Chart widgets (bar, line, pie, summary, table, and more)
- Whitelist-based database security
- Configurable routes, middleware, and allowed tables/columns
The host application keeps authentication, layouts, and shared UI components.
2. Features
- Drag-and-drop dashboard designer
- Grid layouts (1–5 columns)
- 21 chart/widget types
- Secure query builder (no arbitrary SQL by default)
- Configurable route prefix and middleware
- Publishable Vue assets
- Package-owned migrations for layouts, chart types, and saved designs
3. Requirements
- PHP 8.0+
- Laravel 9–13
- Inertia Laravel
^0.6.3/^1/^2/^3 - Vue 3+
- Node.js 18+ and npm
- MySQL, PostgreSQL, or SQLite
- Optional:
spatie/laravel-permissionwhen enabling dashboard permissions
Note: Host PHP/Laravel still apply their own floors (e.g. Laravel 11 needs PHP 8.2+). This package only requires PHP 8.0 so it can install on older apps.
Host application frontend dependencies
The published Vue assets expect these host dependencies:
@inertiajs/vue3(v1+) — chart preview uses Inertia HTTP helpers; prefer v2/v3 when possiblechart.jsvue-chartjs@iconify/vue(optional, used for icons)- Host UI components under
@/components/ui/*(Button, Input, Select, Sheet, Checkbox, Label, Spinner)
4. Laravel Compatibility
| Package version | PHP | Laravel | inertia-laravel |
|---|---|---|---|
| 1.0.5+ | ^8.0 | 9.x – 13.x | ^0.6.3 | ^1 | ^2 | ^3 |
| 1.0.4 | ^8.0 | 13.x | ^3.0 |
| 1.0.1 – 1.0.3 | ^8.3 | 13.x | ^3.0 |
5. Installation
Step 1 — Require from Packagist
Install via Composer (Packagist):
composer require refatrar/dynamic-dashboard-design
Or add it to your application composer.json:
{
"require": {
"refatrar/dynamic-dashboard-design": "^1.0"
}
}
Then run:
composer update refatrar/dynamic-dashboard-design
Expected result:
- Package installed under
vendor/refatrar/dynamic-dashboard-design - Service provider auto-discovered by Laravel
Optional — local path repository (package development only)
{
"repositories": [
{
"type": "path",
"url": "packages/dynamic-dashboard-design",
"options": {
"versions": {
"refatrar/dynamic-dashboard-design": "1.0.1"
}
}
}
],
"require": {
"refatrar/dynamic-dashboard-design": "^1.0"
}
}
Step 2 — Publish Configuration
php artisan vendor:publish --tag=dynamic-dashboard-design-config
Expected result: config/dynamic-dashboard-design.php is created.
Step 3 — Run Migrations
Migrations are auto-loaded by the package. You do not need to publish them unless you want to customize the files.
php artisan migrate
Expected result: grids, types, and dashboard_designs tables exist.
Optional (only if you want copies in your app):
php artisan vendor:publish --tag=dynamic-dashboard-design-migrations
Avoid publishing migrations and relying on auto-loaded package migrations on a fresh database if you do not want duplicate migration file paths. Prefer the auto-loaded package migrations for most apps.
Step 4 — Seed Layouts and Chart Types
Recommended:
php artisan dynamic-dashboard-design:seed
Or seed each class directly:
php artisan db:seed --class="Vendor\\DynamicDashboardDesign\\Database\\Seeders\\TypeSeeder"
php artisan db:seed --class="Vendor\\DynamicDashboardDesign\\Database\\Seeders\\GridSeeder"
If you get Target class [...] does not exist, rebuild Composer’s autoloader first:
composer dump-autoload
Then run the seed command again.
You can also call the seeders from database/seeders/DatabaseSeeder.php:
use Vendor\DynamicDashboardDesign\Database\Seeders\GridSeeder;
use Vendor\DynamicDashboardDesign\Database\Seeders\TypeSeeder;
public function run(): void
{
$this->call([
TypeSeeder::class,
GridSeeder::class,
]);
}
Note for Packagist 1.0.1: Seeders were only under
database/seedersand were not autoloaded. Upgrade to 1.0.2+ (seeders live undersrc/Database/Seeders), or runcomposer dump-autoloadafter ensuring the classes exist undervendor/refatrar/dynamic-dashboard-design/src/Database/Seeders/.
Step 5 — Configure Database Tables
Edit config/dynamic-dashboard-design.php:
'database' => [
'tables' => [
'users' => [
'columns' => ['id', 'name', 'email', 'created_at'],
'aggregates' => ['count', 'sum', 'avg', 'min', 'max'],
'group_by' => ['id', 'name', 'email', 'created_at'],
'filters' => ['id', 'name', 'email', 'created_at'],
'sort' => ['id', 'name', 'email', 'created_at'],
],
],
],
Step 6 — Configure Routes (optional)
'route' => [
'prefix' => 'dynamic-dashboard',
'middleware' => ['web', 'auth'],
'name_prefix' => 'dynamic-dashboard-design.',
],
Expected URLs:
- Dashboard:
/dynamic-dashboard - Designer:
/dynamic-dashboard/design
Step 7 — Install Frontend Dependencies
npm install chart.js vue-chartjs @iconify/vue
Step 8 — Publish Frontend Assets
php artisan vendor:publish --tag=dynamic-dashboard-design-assets --force
Expected result:
resources/js/pages/Dashboard.vueresources/js/pages/Dashboard/Design/Create.vueresources/js/components/Dashboard/**resources/js/lib/dashboard/chart-js.tsresources/js/lib/dashboard/chart-colors.tsresources/js/lib/dashboard/chart-data.tsresources/js/lib/dashboard/chart-options.tsresources/js/composables/useDashboardRoutes.tsresources/js/types/dashboard.ts
Chart components import
@/lib/dashboard/chart-js(and related helpers). After publishing, those files must live directly underresources/js/lib/dashboard/, not under a nesteddashboard/dashboard/folder.
Step 9 — Build Frontend
npm run build
For development:
npm run dev
Step 10 — Open Dynamic Dashboard
- Register or log in.
- Visit
/dynamic-dashboard - Open the designer at
/dynamic-dashboard/design
6. Configuration
Full config file: config/dynamic-dashboard-design.php
| Key | Purpose |
|---|---|
route.prefix |
URL prefix for all package routes |
route.middleware |
Middleware applied to package routes |
route.name_prefix |
Route name prefix for route() helpers |
database.connection |
DB connection for widget queries |
database.tables |
Whitelist of allowed tables/columns |
database.default_limit |
Max rows returned per query |
auth.guard |
Auth guard for ownership checks |
auth.users_table |
Users table for foreign keys |
features.custom_query |
Show Use custom query checkbox and allow SELECT SQL (default: false) |
permissions.enabled |
Gate view/create/edit with Spatie (or any $user->can()) permissions |
permissions.view |
Permission name for viewing dashboard/designer (default: dashboard.view) |
permissions.create |
Permission name for Save Design on new widgets (default: dashboard.create) |
permissions.edit |
Permission name for Save Design / chart Save on updates (default: dashboard.edit) |
inertia.dashboard_page |
Inertia page name for dashboard |
inertia.design_page |
Inertia page name for designer |
7. Database Table Configuration
Only tables listed in database.tables are exposed to the designer.
'users' => [
'columns' => ['id', 'name', 'email', 'created_at'],
'aggregates' => ['count', 'sum', 'avg', 'min', 'max'],
'group_by' => ['id', 'name', 'email', 'created_at'],
'filters' => ['id', 'name', 'email', 'created_at'],
'sort' => ['id', 'name', 'email', 'created_at'],
],
8. Route Configuration
php artisan route:list --path=dynamic-dashboard
Default route names:
dynamic-dashboard-design.dashboarddynamic-dashboard-design.design.indexdynamic-dashboard-design.design.storedynamic-dashboard-design.design.chart-data.tablesdynamic-dashboard-design.design.chart-data.columnsdynamic-dashboard-design.design.chart-data.preview
9. Frontend Configuration
Published Vue files read package URLs from Inertia shared props via:
import { useDashboardRoutes } from '@/composables/useDashboardRoutes';
const { dashboard, designIndex } = useDashboardRoutes();
Add navigation links in your host layout:
import { useDashboardRoutes } from '@/composables/useDashboardRoutes';
const { dashboard } = useDashboardRoutes();
const mainNavItems = [
{
title: 'Dashboard',
href: dashboard(),
},
];
Do not import @/routes/dynamic-dashboard-design. Those Wayfinder files are host-generated and are not part of the package.
10. Using the Dashboard
- Log in.
- Visit the dashboard URL.
- Saved widgets render with live data from configured tables.
11. Creating Dashboard Widgets
- Visit
/dynamic-dashboard/design. - Drag a grid layout into the dropzone.
- Configure a chart widget.
- Select allowed table/column values.
- Save the design.
12. Security
- Whitelist-only tables and columns
- No arbitrary SQL execution by default
- Structured preview endpoint instead of raw query execution
- Identifier validation for table/column names
- Allowed operator and aggregate validation
- SELECT-only query builder
- Query limits enforced server-side
13. Testing
Run host-application feature tests after installing the package:
php artisan test --compact tests/Feature/DashboardTest.php tests/Feature/ChartDataTest.php
14. Troubleshooting
Route Not Found
php artisan route:list --path=dynamic-dashboard
php artisan config:clear
Vite Manifest Not Found
npm install
npm run build
Configuration Not Found
php artisan vendor:publish --tag=dynamic-dashboard-design-config
php artisan config:clear
Seeder Class Not Found (1.0.1)
composer dump-autoload
php artisan dynamic-dashboard-design:seed
Or:
php artisan db:seed --class="Vendor\\DynamicDashboardDesign\\Database\\Seeders\\TypeSeeder"
php artisan db:seed --class="Vendor\\DynamicDashboardDesign\\Database\\Seeders\\GridSeeder"
Upgrade to 1.0.2+ for a permanent Packagist fix (seeders under src/Database/Seeders + dynamic-dashboard-design:seed command).
Vue Component Not Found / Chart Import Build Errors
If Vite fails with Could not load @/lib/dashboard/chart-js (or chart-colors, chart-data, chart-options), republish assets and confirm the helpers are flat:
php artisan vendor:publish --tag=dynamic-dashboard-design-assets --force
ls resources/js/lib/dashboard/
# expect: chart-js.ts chart-colors.ts chart-data.ts chart-options.ts types.ts
npm run build
If you still see resources/js/lib/dashboard/dashboard/chart-*.ts, move those files up one directory (or upgrade to package 1.0.2+ and republish).
No Tables in Designer
Add tables to config/dynamic-dashboard-design.php under database.tables.
15. Production Deployment
composer install --no-dev --optimize-autoloader
php artisan config:cache
php artisan route:cache
php artisan migrate --force
npm ci
npm run build
16. Updating the Package
composer update refatrar/dynamic-dashboard-design
php artisan vendor:publish --tag=dynamic-dashboard-design-config
php artisan vendor:publish --tag=dynamic-dashboard-design-assets --force
php artisan migrate
npm run build
Review CHANGELOG.md for breaking changes.
17. Uninstallation
- Remove
refatrar/dynamic-dashboard-designfromcomposer.json - Run
composer update - Delete published assets/config if desired
- Roll back migrations if needed
18. FAQ
Does the package include authentication?
No. Use Laravel Fortify, Breeze, or your existing auth.
Can I use /dashboard instead of /dynamic-dashboard?
Yes. Set route.prefix to dashboard in config.
Does it support custom SQL?
Yes, when enabled. Set this in config/dynamic-dashboard-design.php:
'features' => [
'custom_query' => true,
],
Then republish frontend assets and rebuild:
php artisan vendor:publish --tag=dynamic-dashboard-design-assets --force
npm run build
Open a chart in the designer — the Use custom query checkbox appears (bound with v-model). Only SELECT queries are allowed.
How do I use Spatie permissions on Save / Edit?
- Install Spatie:
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
-
Add
HasRolesto yourUsermodel. -
Create permissions (names must match config):
use Spatie\Permission\Models\Permission;
Permission::create(['name' => 'dashboard.view']);
Permission::create(['name' => 'dashboard.create']);
Permission::create(['name' => 'dashboard.edit']);
$user->givePermissionTo(['dashboard.view', 'dashboard.create', 'dashboard.edit']);
- Enable in
config/dynamic-dashboard-design.php:
'permissions' => [
'enabled' => true,
'view' => 'dashboard.view',
'create' => 'dashboard.create',
'edit' => 'dashboard.edit',
],
- Republish assets and rebuild. The Save Design and chart Save buttons only show when the user has the matching permission. Backend store/view routes are also authorized.
Does it require PrimeVue or Pinia?
No. The module uses Inertia Vue 3 and host UI components.
Related Packages
Complete dashboard widget system with stats, charts, and custom widgets. Display...
Laravel dashboard components with Vue 3, Inertia, and Bootstrap Vue Next
A dynamic, customizable dashboard package for Laravel with Vue 3, Inertia.js, an...
Lightning-fast Admin Dashboard & CRUD Generator for Laravel (VILT Stack)