Skip to content

Getting Started

A guided path from “I know PHP, new to Laravel” to a production-grade multi-tenant SaaS — built around one real domain: Bookline, an appointment-booking platform that barbershops, dental clinics and yoga studios use to sell their own time, on PHP 8.5 and Laravel 13.

Twenty-four steps. There’s no deadline on any of it — take a step in an evening or over two weeks. The order matters, the pace doesn’t.

  • Comfortable with PHP 8 — classes, interfaces, traits, enums, closures, Composer
  • Comfortable with SQL, a terminal, and git; Docker installed
  • New to Laravel, or you’ve only followed a tutorial

Not assumed: Eloquent, migrations, the service container, middleware, queues, Blade, Livewire, Inertia, Stripe.

If you are new to PHP itself, this will move too fast — learn the language first. Already shipping Laravel in production? Skim steps 0–4 as a checklist and start at step 5.

Bookline is one Laravel application serving many independent businesses. Each one signs up, gets its own address, configures what it sells and when, and takes bookings from its own customers — who never see any other business on the platform.

Three of them are used as the running examples all the way through the roadmap. They were picked because they disagree with each other on exactly the points that are hard to build:

  • the baseline

    Northside Barbershop

    3 barbers · 30-min cuts · walk-ins

    Per-staff schedules, a fast slot grid, and availability that must survive concurrent mobile requests.

  • the constraint

    Bright Smile Dental

    4 dentists · 45-min appointments · deposits

    Cleanup buffers after each service, deposit and refund logic, a cancellation window, and day-before reminders.

  • the exception

    Loft Yoga

    2 instructors · group classes · weekly timetable

    Capacity greater than one, recurring weekly rules, and DST — a Sunday 09:00 class must stay at 09:00 through the clock change.

Three tenants, one codebase: each one is deliberately chosen to break a rule the others do not.
The business What it sells What it forces you to handle
Northside Barbershop — 3 barbers 30-minute cuts, back to back, walk-ins between them Per-staff schedules, a slot grid, availability that must be fast because customers book on a phone in the street
Bright Smile Dental — 4 dentists, 2 hygienists 45-minute appointments, 15 minutes of cleanup after each, deposits to reduce no-shows Buffers after a service, deposits and refunds, a cancellation window, reminders the day before
Loft Yoga — 2 instructors Group classes with 12 places, a weekly timetable, some seasonal Capacity greater than one, recurring weekly rules, and DST — a Sunday 09:00 class stays at 09:00 through the clock change

Same code, same database, three businesses whose rules do not match. That is the whole exercise: one system, configured per tenant, and never a line of if ($tenant->name === …).

Other businesses in this shape, if you want to point your own version at one: driving schools, tattoo studios, physiotherapists, veterinary clinics, photography studios, private tutors, car service centres, nail bars, massage therapists, coworking meeting rooms. All of them sell time in slots, all of them lose money to no-shows, and all of them are somebody’s paying customer today.

Most Laravel tutorials build a blog or a todo list, then bolt on a queue and a cache as demos. You learn the syntax and none of the judgement. A booking platform sold to many businesses at once was chosen because the hard parts are unavoidable:

Reality of the domain Forces you to learn
Every business is a separate tenant sharing one database Tenant resolution, global scopes, tenant context in queues, cache and storage, and a test that proves no data crosses the line
Two customers can book the same 10:00 slot Transactions, row locking, Postgres exclusion constraints, and why a SELECT then INSERT is a bug
The business is in one timezone, the customer in another, and clocks shift twice a year Storing instants in UTC, rendering in tenant time, and the DST hours that happen twice or not at all
The business pays you monthly; their customers pay the business Subscriptions and dunning, webhook idempotency, per-tenant payment credentials, refunds
Reminders go out when nobody is on the site Queues, scheduled jobs, retries, failed-job handling, idempotent workers

You can’t fake a tenancy leak. Either your test proves tenant A’s query never returns tenant B’s row, or it doesn’t.

Every business that sells time runs on software shaped like this, and most of them are paying for it today. Building it once teaches you the shape.

