artflow-studio / tenancy
Enterprise-grade Laravel multi-tenancy package built on stancl/tenancy with Livewire 3 integration, enhanced CLI tools, and comprehensive monitoring.
Installs: 68
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
pkg:composer/artflow-studio/tenancy
Requires
- php: >=8.0
 - laravel/framework: >=10.0
 - predis/predis: *
 - stancl/tenancy: >=3.9.1
 
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
 - phpstan/phpstan: ^1.10
 - phpunit/phpunit: ^10.0|^11.0
 
- dev-main / 2.0.x-dev
 - 0.7.7.0
 - 0.7.6.9
 - 0.7.6.8
 - 0.7.6.7
 - 0.7.6.6
 - 0.7.6.5
 - 0.7.6.4
 - 0.7.6.3
 - 0.7.6.2
 - 0.7.6.1
 - 0.7.6.0
 - 0.7.5.1
 - 0.7.5.0
 - 0.7.4.0
 - 0.7.3.0
 - 0.7.2.3
 - 0.7.2.2
 - 0.7.2.1
 - 0.7.2.0
 - 0.7.1.5
 - 0.7.1.4
 - 0.7.1.3
 - 0.7.1.2
 - 0.7.1.1
 - 0.7.1.0
 - 0.7.0.9
 - 0.7.0.1
 - 0.7.0.0
 - 0.6.9.3
 - 0.6.9.2
 - 0.6.9.1
 - 0.6.9
 - 0.6.8
 - 0.6.7
 - 0.6.6
 - 0.6.5
 - 0.6.1
 - 0.6.0
 - v0.5.4
 - v0.5.3
 - v0.5.2
 - 0.5.1
 - 0.4.5
 - 0.4.1
 - 0.3.0
 - 0.2.0
 - 0.1.0
 
This package is auto-updated.
Last update: 2025-11-03 16:25:56 UTC
README
Enterprise-grade Laravel multi-tenancy with PWA, SEO, and Asset Management
π Complete Multi-Tenancy Solution - Built on stancl/tenancy with advanced features including isolated assets, SEO management, PWA support, performance monitoring, and universal routing capabilities.
β‘ Quick Start
Installation
# Install the package (includes stancl/tenancy automatically) composer require artflow-studio/tenancy # Run the installation (sets up everything including asset directories) php artisan af-tenancy:install # Create your first tenant php artisan tenant:create
Basic Usage
// routes/web.php // Central domain routes (your main app/admin) Route::middleware(['central.web'])->group(function () { Route::get('/', [HomeController::class, 'index']); Route::get('admin', [AdminController::class, 'index']); }); // Tenant routes (with full asset and SEO support) Route::middleware(['tenant.web'])->group(function () { Route::get('/', function () { return view('tenant.home'); }); // Tenant assets are automatically scoped // Use helper functions in your views: // <img src="{{ tenant_asset('images/logo.png') }}" /> // <link href="{{ tenant_pwa_asset('manifest.json') }}" /> });
π― Core Features
π’ Multi-Tenancy Foundation
- Complete Database Isolation - Each tenant gets its own database using stancl/tenancy
 - Domain-Based Routing - Automatic tenant detection and switching
 - Universal Middleware - Routes that work on both central and tenant domains
 - Custom Database Names - User-defined database names with validation
 - FastPanel Integration - Seamless integration with FastPanel control panel
 
π Asset Management (NEW!)
- Isolated Asset Storage - Each tenant has separate folders for assets, documents, and media
 - Exact Domain Naming - Folders use exact domain names (e.g., 
tenant1.local, nottenant1_local) - Automatic Directory Creation - Asset structure created automatically during tenant setup
 - Helper Functions - Easy-to-use functions for generating asset URLs
 - 5 Asset Categories: assets, pwa, seo, documents, media
 
Folder Structure:
storage/app/public/tenants/
βββ tenant1.local/
β   βββ assets/      # General assets (images, fonts, CSS, JS)
β   βββ pwa/         # PWA files (manifest, icons, service worker)
β   βββ seo/         # SEO files (robots.txt, sitemap.xml)
β   βββ documents/   # Documents and downloads
β   βββ media/       # Media files (videos, audio)
π SEO Management (NEW!)
- Per-Tenant robots.txt - Customizable robots.txt for each tenant
 - Dynamic Sitemaps - Auto-generated and manageable sitemaps
 - SEO Commands - Enable, disable, and manage SEO via CLI
 - Public Routes - Automatic 
