Livewire 3 on Vercel
How to setup and deploy a Laravel and Livewire project on Vercel
At the time I’m writing this, the launch of Laravel Cloud is just around the corner, however one of the features I love about Vercel is their password protection and preview comments. Which is really useful when you want to get some feedback from a client.
So I thought I’d write a quick guide to get a Livewire 3 project up and running on Vercel.
Let’s start by installing Laravel and Breeze, but this should work for Jetstream or any other project:
laravel new vercel-example
After that you should be able to see the website running:
cd vercel-example
php artisan serve
Now most of these steps follow this guide on how to Deploy Laravel 11 on Vercel with some slight modifications to allow Livewire to run.
First add an api/index.php
file to the root of your project with the following:
<?php
require __DIR__ . '/../public/index.php';
Then create a vercel.json
file in the root of your project:
{
"version": 2,
"outputDirectory": "public",
"functions": {
"api/*.php": {
"runtime": "vercel-php@0.7.3"
}
},
"routes": [
{
"src": "/(.*\\.(?:css|js|png|jpg|jpeg|gif|svg|ico|ttf|woff|woff2|eot|otf|webp|avif|txt))$",
"dest": "/public/$1"
},
{
"src": "/(.*)",
"dest": "/api/index.php"
}
]
}
Now, when someone tries to access the website on Vercel it’ll use the new api/index.php
file we created:
{
"src": "/(.*)",
"dest": "/api/index.php"
}
Which simply tells Vercel to run the Laravel app from public/index.php
<?php
require __DIR__ . "/../public/index.php";
And then any other assets will be served from the public folder:
{
"src": "/(.*\\.(?:css|js|png|jpg|jpeg|gif|svg|ico|ttf|woff|woff2|eot|otf|webp|avif|txt))$",
"dest": "/public/$1"
},
One problem we have is that when you load a Livewire 3 project it requests the livewire.js
file at livewire/livewire.js
which is served dynamically. To overcome this we can publish the livewire assets:
php artisan livewire:publish --assets
Now our Livewire app will request the livewire.js
file from /public/vendor/livewire/livewire.js
and our Vercel app can read it correctly.
You can also update the composer.json
file to keep these files up to date automatically:
{
"scripts": {
"post-update-cmd": [
// Other scripts
"@php artisan vendor:publish --tag=livewire:assets --ansi --force"
]
}
}
If you’re using Flux UI there’s current no way to publish the assets (yet) but we can get Vercel to handle them with PHP instead.
Let’s add that route before we handle any other css or js files:
"routes": [
{
"src": "/flux/(.*)",
"dest": "/api/index.php"
},
{
"src": "/(.*\\.(?:css|js|png|jpg|jpeg|gif|svg|ico|ttf|woff|woff2|eot|otf|webp|avif|txt))$",
"dest": "/public/$1"
},
{
"src": "/(.*)",
"dest": "/api/index.php"
}
],
If you don’t want to publish the livewire.js
files you can also just add that handler here:
{
"src": "/livewire/(.*)",
"dest": "/api/index.php"
},
Next let’s create a .vercelignore
file and add this line to ignore our composer installs:
/vendor
Then edit the .gitignore
file and ignore the vercel folder that gets generated on deploy:
.vercel
Then we need to do is set up the Trusted Proxies, so let’s edit our boostrap/app.php
file:
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up'
)
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: '*'); // add this line
})
->withExceptions(function (Exceptions $exceptions) {
//
})
->create();
The last thing we need to do is update the package.json
file to specify the node engine, otherwise Vercel has problems during the build process (at the moment) loading PHP libraries like libssl.so
, curl
or pdo_pgsql
…
"engines": {
"node": "18.x"
},
Now let’s deploy the project from our command line.
vercel
Everything should be set up correctly now so Vercel should be able to automatically deploy everything for us us.
I ran into this issue which says the filesystem is readonly, so let’s try fix that. From the vercel-php
docs I found a similar Github issue that seems to be related to Livewire. So let’s update our AppServiceProvider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
if (config('app.vercel.enabled')) {
$paths = [
'/tmp/framework/sessions',
'/tmp/framework/cache',
'/tmp/storage/bootstrap/cache',
'/tmp/storage/framework/cache',
config('view.compiled'),
];
foreach ($paths as $path) {
if (! is_dir($path)) {
mkdir($path, 0755, true);
}
}
}
}
And then let’s update our config/app.php
file to match:
/*
|--------------------------------------------------------------------------
| Ensure the livewire-tmp folder and real-time faces are being processed.
| https://github.com/vercel-community/php/issues/175
|--------------------------------------------------------------------------
*/
'vercel' => [
'enabled' => (bool) env('VERCEL', false),
],
Now that you have access to the project dashboard on settings on Vercel, you can update the envs and add the database credentials:
VERCEL=true
APP_NAME=Laravel
APP_KEY=base64:/abc/xxxxxx
APP_URL=
DB_CONNECTION=pgsql
DATABASE_URL=postgresql://postgres.(...).supabase.com:5432/postgres
DB_HOST=abc.pooler.supabase.com
DB_DATABASE=postgres
DB_USERNAME=postgres.abc
DB_PASSWORD=aaa-bbb-ccc
DB_PORT=5432
For this example I used supabase for the database connection.
Now lets deploy the project again by running vercel
in the command line and it should all be working well:
I can even register and login to the Laravel Breeze dashboard
When I use Vercel it’s mostly because of the preview comments feature, so I like to add a welcome screen on the main
branch and then run the project from a staging
branch.
So at this point I would create a staging branch and then push a welcome screen to the main branch.
And if you run into any problems, you can update the APP_DEBUG
env variable to true in the vercel.json
file so you can debug any errors.
The deployments are working successfully when you deploy manually, and should work well if you connect Vercel to Git… unless you have Flux UI installed.
Flux UI requires an auth.json
file which needs to be generated during the build step:
composer config http-basic.composer.fluxui.dev "${FLUX_USERNAME}" "${FLUX_LICENSE_KEY}"