Documentation

Design Patterns

Repository pattern, service layer, singletons, facades, guard-based auth, theme overrides, and Inertia SPA

Last updated: Feb 09, 2026

Design Patterns

1. Repository Pattern (with Contracts)

Used in Shop (fully with interfaces), CMS, Sales, Reports, Marketing.

Contracts/ProductRepositoryInterface  ← bound in ServiceProvider
    ↓
Repositories/ProductRepository       ← concrete implementation
    ↓
Services/ProductService              ← injects interface, not implementation
Shop registers repositories as singletons in its ServiceProvider with explicit interface bindings:
$this->app->singleton(
    ProductRepositoryInterface::class,
    ProductRepository::class
);

2. Service Layer

Every package with business logic has a Services/ directory. Services encapsulate domain operations and are registered as singletons with constructor injection:

$this->app->singleton(CheckoutService::class, function ($app) {
    return new CheckoutService(
        $app->make(OrderRepositoryInterface::class)
    );
});

3. Singleton Container Bindings

Core services use vortex.* naming convention, bound via $this->app->singleton() with companion class bindings:

$this->app->singleton('vortex.theme', fn ($app) => new ThemeService());
$this->app->bind(ThemeService::class, fn ($app) => $app->make('vortex.theme'));

4. Facade Pattern

Core provides 4 facades (Extension, Hook, Menu, Setting) that resolve vortex.* singletons.

5. Extension/Plugin Architecture

Database-backed with filesystem discovery. Extensions follow an explicit lifecycle (discover → install → activate) and dynamically register their ServiceProviders.

6. Guard-Based Authentication

Separate admin and web guards with dedicated middleware layers. Admin routes require the is_admin middleware. API uses Sanctum bearer tokens.

7. Theme Override Pattern

Themes can override any storefront page by providing a Vue component at the same path. The Inertia resolver checks the theme path first.

8. Inertia SPA with Server-Side Routing

All page navigation goes through Laravel routes → controllers return Inertia::render() → Vue pages render client-side (or SSR). No client-side router — routing is fully server-driven.