/robots.txtand/sitemap.xmlserving - Disallow Paths - Customizable paths to disallow in robots.txt
 
Quick SEO Setup:
# Enable SEO for a tenant php artisan tenant:seo:enable --tenant=uuid # Check SEO status php artisan tenant:seo:status --all # Add URL to sitemap php artisan tenant:seo:generate-sitemap --add-url=/products --priority=0.9
π± PWA Support (NEW!)
- Per-Tenant PWA - Each tenant can have its own Progressive Web App
 - Manifest Generation - Auto-generate PWA manifests
 - Service Worker Support - Custom service workers per tenant
 - Icon Management - Separate PWA icons for each tenant
 - Offline Support - Full PWA capabilities per tenant
 
β‘ Performance & Monitoring
- Real-time Monitoring - Built-in performance metrics and health checks
 - High Performance - Optimized for 1000+ concurrent tenants (18ms avg response)
 - Comprehensive Testing - 15+ specialized testing commands
 - Stress Testing - Production-ready load testing
 - System Validation - Automated health checks and repair tools
 
π§ Developer Experience
- Zero Configuration - Works out of the box with sensible defaults
 - Rich CLI Commands - 40+ artisan commands for tenant management
 - Helper Functions - 7 global helper functions for assets and paths
 - One-Command Setup - Install everything with 
php artisan af-tenancy:install - Comprehensive Docs - Detailed documentation for all features
 
π¦ Installation & Setup
Requirements
- PHP 8.1 or higher
 - Laravel 10.x or 11.x or 12.x
 - MySQL 5.7+ or MariaDB 10.3+
 - Composer 2.x
 
Step-by-Step Installation
- Install via Composer
 
composer require artflow-studio/tenancy
- Run Installation Command
 
php artisan af-tenancy:install
This will:
- β Publish configuration files
 - β Install stancl/tenancy
 - β Create directory structure (including asset directories)
 - β Add tenant_template to database config
 - β Run migrations
 - β Create README files for tenant directories
 
- Configure Database Root Credentials (Optional but Recommended)
 
Add to your .env file:
DB_ROOT_USERNAME=root DB_ROOT_PASSWORD=your_mysql_root_password
Why Root Credentials?
- Automatically creates tenant databases
 - Grants proper MySQL privileges
 - Enables FastPanel integration
 - Required for production deployments
 
- Create Storage Symlink (If not done already)
 
php artisan storage:link
- Configure Domains
 
Edit config/artflow-tenancy.php:
'central_domains' => [ 'localhost', 'yourdomain.com', ],
π Usage Guide
Creating Tenants
Interactive Mode:
php artisan tenant:create
Command Line:
php artisan tenant:create \
    --name="Acme Corp" \
    --domain="acme.local" \
    --database="custom_db_name" \
    --homepage
