Elements vs Laravel

Markdown

Laravel is an open-source web app framework written in PHP. Taylor Otwell created it and first released it in 2011, and Laravel, the venture-backed company he founded, maintains it. The framework ships libraries for the parts of an app: Eloquent for database models, migrations, Blade for templates, queues and a scheduler for background work, broadcasting for realtime events, mail and notifications, and testing with Pest or PHPUnit. For the browser, its starter kits use Livewire, which makes pages interactive from PHP, or Inertia with React, Vue or Svelte, and Vite builds the frontend assets. The framework is free. Around it, the company sells paid services: Laravel Cloud for managed hosting, Forge for provisioning and deploying to your own servers, Vapor for serverless hosting on AWS (closed to new signups), Nova for admin panels, and Nightwatch for monitoring. Laravel 13, released in March 2026, requires PHP 8.3.

Elements is an integrated app environment for building web apps, built for people and their agents: a project server that runs while you work, a package installer, a test runner, a bundled Postgres database with migrations, and a deploy command for any Ubuntu server you reach over SSH. It ships with a default framework that just works, and the framework covers routing, server rendering, typed server functions, sessions, file uploads, realtime data, background jobs and email. Its pages are written in Elements HTML: standard HTML with reactive expressions. Elements apps are written in TypeScript and run on Node.js. Elements charges for that tooling, per machine, and meters nothing (pricing).

Laravel hands you a framework and leaves the assembly to you. A new app is PHP on the server, Blade for views, and React, Vue, Svelte or Livewire for the browser, installed by two package managers and run as three processes, with php artisan migrate, php artisan test and a Reverb server each started on its own, and a paid Cloud or Forge plan, or a pipeline you build, to ship it. Every seam between those parts is a place the app breaks for a person or an agent: a PHP type the TypeScript checker cannot see, a Livewire method named in a string, a test nobody ran before the deploy. Elements starts with elements start, which runs the app, the job worker and the project server against the bundled Postgres. It stays close to the metal, with HTML, CSS, TypeScript and SQL, and its vocabulary is the bare minimum: app.route(), session.login(), sql(), @rpc and tests. The project server checks code, templates, migrations and tests together as you work, and one command deploys the result to your servers.

Elements Laravel 13
Languages in one app TypeScript on the server and in the browser PHP on the server, Blade templates, and JavaScript or TypeScript for the browser
Build errors One build reports type checking, tests, migrations and program analysis, as you work PHP checks types when the code runs; static analysis, tests and migrations are separate commands
What runs in development A project server that runs while you work, builds in milliseconds and serves the app composer run dev starts the PHP server, a queue worker and the Vite server
Development database Postgres, bundled, as in production SQLite by default
Default data access Plain SQL through sql(), safe from SQL injection by construction Eloquent ORM
Migrations SQL files, applied when you save one PHP files, applied with php artisan migrate
Server call from the browser A typed function call (@rpc), checked at build time A route and a controller, or a Livewire method named in a template string
Realtime Built into the app server: changes appear at once for the user who made them and in every open browser A Reverb server or a hosted service, a queue worker, and the Echo library in the browser
Tests Part of the build, and a gate on every deploy php artisan test, or a CI workflow you set up
Deploy Peer to peer over SSH, changed files only, often under a second after the first deploy Cloud builds an image on every deploy; Forge's zero-downtime deploys cover one server
Business model Sells the system you build with, per machine; nothing is metered A venture-backed company gives the framework away and sells Cloud, Forge, Nightwatch and Nova around it

Laravel Runs Your App. Elements Also Runs Your Build.

A new Laravel app starts with composer run dev, which starts Laravel's local development server, queue worker, and Vite development server. Those are three processes, each doing its own job: PHP serves requests, the worker runs queued jobs, and Vite rebuilds the browser code. None of them type checks the code you saved, runs the tests it affects, or applies a migration you just wrote. Migrating and testing are separate commands, each started by hand.

Elements runs a project server: a server that runs while you work. It holds the build graph, meaning every file and what depends on it, and the build state in memory. On every save, the build state is updated almost instantly, because the server redoes only what the change touched. A single-file save often builds and hot reloads in a few milliseconds, swapping the new code into the running app without a restart (build). A build in Elements is where every build error is reported: type checking, tests, migrations and program analysis, done in milliseconds and queried in microseconds. The project server also runs the job worker, so there is nothing else to start (patterns).

