Skip to content

Architecture

System Architecture

Wedissimo API is built as a modular monolith, combining the organizational benefits of microservices with the simplicity of a monolithic application.

Core Principles

1. Modular Monolith Pattern

Each feature is isolated into a module with its own:

  • Controllers and routes (API and web)
  • Models and migrations
  • Services and business logic
  • Livewire components and views
  • Permissions and navigation
  • Tests and documentation

Module Structure:

modules/DomainName/
├── Config/                    # Module configuration
├── Database/
│   ├── Migrations/           # Domain-specific migrations
│   └── Seeders/              # Permission seeders
├── Http/
│   ├── Controllers/          # API controllers
│   └── Resources/            # API resources
├── Livewire/                 # Livewire components
├── Models/                   # Domain models
├── Providers/                # ServiceProvider
├── Resources/views/          # Blade views
│   ├── livewire/            # Component views
│   └── partials/nav.blade.php # Admin navigation
├── Routes/
│   ├── api.php              # API routes (v1)
│   └── web.php              # Web routes (Livewire)
└── Tests/                    # Domain tests

Module Communication:

  • Eloquent relationships (cross-domain)
  • Service contracts (interfaces)
  • Laravel events (loosely coupled)
  • Direct service injection (when appropriate)

Key Modules:

  • Vendor (modules/Vendor/) - Vendor management and search
  • MagicLink (modules/MagicLink/) - Passwordless authentication
  • UserInvitation (modules/UserInvitation/) - User invitation system
  • Profile (modules/Profile/) - User profile management

See Module System Guide and Domain Documentation for details.

2. Service Layer Architecture

Request → Controller → Service → Model → Database

         API Resource → Response

Controllers handle HTTP concerns Services contain business logic Models manage data persistence Resources format API responses

3. UUID Primary Keys

All models use UUID primary keys for:

  • Security (non-sequential IDs)
  • Distributed system compatibility
  • Migration from WordPress
php
use Illuminate\Database\Eloquent\Concerns\HasUuids;

class YourModel extends Model
{
    use HasUuids;
}

Database Architecture

Multi-Database Setup

Primary (PostgreSQL)

  • Connection: pgsql
  • Purpose: All application data
  • Features: UUID support, full-text search, JSONB

Legacy (MySQL)

  • Connection: mysql_legacy
  • Purpose: WordPress migration source
  • Package: Corcel for WordPress ORM
  • Pattern: Maintains wp_id foreign keys
  • Connection: HTTP API
  • Purpose: Full-text search engine
  • Integration: Laravel Scout
  • Port: 8108 (internal), 1026 (local)

Migration Patterns

Always include all column attributes when modifying:

php
// WRONG - drops attributes
$table->string('password')->nullable()->change();

// CORRECT - preserves attributes
$table->string('password', 255)->nullable()->change();

Authentication Architecture

Multi-Strategy Authentication

┌─────────────┐
│   Request   │
└──────┬──────┘

       ├──────────────────────────────┐
       │                              │
┌──────▼────────┐            ┌────────▼────────┐
│  Session Auth │            │  Sanctum Token  │
│  (web guard)  │            │  (sanctum guard)│
└──────┬────────┘            └────────┬────────┘
       │                              │
       └──────────┬───────────────────┘

           ┌──────▼─────┐
           │ Magic Link │
           │  (signed)  │
           └────────────┘

User Roles (Spatie Permission)

  • super_admin - Full system access
  • wedissimo_admin - Platform administration
  • vendor - Service provider
  • couple - Wedding couple
  • user - Basic authenticated user

Search Architecture

Scout + Typesense Integration

Model Change → Observer → Queue Job → Scout → Typesense

User Search ← Controller ← Scout ← ← ← ← ← ← ← ←─┘

Searchable Models:

  • App\Models\Listing - Service listings (core)
  • Modules\Vendor\Models\Vendor - Vendor profiles (module)
  • App\Models\User - User search (core)
  • Modules\UserInvitation\Models\UserInvitation - Invitations (module)