Asset Management
Helper Functions in Blade:
{{-- General assets --}} <img src="{{ tenant_asset('images/logo.png') }}" alt="Logo"> <link href="{{ tenant_asset('css/custom.css') }}" rel="stylesheet"> {{-- PWA assets --}} <link rel="manifest" href="{{ tenant_pwa_asset('manifest.json') }}"> <link rel="icon" href="{{ tenant_pwa_asset('icons/icon-192.png') }}"> {{-- SEO assets --}} <link rel="sitemap" href="{{ tenant_seo_asset('sitemap.xml') }}"> {{-- Get paths in PHP --}} @php $assetsPath = tenant_path('assets'); $pwaPath = tenant_path('pwa'); @endphp
Upload Assets:
use ArtflowStudio\Tenancy\Services\TenantAssetService; $service = app(TenantAssetService::class); // Upload a file $service->uploadAsset($tenant, $uploadedFile, 'assets'); // Copy a file $service->copyAsset($tenant, '/path/to/file.png', 'assets/images/file.png'); // Get folder size $sizes = $service->getTenantFolderSize($tenant); // Returns: ['total' => 1024000, 'assets' => 500000, 'pwa' => 200000, ...]
SEO Management
Enable SEO:
# Single tenant php artisan tenant:seo:enable --tenant=uuid # All tenants php artisan tenant:seo:enable --all # With custom disallow paths php artisan tenant:seo:enable --tenant=uuid --disallow=/private,/admin
Manage Sitemap:
# Add URLs to sitemap php artisan tenant:seo:generate-sitemap \ --tenant=uuid \ --add-url=/products \ --priority=0.9 \ --changefreq=daily # Regenerate sitemap php artisan tenant:seo:generate-sitemap --all
Check SEO Status:
php artisan tenant:seo:status --all
Disable SEO:
php artisan tenant:seo:disable --tenant=uuid --remove-files
PWA Management
# Enable PWA for tenant php artisan tenant:pwa:enable --tenant=uuid # Disable PWA php artisan tenant:pwa:disable --tenant=uuid # Check PWA status php artisan tenant:pwa:status --all
Tenant Management Commands
# List all tenants php artisan tenant:list # Update tenant php artisan tenant:update {tenant_id} # Delete tenant php artisan tenant:delete {tenant_id} # Run migrations for all tenants php artisan tenants:migrate # Run seeders for specific tenant php artisan tenants:seed --tenant=uuid
π Helper Functions Reference
Asset Helpers
tenant_asset($path, $tenant = null)
Generate URL for tenant-specific asset.
tenant_asset('images/logo.png') // Output: http://yourdomain.com/storage/tenants/tenant1.local/assets/images/logo.png
tenant_pwa_asset($path, $tenant = null)
Generate URL for PWA asset.
tenant_pwa_asset('manifest.json') // Output: http://yourdomain.com/storage/tenants/tenant1.local/pwa/manifest.json
tenant_seo_asset($path, $tenant = null)
Generate URL for SEO asset.
tenant_seo_asset('robots.txt') // Output: http://yourdomain.com/storage/tenants/tenant1.local/seo/robots.txt
Path Helpers
tenant_path($subfolder = '', $tenant = null)
Get absolute storage path for tenant.
tenant_path('assets') // Output: /var/www/storage/app/public/tenants/tenant1.local/assets
tenant_url($subfolder = '', $tenant = null)
Get public URL path for tenant.
tenant_url('pwa') // Output: /storage/tenants/tenant1.local/pwa
Tenant Helpers
current_tenant()
Get current tenant instance.
$tenant = current_tenant(); if ($tenant) { echo $tenant->name; }
tenant_config($key = null, $default = null)
Get tenant configuration.
$seoConfig = tenant_config('seo_config');
tenant_domain_folder($domain)
Get folder name for domain (exact domain, lowercased).
tenant_domain_folder('Tenant1.Local') // Output: tenant1.local
π Detailed Documentation
- SEO Management - Complete SEO guide with robots.txt and sitemap management
 - PWA Support - Progressive Web App implementation per tenant
 - Asset Management - File uploads, storage, and organization
 - Commands Reference - All available artisan commands
 - API Reference - REST API for tenant management
 - Testing Guide - Performance and load testing
 - Troubleshooting - Common issues and solutions
 
π― Advanced Features
Custom Middleware
// Apply tenant-specific middleware Route::middleware(['tenant.web', 'tenant.auth'])->group(function () { Route::get('/dashboard', [DashboardController::class, 'index']); });
Database Operations
// Execute queries in tenant context Tenant::find($tenantId)->run(function () { User::create(['name' => 'John Doe']); }); // Switch database connection tenancy()->initialize($tenant);
Events and Listeners
// Listen to tenant events Event::listen(TenantCreated::class, function ($event) { // Send welcome email // Setup default data // Initialize services });
π§ͺ Testing & Validation
Run Tests
# Run all tests php artisan af-tenancy:test-all # Specific tests php artisan tenant:test:performance php artisan tenant:test:stress php artisan tenant:test:database
Health Checks
# System health check php artisan tenant:health-check # Performance monitoring php artisan tenant:performance:monitor
π Security
- Database credentials are encrypted
 - Tenant isolation is enforced at database level
 - CSRF protection on all forms
 - SQL injection prevention via Eloquent ORM
 - Rate limiting on API endpoints
 
π€ Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
π License
The ArtFlow Studio Tenancy Package is open-sourced software licensed under the MIT license.
π Credits
Built on top of the excellent stancl/tenancy package.
π Support
- Documentation: Full Docs
 - Issues: GitHub Issues
 - Email: support@artflowstudio.com
 
πΊοΈ Roadmap
- Multi-database support (PostgreSQL, SQLite)
 - Tenant billing and subscription management
 - Advanced analytics and reporting
 - Tenant backup and restore
 - Tenant cloning and templating
 - Advanced caching strategies
 - GraphQL API support
 
Made with β€οΈ by ArtFlow Studio