Enterprise-grade framework for automatic component registration and management in Laravel and Livewire 3.
Powered by laravel-package-toolkit - Uses modern package toolkit for streamlined package registration and management.
- Installation
- Basic Usage
- Attributes
- Zones
- Cache
- SEO & Sitemap
- Breadcrumbs
- Navigation
- Blade Components
- Commands
composer require nyoncode/wire-mds# Use install command (recommended)
php artisan discovery:install
# Or manually
php artisan vendor:publish --tag=discovery::config
php artisan vendor:publish --tag=discovery::views<?php
namespace App\Livewire\Admin;
use NyonCode\WireMds\Attributes\Access;
use NyonCode\WireMds\Attributes\Navigation;
use NyonCode\WireMds\Attributes\Seo;
use NyonCode\WireMds\Attributes\WebRoute;
use NyonCode\WireMds\Traits\WithDiscoveryAccess;
use Livewire\Component;
#[WebRoute(
uri: '/dashboard',
name: 'admin.dashboard',
zone: 'admin'
)]
#[Navigation(
label: 'Dashboard',
icon: 'home',
sort: 10
)]
#[Access(permission: 'admin.dashboard.view')]
#[Seo(
title: 'Admin Dashboard',
description: 'Overview of administration'
)]
class Dashboard extends Component
{
use WithDiscoveryAccess;
public function render()
{
return view('livewire.admin.dashboard');
}
}Defines component routing.
#[WebRoute(
uri: '/products/{id}/{slug?}', // URI with parameters
name: 'products.show', // Route name (optional)
zone: 'frontend', // Zone (frontend, admin, customer)
middleware: ['verified'], // Additional middleware
where: ['id' => '[0-9]+'], // Regex constraints
methods: ['GET'], // HTTP methods
domain: null // Domain constraint
)]Metadata for UI navigation.
#[Navigation(
label: 'Users', // Display text
group: 'Settings.Users', // Hierarchical group (dot-separated)
icon: 'users', // Icon (Heroicons)
sort: 20, // Order (lower = higher)
hidden: false, // Hide from navigation
badge: 'NEW', // Badge text
badgeColor: 'bg-green-500', // Badge color
parent: 'admin.settings.index' // Parent route for breadcrumbs
)]Access control (Spatie Permission integration).
#[Access(
permission: 'users.view', // Required permission
// or
permission: ['users.view', 'admin.*'], // Multiple permissions (supports wildcards)
roles: ['admin', 'manager'], // Required roles
require: 'any', // 'any' or 'all'
guard: 'web', // Authentication guard
authenticated: true, // Requires authentication
redirectTo: 'login', // Redirect on unauthorized access
httpCode: 403 // HTTP code on denial
)]SEO and sitemap configuration.
#[Seo(
title: 'Product: {name}', // Title (supports placeholders)
description: 'View {name} details', // Description
noindex: false, // Disable indexing
nofollow: false, // Disable link following
sitemap_priority: 0.8, // Sitemap priority (0.0-1.0)
sitemap_frequency: 'weekly', // Update frequency
canonical: '/products/{slug}', // Canonical URL
og_image: '/images/product.png', // Open Graph image
og_type: 'product', // Open Graph type
twitter_card: 'summary_large_image' // Twitter Card type
)]Zones define URL prefixes, default middleware, and permissions.
'zones' => [
'admin' => [
'prefix' => '/admin',
'middleware' => ['web', 'auth', 'verified'],
'default_permission' => 'admin.*',
'default_role' => 'admin',
'layout' => 'layouts.admin',
],
'customer' => [
'prefix' => '/account',
'middleware' => ['web', 'auth'],
'default_permission' => 'customer.*',
'layout' => 'layouts.customer',
],
'frontend' => [
'prefix' => '',
'middleware' => ['web'],
'default_permission' => null, // Public
'layout' => 'layouts.app',
],
],If a component in the admin zone doesn't have #[Access] defined, it automatically gets:
permission: 'admin.*'authenticated: true
php artisan discovery:cachephp artisan discovery:clearCache is automatically generated when running:
php artisan optimizeAnd cleared when running:
php artisan optimize:clear<head>
<x-discovery::meta-tags />
</head>use NyonCode\WireMds\Facades\Seo;
public function mount(Product $product)
{
Seo::set('title', "Product: {$product->name}");
Seo::set('description', $product->description);
Seo::set('og_image', $product->image_url);
}# Generate sitemap.xml
php artisan discovery:sitemap
# Show URLs without generating
php artisan discovery:sitemap --show<x-discovery::breadcrumbs /><x-discovery::breadcrumbs :parameters="['name' => $product->name]" />// In AppServiceProvider
use NyonCode\WireMds\Services\BreadcrumbService;
public function boot()
{
app(BreadcrumbService::class)->registerResolver('products.show', function ($route, $params) {
return Product::find($params['product'])?->name ?? 'Product';
});
}<x-discovery::navigation zone="admin" /><x-discovery::navigation
zone="admin"
class="space-y-2"
item-class="px-4 py-2"
active-class="bg-blue-500 text-white"
:show-icons="true"
:show-badges="true"
/>use NyonCode\WireMds\Services\NavigationBuilder;
$navigation = app(NavigationBuilder::class)->forZone('admin');
$flatNav = app(NavigationBuilder::class)->flatForZone('admin');Renders all SEO meta tags.
Renders breadcrumb navigation.
Props:
parameters- Array for placeholder replacementseparator- Separator (default:/)class- CSS classes for container
Renders hierarchical navigation.
Props:
zone- Zone (required)class- CSS classesshow-icons- Show icons (default: true)show-badges- Show badges (default: true)
| Command | Description |
|---|---|
discovery:cache |
Generates cache manifest |
discovery:clear |
Clears cache |
discovery:list |
Shows all components |
discovery:sitemap |
Generates sitemap.xml |
# Filter by zone
php artisan discovery:list --zone=admin
# Public routes only
php artisan discovery:list --public
# Navigation items only
php artisan discovery:list --nav
# JSON output
php artisan discovery:list --jsonTrait automatically verifies permissions in mount() method.
use NyonCode\WireMds\Traits\WithDiscoveryAccess;
class MyComponent extends Component
{
use WithDiscoveryAccess;
// Permissions are checked automatically before mount()
}For components that need to provide additional metadata:
use NyonCode\WireMds\Contracts\Discoverable;
class MyComponent extends Component implements Discoverable
{
public static function discoveryMeta(): array
{
return [
'model' => User::class,
'supports_export' => true,
];
}
}use NyonCode\WireMds\Facades\Discovery;
$all = Discovery::all();
$component = Discovery::get('admin.dashboard');
$byUri = Discovery::findByUri('/admin/dashboard');
$adminRoutes = Discovery::getByZone('admin');
$publicRoutes = Discovery::getPublicRoutes();use NyonCode\WireMds\Facades\Seo;
Seo::set('title', 'Custom Title');
Seo::setMany(['title' => '...', 'description' => '...']);
$data = Seo::getSeoData();
$html = Seo::render();- Always use cache in production - Reflection is slow
- Define zones properly - Automatic normalization saves work
- Use
WithDiscoveryAccess- Consistent permission checking - Use wildcards carefully -
admin.*is powerful but dangerous - SEO for public pages - Sitemap contains only public routes
MIT