Architecture & Stack

A pure Laravel CMS with a Blade/Livewire admin and a JSON-driven content engine — no Filament, no third-party CMS packages.

Technology stack

LayerTechnology
LanguagePHP 8.2+
FrameworkLaravel 12
DatabaseMySQL 8.0 (UUID PKs, JSON columns, functional indexes)
Admin UIBlade + Livewire 3 + Alpine.js
StylingTailwind CSS 3
Rich textTipTap editor
Cache & queueRedis
AuthLaravel session (admin) + Sanctum / scoped API keys (API)
Build toolingVite

Repository layout

app/
  Models/                   — Eloquent models (UUID-keyed)
  Http/
    Controllers/Admin/      — Admin panel controllers
    Controllers/Api/V1/     — REST API controllers
    Requests/               — Form request validators
    Middleware/             — api.auth, api.cors, api.rate, api.scope, api.log
  Observers/                — Activity logging, revision creation
  Traits/HasUuid.php        — UUID primary keys
database/
  migrations/               — Schema definitions
  seeders/                  — Default roles, settings, admin user
resources/
  views/admin/              — Blade templates per module
  views/layouts/            — Shared admin layout
routes/
  web.php                   — Admin panel routes (admin.* names)
  api.php                   — REST API v1 (prefix: /api/v1)

Architectural decisions

Everything is a content model

Pages, menus, headers, footers, and other site primitives are not separate modules. They are content models the editor defines through the admin. Combined with components and (planned) dynamic zones, this keeps the codebase small while letting site editors model arbitrary content.

ImplicationThere is no pages, menus, or blocks table. Look for those concepts under content_models and content_entries.

UUID primary keys everywhere

All tables use 36-character UUID primary keys via the HasUuid trait. Route model binding uses UUIDs directly, which makes URLs opaque and prevents enumeration.

JSON-first field storage

Each entry stores its field values in a single data JSON column, governed by the entry's content model. This avoids per-model schema migrations and lets editors evolve their models without DBA involvement. A MySQL 8 functional index on data->>'$.title' keeps listing queries fast.

Separate admin and API surfaces

routes/web.php contains all admin functionality behind session auth and the admin.auth middleware. routes/api.php is the public-facing REST surface, all under /api/v1, gated by API keys with scopes (read, write, delete), per-key rate limits, and CORS origin allowlists.

Observers handle audit trail & revisions

Every meaningful save flows through a model observer. Observers write to activity_logs and create content_revisions rows so editors can diff and restore prior versions of any entry.

Routing conventions

Naming & file conventions

Development commands

# Full dev stack (server, queue, logs, Vite)
composer dev

# Just the PHP server
php artisan serve

# Reset DB with seeds
php artisan migrate:fresh --seed

# Vite asset watcher
npm run dev

# Run tests
composer test