Area Technology
Language / runtime PHP 8.5, Composer, strict types
Framework Laravel 13 — container, providers, middleware, events, policies
Persistence Eloquent, migrations, PostgreSQL 17, factories and seeders
Multi-tenancy Subdomain resolution, global scopes, tenant-aware cache / storage / queues, then stancl/tenancy for database-per-tenant
API Form requests, API resources, RFC 9457 problem details, versioning, Sanctum tokens
Auth Session auth, roles and policies, per-tenant membership, signed URLs
Money Laravel Cashier (Stripe) subscriptions, plan limits, dunning; encrypted per-tenant credentials; then Stripe Connect
Async Queues, Horizon, scheduled jobs, idempotent consumers, failed-job policy
Realtime Laravel Reverb — a slot disappearing while the customer is looking at it
Caching & scale Redis 8, cache keys under tenancy, N+1 elimination, index design for availability queries
Observability Structured logs, request and job correlation, slow-query and queue-depth signals
Admin frontend Blade + Livewire 4 + Tailwind 4 — a tenant back-office
Customer frontend Inertia 2 + React 19 + TypeScript — the public booking page
Quality Pest 4, Larastan, Laravel Pint, Rector, database-backed tests
AI workflow An AGENTS.md harness (v1→v4), a LEARN/BUILD mode contract, a portable code-reviewer prompt

Three parts. Read them in this order the first time, then jump back as needed.

Part What it is When you read it
Setup The AI harness — AGENTS.md, the make verify loop, the LEARN/BUILD mode contract — and a portable code-reviewer prompt. This is step 0. Once, before step 1. Configure it, then leave it.
Roadmap The 24 sequenced steps in five sections, plus an overview of locked decisions, the domain model, and the always-on quality guardrails. Skim the overview first. Work the steps in order.
Reference Per-step rubrics (acceptance criteria + anti-patterns), the AGENTS.md template, and a list of deliberate omissions. One rubric section per step. The rest, as questions come up.

The roadmap sections:

Section Steps Focus
Foundations 0–4 Tooling, harness, the Laravel mental model, Eloquent, the request contract, auth
Multi-Tenancy 5–8 Tenant resolution, scoping and the leak test, tenant context outside the request, the Livewire back-office
Booking and Availability 9–13 The availability engine, time correctness, the booking state machine, double-booking, read performance
Money and Async 14–18 Subscriptions, webhooks, per-tenant payment credentials, deposits and refunds, queues
Scale and Migration 19–23 The public booking page, the public API, Connect migration, database-per-tenant migration, deploy
  • Foundations0–4
    • 0Dev environment, quality gate, agent harness
    • 1Project skeleton and the Laravel mental model
    • 2Eloquent, migrations, and the schema
    • 3The request contract: validation, resources, error model
    • 4Auth I: session auth, roles, policies
  • Multi-Tenancy5–8
    • 5The tenant, and resolving it from the request
    • 6Scoping every query, and the leak test
    • 7Tenant context outside the request
    • 8The tenant back-office (Livewire)
  • Booking9–13
    • 9Working hours, staff schedules, and the availability engine
    • 10Time correctness: timezones, DST, recurrence
    • 11The booking flow and its state machine
    • 12Double-booking: locking vs an exclusion constraint
    • 13Read performance: N+1, eager loading, indexing
  • Money and Async14–18
    • 14Subscriptions: plans, trials, and plan limits
    • 15Webhooks: idempotency, retries, dunning
    • 16Per-tenant payment credentials
    • 17Deposits, refunds, and the no-show policy
    • 18Queues, Horizon, and work that must not be lost
  • Scale and Migration19–23
    • 19The public booking page (Inertia + React + Reverb)
    • 20The public API and token authentication
    • 21Payments migration: BYO keys → Stripe Connect
    • 22Tenancy migration: shared database → database per tenant
    • 23Observability and production deployment

LEARN the agent tutors, you decideBUILD the agent may generate

Five sections, 24 steps: four steps to know Laravel before touching tenancy, and the two migrations at the end are optional.

There is deliberately no implementation code in any of these documents. Handing you working code gives you the feeling of understanding, and you remember almost none of it later. The roadmap tells you what to build and how to prove it works; the building is yours.

Backend and tenancy — steps 0–18. Tooling → Laravel fundamentals → tenancy → availability and booking → money → async. Ends with a working multi-tenant SaaS that takes bookings and payments, driven from the Livewire back-office.

Public-facing and scale — steps 19–23. The Inertia booking page, the public API, and the two migrations: BYO payment keys → Stripe Connect, and shared database → database per tenant.

