If you've ever started a SaaS side project in Laravel, you probably know the pattern:
- Set up auth
- Figure out multi-tenancy
- Wire Stripe
- Build an admin panel
- Add teams and roles
- Then start your actual product
That foundation alone can eat weeks — sometimes months.
I kept rebuilding the same stack, so I open-sourced it: Laravel Tenant Kit — a production-minded starter for multi-tenant SaaS apps on Laravel 13.
v1.2.0 adds OAuth (Google/GitHub), Sanctum API tokens, and SaaS analytics widgets in Filament.
What you get out of the box
| Area | Included |
|---|---|
| Tenancy | Database-per-tenant (Stancl), subdomain + custom domains |
| Auth | Laravel Breeze on central app and each workspace |
| Teams | Roles (owner/admin/member), email invitations |
| Billing | Stripe subscriptions via Laravel Cashier |
| Admin | Filament 5 panel at /admin
|
| API | Sanctum tokens — central platform + per-tenant API |
| OAuth | Google & GitHub social login |
| Analytics | Workspace growth chart, subscriptions, user stats |
| i18n | English + Arabic with RTL support |
| DevOps | Docker Compose, GitHub Actions CI, 35 PHPUnit tests, 36-point smoke script |
Stack: Laravel 13 · PHP 8.4 · Filament 5 · Stancl Tenancy · Spatie Permission · Cashier · Breeze · Tailwind · Vite · MySQL or PostgreSQL · Redis
How tenancy works
One Laravel codebase serves everyone. Each workspace gets its own database — no duplicated deployments, no mixed tenant data.
yourdomain.com → central app (signup, billing, admin)
acme.yourdomain.com → Acme workspace → database: tenant{id}
demo.yourdomain.com → Demo workspace → database: tenant{id}
When someone visits acme.yourdomain.com, Laravel resolves the workspace from the URL and switches the DB connection automatically.
When a workspace is created:
- A record is stored in central
tenants+domainstables - A new database
tenant{id}is provisioned - Tenant migrations and role seeds run
- The owner lands on their subdomain
You can also provision from CLI:
php artisan tenant:provision acme "Acme Corp" --admin=boss@acme.com --password=secret
Quick start (local)
git clone https://github.com/mohammedelkarsh/laravel-tenant-kit.git
cd laravel-tenant-kit
composer install && npm install
cp .env.example .env && php artisan key:generate
php artisan migrate && php artisan db:seed && npm run build
Add to your hosts file:
127.0.0.1 laravel-tenant-kit.test
127.0.0.1 demo.laravel-tenant-kit.test
Open http://laravel-tenant-kit.test — done.
Default credentials after seed:
| Context | URL | Password | |
|---|---|---|---|
| Platform admin | /admin |
admin@laravel-tenant-kit.test |
password |
| Demo workspace | http://demo.laravel-tenant-kit.test |
demo@demo.test |
password |
Verify everything with the smoke test:
php scripts/system-test.php # expect 36/36 passed
Docker alternative
No local PHP/MySQL setup? One script runs the full stack (PHP, Nginx, MySQL, Redis):
# Windows
.\scripts\docker-setup.ps1
# macOS / Linux
chmod +x scripts/docker-setup.sh && ./scripts/docker-setup.sh
Then open http://laravel-tenant-kit.test:8080 (port 8080 with Docker).
Screenshots
Landing page:
Filament admin with SaaS analytics:
Tenant dashboard & billing:
Demo walkthrough (GIF):
API & OAuth (v1.2.0)
Sanctum powers token-based APIs for headless clients and mobile apps.
Central platform token:
curl -X POST http://laravel-tenant-kit.test/api/auth/token \
-H "Content-Type: application/json" \
-d '{"email":"admin@laravel-tenant-kit.test","password":"password","device_name":"cli"}'
Tenant API (subdomain resolves tenancy):
curl -X POST http://demo.laravel-tenant-kit.test/api/auth/token \
-H "Content-Type: application/json" \
-d '{"email":"demo@demo.test","password":"password","device_name":"mobile"}'
Full API reference: docs/api.md on GitHub
OAuth: add Google/GitHub credentials to .env — login buttons appear on the central login page automatically.
Why database-per-tenant?
Single-database multi-tenancy is simpler to start, but database-per-tenant gives you:
- Strong isolation (harder to leak data across customers)
- Easier per-customer backups and exports
- Clear scaling story (move heavy tenants to dedicated DBs later)
Stancl Tenancy handles connection switching, cache/filesystem/queue bootstrappers, and Redis key prefixing so tenant data stays isolated in production.
PostgreSQL and Redis are both supported — switch via .env or use the Docker profiles in docs/docker.md.
Production notes
For real deployments you'll need:
yourdomain.com → A record → server IP
*.yourdomain.com → A record → server IP (wildcard — required)
The DB user needs CREATE DATABASE permission. VPS + Laravel Forge/Ploi works well; shared hosting is usually too limited for wildcard DNS and dynamic DB creation.
php artisan migrate --force && php artisan config:cache && php artisan view:cache
Who is this for?
- Developers building B2B SaaS on Laravel
- Teams that want Stripe + admin + tenancy before product features
- Products targeting English and Arabic markets (RTL included)
- Anyone tired of copying the same boilerplate for every new idea
What's next
Roadmap item on the horizon: usage-based billing meters.
Issues and PRs are welcome on GitHub.
Links
- Repository: github.com/mohammedelkarsh/laravel-tenant-kit
- v1.2.0 release notes: GitHub Releases
- Docker guide: docs/docker.md
- API docs: docs/api.md
If this saves you time, a ⭐ on GitHub helps other Laravel developers find it.
MIT licensed. Built for developers who want to ship product features on day one — not rebuild infrastructure for the third time.





Top comments (1)
GitHub repo: github.com/mohammedelkarsh/laravel...
Happy to answer questions about tenancy setup, Stripe, or deployment. Feedback welcome!