Features:

  • Auto-sync on model changes
  • Queued index operations
  • Typo tolerance
  • Geo-location search
  • Faceted filtering

Admin Search Pages:

  • /admin/search/listings - Livewire listing search
  • /admin/search/vendors - Livewire vendor search (module-based)

See Search Documentation for details.

Media Architecture

Architecture decision

The rationale for using a shared polymorphic media system with unified collection names is described in ADR 0002: Polymorphic media with unified collection names.

Polymorphic Media System

php
// Central Media model
Media::class

// Polymorphic pivot
Mediable::class (media_id, mediable_id, mediable_type, collection, order)

// In any model
public function media()
{
    return $this->morphToMany(Media::class, 'mediable')
        ->withPivot('collection', 'order')
        ->orderBy('order');
}

Collections: avatar, gallery, documents, etc.

API Architecture

Versioning Strategy

Current version: v1

/api/v1/users
/api/v1/vendors
/api/v1/listings

Response Format

Always use Eloquent API Resources:

php
// Single resource
return new UserResource($user);

// Collection
return UserResource::collection($users);

// Paginated
return UserResource::collection(
    User::paginate(15)
);

Error Handling

Centralized in app/Exceptions/Handler.php:

  • API errors return JSON
  • Validation errors formatted consistently
  • Bugsnag integration for production

Event-Driven Architecture

Key Events

php
// User events
UserCreated::class
UserUpdated::class

// Vendor events
VendorApproved::class
VendorRejected::class

// Listing events
ListingPublished::class
ListingUnpublished::class

Listeners Pattern

php
// Sync listeners (immediate)
SendWelcomeEmail::class

// Queued listeners (background)
SyncToStripe::class
UpdateSearchIndex::class

Caching Strategy

Cache Layers

  1. Application Cache (Redis)

    • Session storage
    • Queue jobs
    • Rate limiting
  2. Model Cache (Query results)

    • Cached eloquent queries
    • Remember pattern
  3. HTTP Cache (Response caching)

    • API responses
    • Static content
  4. LaRecipe Cache (Documentation)

    • 60-minute cache
    • Markdown rendering

Queue Architecture

Queue Workers

bash
# Development
docker exec wedissimo-api php artisan queue:work

# Production (Supervisor)
[program:wedissimo-worker]
command=php artisan queue:work

Job Types

  • High Priority: Emails, notifications
  • Default: Search indexing, webhooks
  • Low Priority: Analytics, cleanups

Testing Architecture

Test Types

tests/
├── Feature/           # HTTP requests, DB interactions
├── Unit/              # Isolated logic, services
└── Pest.php          # Shared setup, helpers

Coverage Strategy

  • Controllers: Request/response validation
  • Services: Business logic coverage
  • Models: Relationships, scopes
  • Jobs: Queue processing

Target: 80% minimum coverage

Deployment Architecture

Docker Services

yaml
wedissimo-api:          # Laravel app
wedissimo-pg:           # PostgreSQL
wedissimo-typesense:    # Search engine
wedissimo-mailpit:      # Email testing
wedissimo-mysql:        # Legacy data

Environment Modes

  • Local: Docker Compose
  • Staging: Cloud Run + Cloud SQL
  • Production: Cloud Run + Cloud SQL + CDN

Performance Optimization

Database

  • Indexes on foreign keys
  • Composite indexes for common queries
  • Query optimization via Telescope
  • Queued sync operations
  • Cached search results
  • Geo-location indexing

Assets

  • Vite for bundling
  • CDN for static files
  • Image optimization (Intervention)

Caching

  • Query result caching
  • Route caching (production)
  • Config caching (production)

Security

Best Practices

  • Environment variables for secrets
  • CSRF protection (web routes)
  • Rate limiting (API routes)
  • SQL injection prevention (Eloquent)
  • XSS protection (Blade escaping)
  • Mass assignment protection

Authentication

  • Password hashing (bcrypt)
  • Token-based API auth
  • Signed URLs for magic links
  • Role-based permissions

Next Steps

Wedissimo API Documentation