Two frontends is intentional. A tenant back-office is CRUD-heavy and internal; server-rendered Livewire is faster to build and cheaper to maintain, and that is a permanent choice, not a temporary step. The public booking page needs real client state — slot selection, a hold countdown, live availability — and earns the SPA. You learn session auth on one and token auth on the other, and why they differ.

Every step has the same parts. Once you know them you can skim to whichever one you need.

Part What it’s for
Story The user story driving the step. This is the goal — if you can’t demo it, you haven’t finished.
Mode LEARN or BUILD — whether an AI agent may write the implementation. See the mode contract.
Why now What this step depends on, and why it isn’t earlier or later. The ordering encodes dependencies you can’t see yet.
Concepts What you’re actually learning. This is the real point of the step; the code is just the vehicle.
Libraries What to add, and sometimes why that choice over the obvious alternative.
Expected outcome What you should have when the step is done — the pieces to build, and where useful a high-level project structure. The how is yours to work out.
Verification How you prove it’s done — see below.

Some steps also carry a Harness impact note: what to add to AGENTS.md afterwards.

The common failure of self-directed learning is that everything feels like it works. Five verification layers exist to prevent that:

Layer What it is
L1 — Gating test The acceptance test, ACC-NN. Unambiguous pass/fail. Write it, watch it fail, then make it pass.
L2 — Manual checks What a test can’t catch — reading an EXPLAIN plan, watching two browsers fight over one slot, changing your machine’s clock to a DST boundary.
L3 — AI code review The reviewer prompt, run by you at the end of every step.
L4 — Anti-patterns AP-NN-x: “you did it wrong if…”. This is where most of the real learning is — the mistakes that don’t show up on their own.
L5 — Automated guardrails CI, Larastan, Pint, the tenancy leak sweep, coverage. Continuous rather than per-step; listed in the Roadmap Overview.

The step’s Verification block vs. the Rubrics page

Section titled “The step’s Verification block vs. the Rubrics page”

These are two views of the same thing. Be clear which is which:

  • The Verification block ends every step. It’s the checklist you work through to close that step: the ACC-NN test to write, the L2 checks to run by hand, the AP-NN-x IDs to self-check against, and a one-line Done when. This is the thing you do.
  • The Rubrics page holds the full text of the ACC-NN criteria and the AP-NN-x anti-patterns that each step only names by ID. It lives in one place so the AI reviewer can be handed exactly one step’s section without seeing the others. This is a lookup — you read one section per step while working that step’s Verification block. You don’t “complete” it.
  1. Check the step’s Mode. LEARN → your agent tutors only. BUILD → it may generate.
  2. Read the step: story, why now, concepts.
  3. For tenancy, concurrency, time, and money steps — write the acceptance test first, watch it fail. (Steps 6, 7, 10, 12, 15, 17 especially.)
  4. Write the implementation until the test passes.
  5. Run the L2 manual checks.
  6. Self-check against the step’s AP-NN-* list in the rubrics.
  7. Submit to the reviewer with that step’s rubric section only.
  8. Fix findings, resubmit until PASS.
  9. Next step.

Expect to fail review the first time at steps 6, 10, and 12. That’s the design, not a setback.

Each step has a rubric in Reference → Rubrics — the objective pass/fail bar for that step, in two parts:

  • ACC-NN — one gating acceptance test. Objective, no judgement call. You write it, watch it fail, then make it pass.
  • AP-NN-x — named anti-patterns: mistakes that pass the tests but are still wrong (a queued job that runs without a tenant and writes rows to whichever tenant was last active; a cache key that serves Northside’s schedule to a Bright Smile patient).

Use it three times per step: read ACC-NN before you build and write that test first; self-check against every AP-NN-x once it passes; then paste only that step’s section into the reviewer. Never paste the whole file — it leaks later steps.

  1. Read this page to the end. The step format only makes sense once.
  2. Skim the Roadmap Overview — the locked decisions and the domain model. Don’t memorise it; know it’s there.
  3. Set up the agent harness. This is step 0. Setting up tooling before any domain code feels like procrastination; it’s what makes every later step fast.
  4. Set up the reviewer. Configure once, run at the end of every step. Works in a plain chat window — no repo access needed.
  5. Start step 1. A health endpoint and a config file. Small on purpose.

If you’re still tuning AGENTS.md after a couple of sessions, you’re procrastinating. Ship a minimal version and move on — it’s designed to grow.