Skip to main content
The SaaS Starter Vue project follows Laravel and Vue.js best practices with a clear separation between system-level (multi-tenant management) and tenant-level (individual customer) functionality.

Root Directory

saas-starter-vue/
├── app/                    # Laravel application code
├── bootstrap/              # Framework bootstrap files
├── config/                 # Configuration files
├── database/               # Migrations, seeders, and factories
├── public/                 # Public assets (compiled)
├── resources/              # Frontend source code
├── routes/                 # Route definitions
├── storage/                # Application storage
├── tests/                  # Test suites
├── vendor/                 # Composer dependencies
├── node_modules/           # NPM dependencies
├── composer.json           # PHP dependencies
├── package.json            # JavaScript dependencies
├── vite.config.ts          # Vite configuration
└── phpunit.xml             # PHPUnit configuration

Backend Structure (app/)

The Laravel backend is organized into logical namespaces that separate system and tenant concerns:

Key Directories

Custom action classes for specific business logic.
app/Actions/
└── Fortify/
    ├── CreateNewUser.php
    └── ResetUserPassword.php
These handle authentication flows like user registration and password resets.
Controllers organized by domain (System vs Tenant).
app/Http/Controllers/
├── Controller.php              # Base controller
├── System/                     # Multi-tenant management
│   ├── DashboardController.php
│   ├── PlanController.php
│   ├── TenantController.php
│   └── Settings/
│       ├── ProfileController.php
│       ├── PasswordController.php
│       └── TwoFactorAuthenticationController.php
└── Tenant/                     # Customer application
    ├── DashboardController.php
    └── Auth/
        └── LoginController.php
Eloquent models split by system and tenant databases.
app/Models/
├── System/                # Central database models
│   ├── User.php           # System administrators
│   ├── Tenant.php         # Customer organizations
│   ├── Plan.php           # Subscription plans
│   ├── Feature.php        # Plan features
│   ├── Subscription.php   # Tenant subscriptions
│   └── Setting.php        # System settings
└── Tenant/                # Tenant database models
    └── User.php           # Tenant users
Important: System models connect to the central database, while Tenant models live in isolated tenant databases.
Business logic and complex operations.
app/Services/
└── System/
    ├── TenantService.php       # Tenant lifecycle management
    ├── PlanService.php         # Plan operations
    ├── FeatureService.php      # Feature management
    └── SubscriptionService.php # Subscription handling

Example: System Model

The Tenant model demonstrates the multi-tenant architecture:
app/Models/System/Tenant.php
namespace App\Models\System;

use Stancl\Tenancy\Database\Models\Tenant as BaseTenant;
use Stancl\Tenancy\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\Concerns\HasDatabase;
use Stancl\Tenancy\Database\Concerns\HasDomains;

class Tenant extends BaseTenant implements TenantWithDatabase
{
    use HasDatabase, HasDomains;

    protected $casts = [
        'subscription_ends_at' => 'datetime',
        'trial_ends_at' => 'datetime',
        'canceled_at' => 'datetime',
    ];

    public function plan()
    {
        return $this->belongsTo(Plan::class);
    }

    public function subscriptions()
    {
        return $this->hasMany(Subscription::class);
    }
}

Frontend Structure (resources/js/)

The Vue.js frontend follows a component-based architecture with Inertia.js for server-side routing:
resources/js/
├── app.ts                  # Application entry point
├── ssr.ts                  # Server-side rendering entry
├── components/             # Reusable components
│   ├── ui/                 # shadcn-vue UI components
│   ├── AppShell.vue
│   ├── AppHeader.vue
│   ├── AppSidebar.vue
│   └── Breadcrumbs.vue
├── composables/            # Vue composables
│   ├── useAppearance.ts
│   ├── useCurrentUrl.ts
│   └── useTwoFactorAuth.ts
├── layouts/                # Page layouts
│   ├── AppLayout.vue       # System layout
│   ├── AuthLayout.vue      # Authentication pages
│   ├── TenantAppLayout.vue # Tenant layout
│   └── app/                # Layout components
├── lib/                    # Utility functions
├── pages/                  # Inertia page components
│   ├── system/             # System pages
│   │   ├── Dashboard.vue
│   │   ├── auth/
│   │   ├── plans/
│   │   ├── settings/
│   │   └── tenants/
│   └── tenant/             # Tenant pages
│       └── Dashboard.vue
└── types/                  # TypeScript definitions

Application Entry Point

resources/js/app.ts
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import type { DefineComponent } from 'vue';
import { createApp, h } from 'vue';
import '../css/app.css';
import { initializeTheme } from './composables/useAppearance';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
    title: (title) => (title ? `${title} - ${appName}` : appName),
    resolve: (name) =>
        resolvePageComponent(
            `./pages/${name}.vue`,
            import.meta.glob<DefineComponent>('./pages/**/*.vue'),
        ),
    setup({ el, App, props, plugin }) {
        createApp({ render: () => h(App, props) })
            .use(plugin)
            .mount(el);
    },
    progress: {
        color: '#4B5563',
    },
});

initializeTheme();

Routes Structure

The application uses multiple route files to organize different domains:
Main system routes (central domain):
routes/web.php
Route::domain(config('app.url_base'))->group(function () {
    // Dashboard
    Route::get('dashboard', [DashboardController::class, 'index'])
        ->middleware(['auth', 'verified'])
        ->name('dashboard');

    // Tenants Management
    Route::resource('tenants', TenantController::class)
        ->middleware(['auth', 'verified']);

    // Plans Management
    Route::resource('plans', PlanController::class)
        ->middleware(['auth', 'verified']);

    // Authentication Routes
    Route::prefix('auth')->group(function () {
        // Login, logout, registration, etc.
    });
});

Database Structure

The project uses a multi-database architecture:
database/
├── factories/              # Model factories for testing
├── migrations/             # Central database migrations
│   └── tenant/             # Tenant database migrations
├── seeders/
│   └── System/             # System database seeders
└── database.sqlite         # Default SQLite database
Multi-Tenancy Pattern: Each tenant gets their own isolated database. Central database stores tenant metadata, while tenant databases store customer-specific data.

Configuration Files

Key configuration files in the config/ directory:
FilePurpose
app.phpApplication settings, environment, timezone
database.phpDatabase connections and tenancy config
inertia.phpInertia.js middleware configuration
tenancy.phpMulti-tenancy settings
fortify.phpLaravel Fortify authentication
sanctum.phpAPI authentication

Key Files

composer.json

Defines PHP dependencies including Laravel 12, Inertia.js, Fortify, and Tenancy packages.

package.json

Frontend dependencies: Vue 3, Vite, Tailwind CSS 4, TypeScript, and UI libraries.

vite.config.ts

Vite build configuration with Vue, Tailwind, and Wayfinder plugins for type-safe routing.

tsconfig.json

TypeScript compiler configuration with path aliases and strict type checking.

Multi-Tenant Architecture

The project implements a database-per-tenant strategy:
  1. Central Database: Stores system users, tenants, plans, and subscriptions
  2. Tenant Databases: Isolated databases for each customer with their own users and data
  3. Domain-Based Routing: Tenants access via subdomains (e.g., customer.yoursaas.com)

Next Steps

Frontend Development

Learn about Vue 3, Inertia.js, and component development

Backend Development

Explore Laravel architecture, services, and multi-tenancy

Testing

Understand the testing strategy and running tests

Build docs developers (and LLMs) love