A new Laravel app develops against SQLite: its .env points at SQLite, and the installer creates the file. To develop against the MySQL or Postgres you deploy, you install the server yourself, create the database and run the migrations. The docs suggest DBngin or Herd Pro, a paid annual license from the same company. Elements bundles Postgres and runs it as a background service on your machine from the first command, so the database you develop against is Postgres, as in production (database).

For an Agent, the Value Is in Correction

An agent writing code needs two things: context for its first attempt, and correction, meaning it finds out what it got wrong the moment it gets it wrong. Laravel puts its effort into the first. Its documentation calls Laravel "An Agent Ready Framework" on convention: "When you ask an AI agent to add a controller, it knows exactly where to place it." A convention tells an agent where a file goes, not what it means, and the same guide "strongly" recommends that newcomers read about the service container and facades, two layers of Laravel's own design. Laravel Boost adds an MCP server with "over 15 specialized tools," including querying the database, searching the Laravel documentation, reading browser logs and running code through Tinker: more context for the first attempt.

Then comes the ecosystem. Laravel's site lists fourteen first-party packages, from Cashier and Horizon to Sanctum, Socialite, Scout and Pulse, beside the paid products, and each starter kit brings a component library of its own: shadcn/ui, shadcn-vue, shadcn-svelte or Flux UI. A library earns its place when it does something an agent cannot write quickly from standards, and Elements is a shortcut of exactly that kind. That surface is far smaller than an ecosystem. An agent would rather write HTML and CSS than learn one of four component libraries, a few lines of TypeScript beat another dependency, and every package past that surface is one more API to look up, one more config to keep in agreement and one more seam to get wrong.

Correction is also where Laravel leaves the agent on its own. PHP checks type declarations "at call time", so a wrong argument surfaces when that line runs, Boost's tools read errors from logs after the code has run, and static analysis such as Larastan is a separate package you install and run.

On a line from an agent writing machine code, which nobody does, to a package that does subtraction, the right amount of framework sits at the plumbing every app needs. Elements ships that plumbing: routing, typed server calls with @rpc, sessions, sql() and the database driver. Past that plumbing comes a point of diminishing returns, where each further abstraction costs an agent more to learn and get right than it saves. So Elements stops there and keeps abstractions to a minimum. A page is HTML and CSS, in Elements HTML. A call from the browser to the server is a TypeScript function marked @rpc (rpc). Data is SQL, through sql() (database/sql). The vocabulary on top is app.route(), session.login(), sql(), @rpc and tests, and elements create scaffolds pages, templates, migrations, jobs and email the way php artisan make does (cli), with code inside that every agent already writes.

Its engineering goes into correction. The framework and its build were designed together, so one coherent system checks every page, function, sql() call, test and migration the agent writes. An agent runs elements build -json and gets its answer in microseconds, because the project server already holds the build state (build). A failing test, a bad migration, a template reading a field that does not exist or a wrong argument type comes back as a diagnostic, with a file and a line, before the change is released. Your terminal, your editor and any number of agents connect to the same project server and see the same build state, and one build loop orders their changes so two agents never build over each other.

Server Calls Are Typed Function Calls

Every web app has a boundary between code that runs on the server, where the database and secrets live, and code that runs in the browser. Laravel crosses it in two ways. With Inertia, a controller action behind a route passes props to a page component, and the component calls routes back. With Livewire, a template names a PHP method in an attribute such as wire:submit="save", and clicking the Save button "sends both values to the server and calls save()." In both, the connection between the browser and the server is a url or a string, resolved when the request runs.

Elements crosses the boundary with @rpc functions. An @rpc is a server function, marked with an @rpc tag in its doc comment, that the browser calls directly with typed parameters and a typed return value (rpc). An event handler calls it like any other function, so a renamed parameter or a changed return type breaks the build at every caller. The compiler turns the browser call into a network request and keeps the function body, and everything it depends on, out of the browser bundle.

