Directory Structure
Open a freshly generated Laravel project and you'll see a couple dozen top-level folders and files.
None of it is arbitrary — every folder has one clear responsibility, and knowing what lives where means
you'll always know exactly which file to open for a given change. This page is a complete reference to
that layout, a closer look inside the app/ folder specifically, and a quick walk through
how a request actually flows through all of it.
1. Top-Level Folder Reference
| Folder | Purpose |
|---|---|
app/ | Your application's own code: Models, Http/Controllers, Providers, and more. This is where you'll spend most of your time. |
bootstrap/ | The bootstrapping/startup logic that wires up the framework on every request, plus a cache/ subfolder for framework-generated cache files. You'll rarely need to touch this directly. |
config/ | Every configuration file for the application, one per subsystem — app.php, database.php, mail.php, queue.php, and so on. Most values here simply read from .env. |
database/ | Database migrations/ (version-controlled schema changes), factories/ (fake model data for testing/seeding), and seeders/ (scripts that populate the database with initial data). |
public/ | The web server's document root. Only index.php (the single entry point for every request) and built/compiled front-end assets live here — nothing else in the project is web-accessible. |
resources/ | Blade view templates, raw uncompiled CSS/JS/Sass before a build step processes them, and language/localization files. |
routes/ | All route definitions, split by context: web.php, api.php, console.php, and channels.php. |
storage/ | Framework-generated logs, compiled Blade views, cache files, sessions, and any files your application stores (uploads, generated PDFs, etc.). Needs to be writable by the web server. |
tests/ | PHPUnit (or Pest) tests, typically split into Feature/ and Unit/ subfolders — covered in depth in the Testing lesson later in this track. |
2. Routes, Split by Purpose
The four files inside routes/ aren't just an arbitrary split — each one is loaded under
different default settings:
// routes/web.php - browser-facing routes, session + CSRF protection enabled
// routes/api.php - stateless routes, prefixed with /api automatically
// routes/console.php - closure-based Artisan commands
// routes/channels.php - broadcasting/WebSocket channel authorization
The Routing lessons that follow focus almost entirely on web.php, since that's where the
vast majority of a typical application's routes live.
3. A Closer Look Inside app/
app/ is where nearly all of your own code lives, and it's organized by role rather than by
feature:
| Subfolder | Contains |
|---|---|
app/Http/Controllers/ | Controller classes — the entry point that receives a routed request and decides what response to send back. Covered fully in the Controllers lesson. |
app/Models/ | Eloquent model classes, one per database table (typically) — User.php, Article.php, etc. Covered starting in the Eloquent ORM Basics lesson. |
app/Providers/ | Service provider classes, the central place where the framework and your own services get bootstrapped and registered. Covered in the Service Providers lesson. |
app/ yourself — app/Services/, app/Http/Requests/, app/Policies/, and similar. Laravel doesn't force a single "correct" structure beyond the defaults it ships with.4. The Request Lifecycle, at a High Level
Every single request to a Laravel application — whether it's a browser loading a page or an API client hitting an endpoint — passes through the same basic pipeline:
| Step | What happens |
|---|---|
| 1 | public/index.php receives the request — this is the single, universal entry point for the entire application. |
| 2 | The framework bootstraps itself: the service container is built, service providers are registered and booted (config, routing, database connections, etc. all become available). |
| 3 | The router matches the incoming URL and HTTP verb against the definitions in routes/web.php or routes/api.php. |
| 4 | Any middleware assigned to that route runs — authentication checks, CSRF verification, and so on (covered fully in the Middleware lesson). |
| 5 | The matched route's closure or controller method executes and builds a response — often by returning a Blade view or JSON data. |
| 6 | The response travels back out through the middleware, and is finally sent to the browser/client. |
5. Why public/ Being the Only Web Root Matters
It's worth calling out explicitly: your web server (Apache, Nginx, or Laravel's own dev server) should
only ever be configured to serve files from public/. Every other folder — app/,
config/, routes/, storage/, even your .env file —
sits outside the web root entirely.
.env file (with real database credentials) or your raw application source lived inside the web root the way it might on a naive hand-rolled PHP site, a misconfigured server could serve those files directly to anyone who requested them by URL. Because Laravel only exposes public/, that entire class of accidental-exposure bug is designed out of the framework from the start.routes/web.php.