Building Laravel Cloud: The Web Application

Building Laravel Cloud: The Web Application

Building Laravel Cloud: The Web Application

We continue our exploration into Laravel Cloud. This time, we will focus on the web application: how we built it, tested it, and the patterns we adopted to keep development fast and sane.

Laravel Cloud is a platform we built in under a year and launched in February 2025 to give developers the fastest path from pushing code to running Laravel apps in production. We were guided by a single North Star: from sign-in to a live URL in one minute or less. We got it to 30 seconds.

We previously covered how Laravel Cloud is architected, from our AWS account strategy to Kubernetes networking and traffic routing with Cloudflare.

Laravel Cloud Web App Stack

When it came to designing the web application for the platform, the app would naturally be built with Laravel. But the big decision was choosing how to build it.

We knew we’d eventually need a robust API. But should we go full single-page application (SPA)? Or would a more monolithic stack like TALL (Tailwind CSS, Alpine, Livewire, Laravel), VILT (Vue, Inertia, Laravel, and Tailwind CSS), or RILT (React, Inertia, Laravel, Tailwind CSS) make more sense?

We wanted a beautiful, engaging, and rich user interface. An interface that would feel alive and delight users. But we didn’t have a designer on the team when we kicked off the project. That pushed us toward a system with flexible out-of-the-box components so we could experiment with layout and page structure before custom designs landed.

We also had a strong feeling that the monolithic, single repository approach would allow us to move the most quickly toward our ambitious timeline to launch.

After some discussion, we settled on the RILT stack. There were a few reasons for it:

  • We needed a reactive frontend: logs updating in real-time, charts refreshing as new data is available, and deployments streaming events live. This type of functionality lent itself to a JavaScript-heavy UI.
  • We wanted a large component ecosystem. shadcn/ui and [Radix UI](https://www.radix-ui.com/
  • ) made React the obvious choice.

The Action Pattern

At first, we planned to ship Laravel Cloud with a command-line interface tool like Vapor, which clients would use to deploy their Laravel applications. To support it, we started building a JSON:API-compliant backend.

We didn’t want to duplicate logic between that API and the Inertia-powered frontend, so we adopted the Action (or Command) pattern.

Each action class typically does the following:

  • Executes a task (e.g., database update, third-party call)
  • Calls other actions
  • Logs activity
  • Broadcasts updates to the frontend

This separation gave us a clean way to reuse backend logic across both UI and API layers.

This approach was vindicated further when, eventually, we paused the CLI and decided to keep things simple for the launch and our users: deployment happens through the UI, source control, or webhooks. But the action pattern stayed, and we’ll use it when we revisit the CLI and future API tooling (like a Terraform provider) later on.

Still, hammering the scope here has proven to be a good choice for launch.

Fakes

The Cloud application interacts with our infrastructure and several third-party services like Cloudflare, Neon, and Upstash. This means working on the app locally requires us to be a little creative. We don’t want to make a real R2 bucket every time we test things locally, nor do we want to issue a real deployment.

To solve this, we bind interfaces to Laravel’s container. In production, they resolve to real service classes. Locally, they resolve to fakes that simulate production behavior: mock logs, deployment output, and source control repositories. It’s fast, safe, and works well for dev and test environments.

Testing

A solid test suite was something we would strive for, from the very first commits to the Laravel Cloud web application codebase. We knew the code would evolve rapidly and needed confidence to move quickly as we spike on features and as those features change to satisfy new requirements. A strong foundation of tests would allow us to make changes with confidence.

Test coverage currently sits at 99.2%. Although some may consider this a vanity metric, it really gives us the confidence to ship fast and acts as a gut check on pull requests, giving developers a nudge to check all the critical paths are covered.

We also enforce:

  • 100% type coverage
  • PHPStan at level 5
  • All of this runs in CI

And of course, we’re using Pest for all our testing.

Follow the Framework

These are the architecture decisions I found most interesting to share from the web application. Aside from that, the app looks intentionally like any other Laravel app.

Some advice you’ll hear regularly from the Laravel community is to “follow the framework conventions.” That’s exactly what we do, and it really pays off.

Onboarding for new team members is almost non-existent, contributing to the codebase is straightforward, and upgrades are trivial (test coverage helps here too) because there are no overrides in place fighting the framework.

Built for Developer Happiness

Laravel Cloud’s web app is modern and fast, but still grounded in Laravel’s core principles: convention, clarity, and developer happiness. We chose the RILT stack because it allowed us to move quickly and build the reactive UI we needed. With strong testing and architectural discipline, the app remains easy to work on even as it grows. More features are coming, including a full API and CLI tooling (watch this space), but for now, staying focused on simplicity has paid off. We built it simple so you can build simple: from sign-in to live in 30 seconds or less.

Keep reading

Stay connected with the latest Laravel news