The compiler also guards the boundary. Calling server-only code such as sql, tx, session.login or email from code the browser can reach is a compile error at the call site, so a query or a secret cannot reach the browser by accident.

SQL Is the Default, and a Migration Applies When You Save It

Laravel reaches its database through Eloquent, an ORM that maps each table to a PHP model class, with a query builder and raw SQL available beneath it. Migrations are PHP classes that describe schema changes through Laravel's schema builder, applied by running php artisan migrate.

Elements makes SQL the default, because SQL is the query language every agent and every database tool already speaks. sql() takes a plain SQL template, and the build turns every ${value} in it into a separate query parameter at compile time, so an interpolated value cannot inject SQL (database/sql).

Migrations are SQL too, and saving one applies it (migrations). Edit an applied migration in development and Elements rolls it back and applies the new version. Pending migrations run together in one Postgres transaction, against the test database first, so a batch applies in full or not at all.

One Reactive HTML Language, Rendered on the Server and Live in the Browser

A Laravel app does not have a frontend until you pick one of two models. Livewire keeps the page in Blade and PHP, and each action on a component is a request to the server, which runs the PHP method and sends back the updated HTML. Behavior that should happen without a round trip, beyond Livewire's own directives, is written in Alpine.js, a second JavaScript layer in the template. Inertia hands the page to React, Vue or Svelte, which means a second framework, written in JavaScript or TypeScript, for everything the user sees.

In Elements, one template runs on the server and in the browser. Elements HTML is standard HTML plus four attributes (e:if, e:switch, e:for and group) and reactive expressions in braces (html). A page renders fully on the server, so search engines and first-time visitors get the complete page. The browser then picks up the server-rendered page and makes it interactive, and when data changes, the runtime updates only the elements that depend on it. An input bound to a field updates the field as the user types, with no round trip, and event handlers are TypeScript in the same file as the markup, calling @rpc functions directly.

Realtime Is Part of the App Server

Realtime features push changes to browsers that are already open, such as a new message or an edited row. Laravel does this with broadcasting, which takes three pieces beyond the app. Broadcasts go out through queued jobs, so the docs say to "configure and run a queue worker" first. The WebSocket server is Reverb, started as its own process with php artisan reverb:start, or a hosted service such as Pusher or Ably. The browser subscribes with Echo, a JavaScript library installed from npm. Each broadcast is an event class in PHP, and the browser code that receives it is written separately.

Elements builds realtime into the app server, on Postgres notifications (LISTEN/NOTIFY): every app server listens and forwards each message to its connected browsers as it arrives (channel). There is no separate WebSocket server, no queue in the path and no client library to install. On top of channels sits LiveTable, a live, ordered set of typed rows that the page reads and writes directly (livetable). A LiveTable change paints at once in the browser that made it while the server confirms it, and every other watching browser patches the affected row in place.

Tests Are Part of the Build and Gate Every Deploy

Laravel includes Pest and PHPUnit with a phpunit.xml already set up, and tests run when you start them, with php artisan test. Tests run one after another in a single process by default; running them in parallel takes the brianium/paratest package and the --parallel flag. Laravel Cloud's deploy runs the build and deploy commands you configure. To gate a deploy on tests, you run them in a CI pipeline that calls Cloud's deploy hook: a second system you set up.

In Elements, tests are part of the build (tests). The project server knows which tests depend on a change and runs only those, on a pool of concurrent workers, each inside a Postgres transaction that rolls back. Failures arrive in the same diagnostic stream as compile errors. A release does not happen until every test passes, on your machine and on every deploy machine.

Deploys Ship Changed Files and Release Only When Every Machine Passes

Laravel offers several ways to deploy, each a separate product. On Laravel Cloud, every deploy builds "an image configured for your application's runtime and version," runs your build and deploy commands, and then brings the new deployment online. Forge deploys to servers you rent, and its pricing page notes that it "only supports deployments with zero downtime on one server, unlike Envoyer which can deploy one project to multiple servers." Vapor, which deploys to AWS Lambda, no longer accepts new signups.

Elements has one deploy command. It runs peer to peer over SSH: your project server talks to the one on the deploy machine, the two compare their lists of files, and only changed files transfer (what deploy does). The first deploy to a new machine takes a few seconds, and later deploys often finish in under a second (deploy). Every machine compiles the release and runs the tests; migrations run once, on the first machine, against the test database first and then the app database. Only then does each machine switch to the new release, in one step. An error anywhere aborts the deploy, and the previous release keeps serving. A single machine runs its own bundled Postgres, a good fit for a prototype; for several machines, or managed backups and scaling, Elements recommends a hosted Postgres connected through DB_HOST (setup).

The rest of the server comes with Elements. Every machine runs a built-in load balancer that issues and renews Let's Encrypt certificates for every configured domain and spreads requests across the cluster (load balancer). There is no web server to configure and no provisioning service to subscribe to.

Who Pays for Laravel

Laravel is the on-ramp to Laravel Cloud and the company's other paid products. In September 2024, Laravel took venture funding, and Laravel News reported the money would go to "scaling up the team" and "building out the new Laravel Cloud" (Laravel News). The framework's own installation guide points to the product: for "extreme scaling," it says, "Platforms like Laravel Cloud allow you to run your Laravel application at nearly limitless scale" (installation).

What the company sells is a stack of separate subscriptions. Laravel Cloud is a monthly plan "plus usage": compute billed by the second while the app is awake, bandwidth past the plan's allowance billed per GB, and databases, cache, Reverb and queues on their own meters. Forge is a monthly plan on top of your server bill, and its zero-downtime deploys cover one server; its FAQ says Envoyer, another subscription, is what deploys one project to several. Nightwatch is a monthly plan that bills events past the plan's allowance. Nova is a per-project license, renewed each year for updates. Three of those four products host, deploy or monitor a Laravel app, the work the framework leaves to you.

Elements is one coherent system. The project server, the installer, the test runner, the job worker, the database, the deploy and the load balancer come in one install, built by one team to work together, under one license per machine (licenses). Nothing is metered: requests, bandwidth, build minutes and agent work never appear on an Elements bill. Your app runs on a server you rent at your provider's published price. What Elements charges for is the tooling, never the framework: the app framework and runtime packages such as @elements/app are MIT licensed, and the app you build on them is yours.

Laravel sells Nova for admin panels and Nightwatch for monitoring. In Elements, an admin screen or a metrics page is an ordinary page, which an agent builds against the same sql() and sessions as the rest of the app.

Questions

Is Elements a Laravel alternative?

Yes. Elements is an integrated app environment with a project server that runs while you work, builds in milliseconds and answers agents and humans in microseconds. It ships with a default framework that covers routing, server-rendered pages, database access, sessions, background jobs, email and realtime. The same system includes a bundled Postgres database with migrations, a test runner, and a command that deploys to your servers. Apps are written in TypeScript.

Does Elements have an ORM like Eloquent?

Elements puts SQL first. The sql() function takes plain SQL, turns every interpolated value into a parameter at compile time, and converts camelCase columns to snake_case at the database boundary. When you want rows without writing queries, LiveTable gives you select, insert, update and delete.

What replaces Laravel Forge or Laravel Cloud in Elements?

The elements deploy command, run against any Ubuntu server you rent. It deploys over SSH, sends only changed files, runs the tests on every machine and the migrations once, and releases only after every machine passes. It also runs the load balancer and issues Let's Encrypt certificates, so there is no provisioning service or deploy product to subscribe to.

Is Elements like Livewire?

No. Livewire sends each component action to the server and re-renders it there, and client-side behavior beyond its directives goes into Alpine.js. Elements uses one reactive html language that renders on the server, runs in the browser, binds form inputs both ways without a round trip, and calls typed @rpc functions from its event handlers.

Who makes Laravel?

Laravel, the company, which took venture funding in 2024 to build Laravel Cloud. The framework is free; the company sells Cloud, Forge, Nightwatch and Nova. Elements is sold directly, per machine, so its revenue comes from the tooling itself.

How does realtime in Elements compare with Laravel Reverb?

Laravel broadcasting is three parts to assemble: a queue worker, a Reverb server or a hosted service such as Pusher, and the Echo library in the browser. Elements channels and LiveTable run inside the app server on Postgres LISTEN/NOTIFY, with no separate WebSocket server or client library to install.