Tenanto
Production-ready Laravel Multi-Tenant SaaS Boilerplate
A comprehensive Laravel 12 boilerplate for building multi-tenant SaaS applications with built-in billing, team management, and admin panels.
Features
Multi-Tenancy
- Single Database Architecture - Efficient tenant isolation via
tenant_idcolumn - Subdomain & Custom Domain - Flexible tenant identification
- Automatic Scoping - Global scopes ensure data isolation
- Defense-in-Depth - Policy layer double-checks tenant ownership
Authentication & Authorization
- Laravel Breeze + Livewire - Modern authentication flows
- Email Verification - Required before access
- Role-Based Access Control - Owner, Admin, Member roles per tenant
- spatie/laravel-permission - Granular permission management
Billing & Subscriptions
- Stripe Integration - Via Laravel Cashier
- Subscription Plans - Basic, Pro, Enterprise tiers
- Feature Limits - Users, teams, projects per plan
- Trial Support - Configurable trial periods
- Webhook Handling - Automatic subscription lifecycle management
Admin Panels (FilamentPHP 3)
- System Admin (
/admin) - Tenant management, licenses, system users - Tenant Admin (
/app) - Complete per-tenant management:- Users - Invite users, manage roles (Owner/Admin/Member)
- Teams - Create teams, manage members
- Projects - Example CRUD module with tasks
- Billing - Subscription management, invoices
- Beautiful UI - Modern, responsive design
API
- Laravel Sanctum - Token-based authentication
- RESTful Design - Version-prefixed endpoints (
/api/v1/) - Rate Limiting - Tiered limits (30/60/120 req/min)
- Full CRUD - Projects, Tasks example implementation
Marketplace & Distribution
- Demo Automation - Auto-provisioned demo tenants with scheduled cleanup
- License Management - HMAC-validated license keys with tier-based features
- Update Notifications - Automatic new version detection
- Onboarding Wizard - Guided setup for new customers
- Support System - Extensible support ticket infrastructure
Internationalization (i18n)
- Translation Ready - Complete i18n infrastructure prepared
- Per-Tenant Locale - Each tenant can have their own language
- Automatic Detection - Browser Accept-Language header support
- 11 Translation Files - All application strings externalized
Developer Experience
- PHP 8.4 - Modern PHP features
- PHPStan Level 8 - Maximum type safety (0 errors)
- Laravel Pint - Consistent code style
- 1091 Tests - Comprehensive coverage (607 PHP unit/feature + 484 Playwright E2E)
- Docker Ready - One-command development setup (7 services)
- Laravel Horizon - Queue dashboard with job metrics and monitoring
Requirements
- PHP 8.4+
- PostgreSQL 16+
- Redis 7+
- Node.js 20+
- Docker Desktop (recommended)
Quick Start
1. Clone the Repository
# Replace with your repository URL
git clone https://your-git-host.com/your-org/tenanto.git
cd tenanto
2. Start Docker Environment
docker compose up -d
3. Install Dependencies
docker compose exec app composer install
docker compose exec app npm install && npm run build
4. Configure Environment
cp .env.example .env
docker compose exec app php artisan key:generate
Edit .env with your settings:
- Database credentials
- Stripe API keys
- Mail configuration
5. Run Migrations & Seed
docker compose exec app php artisan migrate --seed
6. Configure Local DNS
Add to your hosts file:
- Linux/macOS:
/etc/hosts - Windows:
C:\Windows\System32\drivers\etc\hosts
127.0.0.1 tenanto.local
127.0.0.1 admin.tenanto.local
127.0.0.1 demo.tenanto.local
7. Access the Application
| URL | Redirects To | Credentials |
|---|---|---|
| http://tenanto.local | Landing page | - |
| http://admin.tenanto.local | → /admin (System Admin) |
[email protected] / password |
| http://demo.tenanto.local | → /app (Tenant App) |
[email protected] / password |
| http://demo.tenanto.local/api/v1 | API | Bearer token |
| http://admin.tenanto.local/horizon | Queue Dashboard | System admin only |
| http://localhost:8025 | Email Testing | No auth required |
URL Structure:
- Main domain (
tenanto.local) - Marketing/landing page - Admin subdomain (
admin.tenanto.local) - Auto-redirects to Filament admin panel - Tenant subdomains (
{tenant}.tenanto.local) - Auto-redirects to Filament tenant app
Docker Services
The docker compose up -d command starts all 7 services automatically:
| Service | Container | Port | Description |
|---|---|---|---|
| app | tenanto_app | - | PHP-FPM 8.4 application server |
| nginx | tenanto_nginx | 80, 443 | Web server with SSL support |
| db | tenanto_db | 5432 | PostgreSQL 16 database |
| redis | tenanto_redis | 6379 | Cache, sessions, and queue broker |
| queue | tenanto_queue | - | Laravel Horizon (background jobs) |
| scheduler | tenanto_scheduler | - | Laravel task scheduler (cron jobs) |
| mailhog | tenanto_mailhog | 1025, 8025 | SMTP server + Email testing UI |
Service Details
- Queue Worker - Processes background jobs: emails, Stripe webhooks, notifications
- Scheduler - Runs cron jobs: demo tenant cleanup, subscription reminders
- Mailhog - Catches all outgoing emails at http://localhost:8025
Useful Commands
# View all container logs
docker compose logs -f
# View specific service logs
docker compose logs -f queue
# Restart all services
docker compose restart
# Rebuild containers (after Dockerfile changes)
docker compose up -d --build
# Stop all services
docker compose down
Project Structure
app/
├── Domain/ # Business logic (DDD-lite)
│ ├── Authorization/ # Roles & permissions
│ ├── Billing/ # Stripe/subscription logic
│ ├── Demo/ # Demo tenant automation
│ ├── ExampleApp/ # Demo module (Projects/Tasks)
│ ├── Licensing/ # License key management
│ ├── Onboarding/ # Customer onboarding wizard
│ ├── Support/ # Support ticket system
│ ├── Tenancy/ # Multi-tenant core
│ └── Updates/ # Version update notifications
├── Filament/
│ ├── Admin/ # System admin panel
│ └── Tenant/ # Per-tenant admin panel
└── Http/
├── Controllers/Api/ # API controllers
└── Middleware/ # Tenant middleware
docs/
├── api.md # API documentation
├── authorization.md # Roles & permissions guide
├── backup-restore.md # Backup & recovery guide
├── deployment.md # Deployment guide
├── example-module.md # Module development guide
├── filament.md # FilamentPHP customization
├── i18n.md # Internationalization guide
├── launch-checklist.md # Production launch checklist
├── marketplace.md # Marketplace features documentation
├── multi-tenancy.md # Multi-tenancy architecture
├── performance.md # Performance optimization
└── security.md # Security checklist
tests/
├── Feature/ # Integration tests
└── Unit/ # Unit tests
e2e/ # Playwright E2E tests (484 tests)
├── admin/ # Admin panel tests
├── auth/ # Authentication tests
├── api/ # API tests
├── errors/ # Error page tests
├── helpers/ # Test utilities (auth, api)
├── isolation/ # Tenant isolation tests
├── navigation/ # Navigation tests
├── onboarding/ # Onboarding wizard tests
└── tenant/ # Tenant panel tests
Getting Started for Developers
This section guides you through customizing Tenanto for your own SaaS product.
Step 1: Remove the Example Module
The ExampleApp module (Projects/Tasks) is included as a reference implementation. To remove it:
# Remove domain files
rm -rf app/Domain/ExampleApp
# Remove Filament resources
rm -rf app/Filament/Tenant/Resources/ProjectResource
rm -rf app/Filament/Tenant/Resources/TaskResource
rm -rf app/Filament/Tenant/Resources/ProjectResource.php
rm -rf app/Filament/Tenant/Resources/TaskResource.php
rm -rf app/Filament/Tenant/Widgets/ProjectStatsWidget.php
rm -rf app/Filament/Tenant/Widgets/TaskStatsWidget.php
# Remove API controllers
rm app/Http/Controllers/Api/V1/ProjectController.php
rm app/Http/Controllers/Api/V1/TaskController.php
# Remove migrations
rm database/migrations/*_create_projects_table.php
rm database/migrations/*_create_tasks_table.php
# Remove factories, seeders, and tests
rm database/factories/ProjectFactory.php
rm database/factories/TaskFactory.php
rm database/seeders/ExampleAppSeeder.php
rm -rf tests/Feature/Api/Project*
rm -rf tests/Feature/Api/Task*
# Clean up API routes
# Edit routes/api.php and remove Project/Task routes
Step 2: Create Your Own Module
Follow this pattern to add tenant-scoped models:
// 1. Create Model with BelongsToTenant trait
namespace App\Domain\YourModule\Models;
use App\Domain\Tenancy\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
class YourModel extends Model
{
use BelongsToTenant;
protected $fillable = ['tenant_id', 'name', ...];
}
// 2. Create Migration with tenant_id
Schema::create('your_models', function (Blueprint $table) {
$table->id();
$table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->timestamps();
// Always add composite index for tenant queries
$table->index(['tenant_id', 'created_at']);
});
// 3. Create Policy for authorization
namespace App\Policies;
use App\Domain\YourModule\Models\YourModel;
use App\Models\User;
class YourModelPolicy
{
public function viewAny(User $user): bool
{
return $user->can('view your-models');
}
public function view(User $user, YourModel $model): bool
{
// Defense-in-depth: verify tenant ownership
return $user->tenant_id === $model->tenant_id;
}
}
// 4. Create Filament Resource
// See docs/example-module.md for complete guide
Step 3: Configure Your Plans
Edit config/billing.php to define your subscription tiers:
'plans' => [
'starter' => [
'name' => 'Starter',
'stripe_price_id' => env('STRIPE_PRICE_STARTER'),
'features' => [
'users' => 3,
'your_feature' => 100,
'premium_feature' => false,
],
],
// Add more plans...
],
Step 4: Customize Branding
- Application Name: Edit
APP_NAMEin.env - Colors: Edit
app/Filament/Tenant/TenantPanelProvider.php - Logo: Add to
public/images/and update panel config - Email Templates: Edit
resources/views/mail/
Step 5: Set Up Stripe
- Create products/prices in Stripe Dashboard
- Copy Price IDs to
.env:STRIPE_PRICE_STARTER=price_xxx STRIPE_PRICE_PROFESSIONAL=price_yyy - Set up webhooks pointing to
/stripe/webhook - Test with Stripe CLI:
stripe listen --forward-to localhost/stripe/webhook
Key Concepts
| Concept | Location | Purpose |
|---|---|---|
BelongsToTenant |
app/Domain/Tenancy/Traits/ |
Auto-scopes models to current tenant |
TenantScope |
app/Domain/Tenancy/Scopes/ |
Filters all queries by tenant_id |
TenantMiddleware |
app/Http/Middleware/ |
Resolves tenant from subdomain/domain |
PlanFeatureService |
app/Domain/Billing/Services/ |
Checks feature limits per plan |
For detailed documentation, see docs/example-module.md.
Development Commands
# Start development environment
make up
# Run tests
make test
# Run static analysis
make lint
# Fix code style
make fix
# Fresh database with seeds
make db-fresh
# Enter app container
make shell
See Makefile for all available commands.
API Overview
Base URL: /api/v1/
Authentication
POST /api/v1/auth/login
POST /api/v1/auth/logout
GET /api/v1/auth/me
Resources
# Projects
GET /api/v1/projects
POST /api/v1/projects
GET /api/v1/projects/{id}
PUT /api/v1/projects/{id}
DELETE /api/v1/projects/{id}
POST /api/v1/projects/{id}/archive
POST /api/v1/projects/{id}/unarchive
# Tasks
GET /api/v1/projects/{id}/tasks
POST /api/v1/projects/{id}/tasks
GET /api/v1/tasks/{id}
PUT /api/v1/tasks/{id}
DELETE /api/v1/tasks/{id}
POST /api/v1/tasks/{id}/complete
See docs/api.md for complete API documentation.
Testing
PHP Tests (PHPUnit/Pest)
# Run all PHP tests
docker compose exec app php artisan test
# Run with coverage
docker compose exec app php artisan test --coverage
# Run specific group
docker compose exec app php artisan test --group=tenant-isolation
Test Groups:
tenant-isolation- Critical security testsapi- API endpoint testsbilling- Subscription/payment tests
E2E Tests (Playwright)
# Install Playwright
npm install
npx playwright install chromium
# Run all E2E tests
npx playwright test --project=chromium
# Run specific test file
npx playwright test e2e/auth/login.spec.ts
# Run with UI mode
npx playwright test --ui
# View HTML report
npx playwright show-report
E2E Test Coverage (484 tests):
| Category | Tests | Description |
|---|---|---|
| Auth | 95 | Login, logout, register, password reset, email verification |
| Admin Panel | 76 | Tenants, users, licenses, dashboard |
| Tenant Panel | 101 | Projects, tasks, teams, users, profile, billing |
| API | 22 | Authentication, CRUD operations |
| Isolation | 44 | Tenant isolation, permission enforcement |
| Navigation | 26 | Route testing, menu visibility |
| Onboarding | 23 | Wizard flow |
| Errors | 23 | Error pages (403, 404, 500) |
Configuration: playwright.config.ts
Configuration
Environment Variables
Key variables in .env:
# Tenancy
TENANCY_MODE=subdomain
TENANT_CENTRAL_DOMAINS=tenanto.local,admin.tenanto.local
# Billing
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
# Plans
STRIPE_PRICE_BASIC=price_xxx
STRIPE_PRICE_PRO=price_xxx
STRIPE_PRICE_ENTERPRISE=price_xxx
See .env.example for all options with documentation.
Subscription Plans
Configure in config/billing.php:
'plans' => [
'basic' => [
'name' => 'Basic',
'stripe_price_id' => env('STRIPE_PRICE_BASIC'),
'features' => [
'users' => 5,
'teams' => 1,
'projects' => 10,
],
],
// ...
],
Deployment
See docs/deployment.md for production deployment instructions.
Quick Checklist
- Set
APP_ENV=production - Set
APP_DEBUG=false - Configure production database
- Set up Stripe production keys
- Configure mail provider
- Set up SSL certificates
- Configure queue workers
- Set up monitoring (Sentry, etc.)
Security
Built-in Protections
- Tenant Isolation - Global scopes + policy checks
- CSRF Protection - All forms protected
- Rate Limiting - API and auth endpoints
- XSS Prevention - Blade auto-escaping
- SQL Injection - Eloquent prepared statements
- Secure Headers - CSP, X-Frame-Options, etc.
See docs/security.md for security checklist.
Documentation
| Document | Description |
|---|---|
| Multi-Tenancy Architecture | Tenant isolation and scoping |
| Authorization & Permissions | RBAC and policies |
| FilamentPHP Customization | Admin panel configuration |
| API Documentation | Complete API reference |
| Deployment Guide | Production deployment |
| Security Checklist | Security best practices |
| Example Module | Building custom modules |
| Performance Guide | Optimization strategies |
| i18n Guide | Internationalization setup |
| Backup & Restore | Backup strategies and recovery |
| Launch Checklist | Production launch checklist |
| Marketplace Features | Demo, licensing, onboarding, updates |
| CodeCanyon Guide | Buyer guide for CodeCanyon purchases |
| Troubleshooting | Common issues and solutions |
| UPGRADING | Version upgrade instructions |
| CHANGELOG | Version history and changes |
| Third-Party Licenses | Dependency licenses |
Tech Stack
| Component | Technology |
|---|---|
| Framework | Laravel 12 |
| PHP Version | 8.4 |
| Admin Panel | FilamentPHP 3 |
| Frontend | Livewire 3 + Tailwind CSS |
| Database | PostgreSQL 16 |
| Cache/Queue | Redis 7 |
| API Auth | Laravel Sanctum |
| Billing | Laravel Cashier (Stripe) |
| Permissions | spatie/laravel-permission |
| Testing | PHPUnit + Pest (607 tests) |
| E2E Testing | Playwright (484 tests) |
| Static Analysis | PHPStan Level 8 |
| Code Style | Laravel Pint |
Support
Email: [email protected]
Response Time:
- General questions: 24-48 hours
- Bug reports: 24-48 hours (critical bugs prioritized)
- Feature requests: Reviewed weekly
What's Included:
- Installation assistance
- Bug fixes
- Documentation clarification
- Configuration questions
What's Not Included:
- Custom feature development
- Third-party integration setup
- Server/hosting configuration
- Code customization beyond documentation
For CodeCanyon buyers, support is provided according to Envato's Item Support Policy.
See docs/codecanyon.md for CodeCanyon-specific information. See docs/troubleshooting.md for common issues and solutions.
License
Tenanto is commercial software. See LICENSE for details.
Third-party dependencies are licensed under MIT, BSD-3-Clause, and Apache-2.0 licenses. See THIRD_PARTY_LICENSES.md for details.
Credits
Built with: