Open-Source Wikis

/

Laravel

/

Laravel application skeleton

/

Architecture

laravel/laravel

Architecture

The skeleton is a single-process PHP web application. There is no microservice topology, no separate worker fleet, no front-end framework — just a Laravel app that handles HTTP requests and Artisan commands through one bootstrap entry point.

Top-level layout

laravel_laravel/
├── app/                 # Application code (PSR-4: App\)
│   ├── Http/            # Controllers (empty)
│   ├── Models/          # Eloquent models (User.php)
│   └── Providers/       # Service providers (AppServiceProvider.php)
├── bootstrap/           # Framework bootstrap (app.php, providers.php, cache/)
├── config/              # Per-feature config files (app, auth, cache, ...)
├── database/            # Migrations, factories, seeders
├── public/              # Web server document root (index.php, .htaccess)
├── resources/           # Views (Blade), CSS, JS — compiled by Vite
├── routes/              # Route registration (web.php, console.php)
├── storage/             # Runtime artifacts (logs, sessions, views, cache)
├── tests/               # PHPUnit tests (Unit/, Feature/)
├── artisan              # CLI entry point
├── composer.json        # PHP deps + scripts (setup, dev, test)
├── package.json         # Node deps for Vite/Tailwind
├── phpunit.xml          # Test runner config + test env vars
└── vite.config.js       # Frontend build pipeline

The vendor/, node_modules/, and public/build/ directories are not committed; they are generated by composer install, npm install, and npm run build respectively (see .gitignore).

Request lifecycle

A typical HTTP request flows through four files in this repo and many more in the framework:

graph LR
    Browser -->|HTTP| Apache[Apache or PHP built-in server]
    Apache -->|rewrite| FrontController[public/index.php]
    FrontController -->|require| Bootstrap[bootstrap/app.php]
    Bootstrap -->|configure| Framework[Illuminate\Foundation\Application]
    Framework -->|dispatch| WebRoutes[routes/web.php]
    WebRoutes -->|render| View[resources/views/*.blade.php]
    View -->|HTML| Browser

Step by step:

  1. public/index.php captures the start time, checks for a maintenance file at storage/framework/maintenance.php, requires vendor/autoload.php, and then require_onces bootstrap/app.php to obtain the Illuminate\Foundation\Application instance. It calls $app->handleRequest(Request::capture()) and exits.
  2. bootstrap/app.php uses the Application::configure() fluent builder to point the framework at the route files, register a health check at /up, and accept (currently empty) middleware and exception closures. The commands: parameter wires routes/console.php for Artisan command definitions.
  3. routes/web.php registers GET / to view('welcome'). The framework matches the URL and runs the closure.
  4. resources/views/welcome.blade.php renders the response. Because the file is large (223 lines of inline HTML/Tailwind), Laravel compiles it once into storage/framework/views/<hash>.php and serves the compiled version on subsequent requests.

The CLI entry (artisan) follows the same bootstrap path but calls $app->handleCommand(new ArgvInput) instead of handleRequest().

Bootstrap composition

bootstrap/app.php is the central wiring file. The fluent calls compose into a configured Application:

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void { /* empty */ })
    ->withExceptions(function (Exceptions $exceptions): void { /* empty */ })
    ->create();

Two consequences of this design:

  • All middleware/exception customization happens here. There is no separate Kernel.php or Handler.php to edit (those existed in Laravel 10 and earlier).
  • The bootstrap/providers.php file is the only list of application service providers. It is read by the framework alongside any providers discovered in composer.json's extra.laravel block. Out of the box it contains exactly one entry: App\Providers\AppServiceProvider::class.

Persistence layout

The default environment variables (.env.example) point database, cache, queue, and sessions at the same SQLite file. The three migrations in database/migrations/ create every table the skeleton relies on:

Migration Tables created Used for
0001_01_01_000000_create_users_table.php users, password_reset_tokens, sessions Auth + database session driver
0001_01_01_000001_create_cache_table.php cache, cache_locks database cache store
0001_01_01_000002_create_jobs_table.php jobs, job_batches, failed_jobs database queue connection

A diagram of the default data dependencies:

graph TD
    User[App\Models\User]
    UsersTable[(users)]
    SessionsTable[(sessions)]
    CacheTable[(cache)]
    JobsTable[(jobs)]
    FailedJobsTable[(failed_jobs)]

    User -->|reads/writes| UsersTable
    Auth[Web auth guard] -->|reads| UsersTable
    Auth -->|writes session id| SessionsTable
    CacheFacade[Cache facade] -->|reads/writes| CacheTable
    Queue[Queue worker] -->|polls| JobsTable
    Queue -->|on failure| FailedJobsTable

See Systems → Database for the full schema and Reference → Data models for the User model definition.

Frontend pipeline

The frontend is deliberately tiny. resources/css/app.css (11 lines) imports Tailwind v4 and pulls in source paths for the framework's pagination views, the compiled Blade view cache, and any .blade.php/.js files under resources/. resources/js/app.js is a one-line stub (//). The Vite config (vite.config.js) registers the Laravel plugin for HMR, declares the two inputs, and pulls Instrument Sans (400/500/600) from Bunny via laravel-vite-plugin/fonts.

graph LR
    SourceCSS[resources/css/app.css] --> Vite
    SourceJS[resources/js/app.js] --> Vite
    Tailwind[tailwindcss vite plugin] --> Vite
    Bunny[bunny font plugin] --> Vite
    Vite --> Build[public/build/*]
    Build -->|@vite directive| Blade[Blade views]

In dev, npm run dev runs vite and writes a public/hot file so Blade's @vite directive serves from the dev server. In production, npm run build writes the manifest into public/build/ and Blade renders the hashed asset URLs.

Configuration sources

Configuration in this skeleton has two layers:

  1. PHP config files in config/. Ten files (app.php, auth.php, cache.php, database.php, filesystems.php, logging.php, mail.php, queue.php, services.php, session.php) define every setting the framework reads. They are pure PHP arrays that mostly delegate to env() calls.
  2. .env file. Values flow into the config arrays via env(). The committed .env.example is the template; composer setup (and the post-root-package-install hook) copy it to .env if no .env exists, then run php artisan key:generate.

The runtime resolution order is: .envenv() calls inside config/*.php → cached config (if php artisan config:cache was run) → service providers / framework code.

Test architecture

phpunit.xml overrides almost every persistence env var so tests don't touch local storage:

Env var Test value Purpose
APP_ENV testing Switches the app into test mode
DB_CONNECTION sqlite Use SQLite
DB_DATABASE :memory: In-memory database — no disk artifacts
CACHE_STORE array Cache lives in-process for a single test
SESSION_DRIVER array Same — sessions never persist
QUEUE_CONNECTION sync Jobs run inline; no worker required
MAIL_MAILER array Captured in memory for assertions
BROADCAST_CONNECTION null No broadcasting in tests
BCRYPT_ROUNDS 4 Faster hashing for fixture users
PULSE_ENABLED false Pre-empts Laravel Pulse if installed
TELESCOPE_ENABLED false Pre-empts Laravel Telescope if installed
NIGHTWATCH_ENABLED false Pre-empts Laravel Nightwatch if installed

The base test class is tests/TestCase.php, which extends Illuminate\Foundation\Testing\TestCase (so it boots a fresh Application per test). tests/Unit/ExampleTest.php extends PHPUnit's bare TestCase instead — i.e. unit tests do not boot the framework.

Where to make common changes

You want to… Edit…
Register a new web route routes/web.php
Add a Console (Artisan) command routes/console.php
Register a service binding app/Providers/AppServiceProvider.php (register() / boot())
Add a global middleware bootstrap/app.php's withMiddleware() closure
Customize exception rendering bootstrap/app.php's withExceptions() closure
Add a database table php artisan make:migration create_X_tabledatabase/migrations/
Add a model php artisan make:model Xapp/Models/
Tweak any config The matching config/*.php file (and add the env var to .env.example)

See How to contribute → Patterns and conventions for style and structural conventions used throughout the repo.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Laravel wiki | Factory