From dcd325dc44f20806d983c92d4fa60fb28ad961d7 Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Mon, 15 Jun 2026 23:09:49 +0200
Subject: [PATCH] feat(v5): add Inertia app shell with Flux health
Adds v5 routing, middleware, home page rendering, team context sharing,
project model/table support, and Flux health reporting. Installs Flux in
container builds with role-aware s6 services and documents runtime roles.
---
README.md | 25 +
app/Http/Controllers/V5/HomeController.php | 44 +
app/Http/Kernel.php | 18 +
app/Http/Middleware/V5/EnsureCurrentTeam.php | 54 ++
.../Middleware/V5/HandleInertiaRequests.php | 25 +
app/Models/V5/Project.php | 29 +
app/Models/V5/V5Model.php | 10 +
app/Providers/RouteServiceProvider.php | 5 +
app/Services/Flux/FluxHealth.php | 66 ++
composer.json | 1 +
composer.lock | 111 ++-
config/flux.php | 6 +
..._06_04_050157_create_v5_projects_table.php | 33 +
database/schema/testing-schema.sql | 11 +
docker-compose.dev.yml | 2 +
docker-compose.prod.yml | 4 +
docker/development/Dockerfile | 27 +
.../s6-rc.d/flux/dependencies.d/init-setup | 0
.../etc/s6-overlay/s6-rc.d/flux/run | 49 ++
.../etc/s6-overlay/s6-rc.d/flux/type | 1 +
.../etc/s6-overlay/s6-rc.d/horizon/run | 14 +
.../s6-overlay/s6-rc.d/nightwatch-agent/run | 14 +
.../s6-overlay/s6-rc.d/scheduler-worker/run | 14 +
.../s6-overlay/s6-rc.d/user/contents.d/flux | 0
docker/production/Dockerfile | 27 +
.../s6-rc.d/flux/dependencies.d/init-script | 0
.../etc/s6-overlay/s6-rc.d/flux/run | 49 ++
.../etc/s6-overlay/s6-rc.d/flux/type | 1 +
.../etc/s6-overlay/s6-rc.d/horizon/run | 14 +
.../s6-overlay/s6-rc.d/nightwatch-agent/run | 14 +
.../s6-overlay/s6-rc.d/scheduler-worker/run | 14 +
.../s6-overlay/s6-rc.d/user/contents.d/flux | 0
package-lock.json | 793 ++++++++++++++++--
package.json | 7 +-
resources/css/v5/app.css | 11 +
resources/js/v5/Pages/Home.jsx | 59 ++
resources/js/v5/app.jsx | 11 +
resources/views/v5/app.blade.php | 18 +
routes/v5.php | 8 +
tests/Feature/V5/HomeTest.php | 214 +++++
vite.config.js | 10 +-
41 files changed, 1705 insertions(+), 108 deletions(-)
create mode 100644 app/Http/Controllers/V5/HomeController.php
create mode 100644 app/Http/Middleware/V5/EnsureCurrentTeam.php
create mode 100644 app/Http/Middleware/V5/HandleInertiaRequests.php
create mode 100644 app/Models/V5/Project.php
create mode 100644 app/Models/V5/V5Model.php
create mode 100644 app/Services/Flux/FluxHealth.php
create mode 100644 config/flux.php
create mode 100644 database/migrations/2026_06_04_050157_create_v5_projects_table.php
create mode 100644 docker/development/etc/s6-overlay/s6-rc.d/flux/dependencies.d/init-setup
create mode 100755 docker/development/etc/s6-overlay/s6-rc.d/flux/run
create mode 100644 docker/development/etc/s6-overlay/s6-rc.d/flux/type
create mode 100644 docker/development/etc/s6-overlay/s6-rc.d/user/contents.d/flux
create mode 100644 docker/production/etc/s6-overlay/s6-rc.d/flux/dependencies.d/init-script
create mode 100755 docker/production/etc/s6-overlay/s6-rc.d/flux/run
create mode 100644 docker/production/etc/s6-overlay/s6-rc.d/flux/type
create mode 100644 docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/flux
create mode 100644 resources/css/v5/app.css
create mode 100644 resources/js/v5/Pages/Home.jsx
create mode 100644 resources/js/v5/app.jsx
create mode 100644 resources/views/v5/app.blade.php
create mode 100644 routes/v5.php
create mode 100644 tests/Feature/V5/HomeTest.php
diff --git a/README.md b/README.md
index b387d87e8..f4e289bcd 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,31 @@ You can find the installation script source [here](./scripts/install.sh).
> [!NOTE]
> Please refer to the [docs](https://coolify.io/docs/installation) for more information about the installation.
+
+## Container roles and Flux
+
+The Coolify image can run different process roles with `COOLIFY_CONTAINER_ROLE`:
+
+- `all` (default): self-hosted mode; runs the web process, worker services, and Flux when configured.
+- `web`: web/API process only; s6 worker services and Flux sleep.
+- `worker`: Horizon, Laravel scheduler worker, and optional Nightwatch agent.
+- `flux`: Flux only; used by Cloud/HA deployments that scale coold connection routers separately.
+
+Flux is installed from the coold nightly release into `/usr/local/bin/flux`. Containers running the `all` or `flux` role expose Flux on port `6443` and use these runtime variables:
+
+```env
+COOLIFY_FLUX_GRPC_BIND=0.0.0.0:6443
+COOLIFY_FLUX_UNIX_SOCKET_PATH=/run/coolify/flux.sock
+COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH=/var/www/html/storage/app/flux/jwt.priv
+COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH=/var/www/html/storage/app/flux/jwt.pub
+COOLIFY_FLUX_ALLOW_PUBLIC_BIND=1
+COOLIFY_FLUX_ID=flux-eu-1
+COOLIFY_FLUX_PUBLIC_URL=grpcs://flux-eu-1.example.com:6443
+COOLIFY_FLUX_INTERNAL_URL=http://coolify-flux-eu-1.internal:6443
+```
+
+If `COOLIFY_FLUX_ENABLED=false` is set, the Flux s6 service sleeps even for `all` and `flux` roles. The Flux s6 service creates a persistent JWT keypair on first boot when the key files are missing. The current Coolify image only installs the nightly Flux artifact during the Docker build; the s6 service verifies the binary at runtime and sleeps with a clear error if the published artifact is not compatible with the Alpine base image.
+
## Support
Contact us at [coolify.io/docs/contact](https://coolify.io/docs/contact).
diff --git a/app/Http/Controllers/V5/HomeController.php b/app/Http/Controllers/V5/HomeController.php
new file mode 100644
index 000000000..b8f9fa6db
--- /dev/null
+++ b/app/Http/Controllers/V5/HomeController.php
@@ -0,0 +1,44 @@
+user();
+ $currentTeam = $request->attributes->get('v5.currentTeam');
+
+ return Inertia::render('Home', [
+ 'status' => 'v5-ready',
+ 'flux' => $fluxHealth->check(),
+ 'currentTeam' => $currentTeam instanceof Team ? [
+ 'id' => $currentTeam->id,
+ 'name' => $currentTeam->name,
+ 'description' => $currentTeam->description,
+ 'role' => $currentTeam->pivot?->role ?? $user->roleInTeam($currentTeam->id),
+ 'personal' => $currentTeam->personal_team,
+ ] : null,
+ 'teams' => $user->teams()
+ ->select('teams.id', 'teams.name', 'teams.description', 'teams.personal_team')
+ ->orderBy('teams.name')
+ ->get()
+ ->map(fn (Team $team) => [
+ 'id' => $team->id,
+ 'name' => $team->name,
+ 'description' => $team->description,
+ 'role' => $team->pivot->role,
+ 'personal' => $team->personal_team,
+ ]),
+ ]);
+ }
+}
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 02a49aaa8..dfd66284a 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -18,6 +18,8 @@ use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustHosts;
use App\Http\Middleware\TrustProxies;
+use App\Http\Middleware\V5\EnsureCurrentTeam as V5EnsureCurrentTeam;
+use App\Http\Middleware\V5\HandleInertiaRequests as V5HandleInertiaRequests;
use App\Http\Middleware\ValidateSignature;
use App\Http\Middleware\VerifyCsrfToken;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
@@ -76,6 +78,22 @@ class Kernel extends HttpKernel
],
+ 'v5.web' => [
+ EncryptCookies::class,
+ AddQueuedCookiesToResponse::class,
+ StartSession::class,
+ ShareErrorsFromSession::class,
+ VerifyCsrfToken::class,
+ SubstituteBindings::class,
+ V5HandleInertiaRequests::class,
+ ],
+
+ 'v5.authenticated' => [
+ 'auth',
+ 'verified',
+ V5EnsureCurrentTeam::class,
+ ],
+
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
ThrottleRequests::class.':api',
diff --git a/app/Http/Middleware/V5/EnsureCurrentTeam.php b/app/Http/Middleware/V5/EnsureCurrentTeam.php
new file mode 100644
index 000000000..f8aa78f92
--- /dev/null
+++ b/app/Http/Middleware/V5/EnsureCurrentTeam.php
@@ -0,0 +1,54 @@
+user();
+
+ if (! $user) {
+ return $next($request);
+ }
+
+ $currentTeam = $this->resolveCurrentTeam($user);
+
+ if (! $currentTeam) {
+ abort(403, 'No team available for this user.');
+ }
+
+ session(['currentTeam' => $currentTeam]);
+ $request->attributes->set('v5.currentTeam', $currentTeam);
+
+ return $next($request);
+ }
+
+ private function resolveCurrentTeam(User $user): ?Team
+ {
+ $sessionTeamId = data_get(session('currentTeam'), 'id');
+
+ if ($sessionTeamId) {
+ $sessionTeam = $user->teams()
+ ->select('teams.id', 'teams.name', 'teams.description', 'teams.personal_team')
+ ->whereKey($sessionTeamId)
+ ->first();
+
+ if ($sessionTeam) {
+ return $sessionTeam;
+ }
+ }
+
+ return $user->teams()
+ ->select('teams.id', 'teams.name', 'teams.description', 'teams.personal_team')
+ ->orderBy('teams.id')
+ ->first();
+ }
+}
diff --git a/app/Http/Middleware/V5/HandleInertiaRequests.php b/app/Http/Middleware/V5/HandleInertiaRequests.php
new file mode 100644
index 000000000..2772c9c2e
--- /dev/null
+++ b/app/Http/Middleware/V5/HandleInertiaRequests.php
@@ -0,0 +1,25 @@
+ [
+ 'user' => $request->user() ? [
+ 'id' => $request->user()->id,
+ 'name' => $request->user()->name,
+ 'email' => $request->user()->email,
+ ] : null,
+ ],
+ ];
+ }
+}
diff --git a/app/Models/V5/Project.php b/app/Models/V5/Project.php
new file mode 100644
index 000000000..a04a381f9
--- /dev/null
+++ b/app/Models/V5/Project.php
@@ -0,0 +1,29 @@
+belongsTo(Team::class);
+ }
+
+ public function creator(): BelongsTo
+ {
+ return $this->belongsTo(User::class, 'created_by_user_id');
+ }
+}
diff --git a/app/Models/V5/V5Model.php b/app/Models/V5/V5Model.php
new file mode 100644
index 000000000..9907e827d
--- /dev/null
+++ b/app/Models/V5/V5Model.php
@@ -0,0 +1,10 @@
+group(base_path('routes/webhooks.php'));
+ Route::middleware('v5.web')
+ ->prefix('v5')
+ ->as('v5.')
+ ->group(base_path('routes/v5.php'));
+
Route::middleware('web')
->group(base_path('routes/web.php'));
});
diff --git a/app/Services/Flux/FluxHealth.php b/app/Services/Flux/FluxHealth.php
new file mode 100644
index 000000000..85d49d948
--- /dev/null
+++ b/app/Services/Flux/FluxHealth.php
@@ -0,0 +1,66 @@
+unavailable(null, 'Flux socket is not configured.');
+ }
+
+ if (! file_exists($socketPath)) {
+ return $this->unavailable($socketPath, 'Flux socket was not found.');
+ }
+
+ $timeout = (float) config('flux.health_timeout_seconds', 1.0);
+ $stream = @stream_socket_client("unix://{$socketPath}", $errorCode, $errorMessage, $timeout);
+
+ if ($stream === false) {
+ return $this->unavailable($socketPath, $errorMessage ?: "Could not connect to Flux socket ({$errorCode}).");
+ }
+
+ stream_set_timeout($stream, (int) ceil($timeout));
+
+ fwrite($stream, "GET /v1/health HTTP/1.1\r\nHost: flux\r\nAccept: application/json\r\nConnection: close\r\n\r\n");
+ $response = stream_get_contents($stream) ?: '';
+ fclose($stream);
+
+ if (! str_starts_with($response, 'HTTP/1.1 200') && ! str_starts_with($response, 'HTTP/1.0 200')) {
+ return $this->unavailable($socketPath, 'Flux health endpoint did not return HTTP 200.');
+ }
+
+ $body = str_contains($response, "\r\n\r\n") ? substr($response, strpos($response, "\r\n\r\n") + 4) : '';
+ $payload = json_decode($body, true);
+
+ if (! is_array($payload) || ($payload['ok'] ?? false) !== true) {
+ return $this->unavailable($socketPath, 'Flux health endpoint returned an invalid response.');
+ }
+
+ return [
+ 'available' => true,
+ 'label' => 'Running',
+ 'message' => 'Flux is running.',
+ 'socket' => $socketPath,
+ ];
+ }
+
+ /**
+ * @return array{available: false, label: string, message: string, socket: string|null}
+ */
+ private function unavailable(?string $socketPath, string $message): array
+ {
+ return [
+ 'available' => false,
+ 'label' => 'Unavailable',
+ 'message' => $message,
+ 'socket' => $socketPath,
+ ];
+ }
+}
diff --git a/composer.json b/composer.json
index 9415aa624..1d94dca00 100644
--- a/composer.json
+++ b/composer.json
@@ -15,6 +15,7 @@
"danharrin/livewire-rate-limiting": "^2.1.0",
"doctrine/dbal": "^4.4.1",
"guzzlehttp/guzzle": "^7.10.0",
+ "inertiajs/inertia-laravel": "^3.1",
"laravel/fortify": "^1.34.0",
"laravel/framework": "^12.49.0",
"laravel/horizon": "^5.43.0",
diff --git a/composer.lock b/composer.lock
index 7d958a9cc..ded6d4b6c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "64b77285a7140ce68e83db2659e9a21d",
+ "content-hash": "d7e1f3eef5ae01d358f9482007814245",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -1643,6 +1643,79 @@
],
"time": "2025-08-22T14:27:06+00:00"
},
+ {
+ "name": "inertiajs/inertia-laravel",
+ "version": "v3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/inertiajs/inertia-laravel.git",
+ "reference": "f588ce4a5beb25d166f4e372bac0c7f46a4f52ac"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/f588ce4a5beb25d166f4e372bac0c7f46a4f52ac",
+ "reference": "f588ce4a5beb25d166f4e372bac0c7f46a4f52ac",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "laravel/framework": "^11.0|^12.0|^13.0",
+ "php": "^8.2.0",
+ "symfony/console": "^7.0|^8.0"
+ },
+ "conflict": {
+ "laravel/boost": "<2.2.0"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^7.2",
+ "larastan/larastan": "^3.0",
+ "laravel/pint": "^1.16",
+ "mockery/mockery": "^1.3.3",
+ "orchestra/testbench": "^9.2|^10.0|^11.0",
+ "phpunit/phpunit": "^11.5|^12.0",
+ "roave/security-advisories": "dev-master"
+ },
+ "suggest": {
+ "ext-pcntl": "Recommended when running the Inertia SSR server via the `inertia:start-ssr` artisan command."
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Inertia\\ServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "./helpers.php"
+ ],
+ "psr-4": {
+ "Inertia\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jonathan Reinink",
+ "email": "jonathan@reinink.ca",
+ "homepage": "https://reinink.ca"
+ }
+ ],
+ "description": "The Laravel adapter for Inertia.js.",
+ "keywords": [
+ "inertia",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/inertiajs/inertia-laravel/issues",
+ "source": "https://github.com/inertiajs/inertia-laravel/tree/v3.1.0"
+ },
+ "time": "2026-04-30T15:30:29+00:00"
+ },
{
"name": "jean85/pretty-package-versions",
"version": "2.1.1",
@@ -8973,16 +9046,16 @@
},
{
"name": "symfony/http-foundation",
- "version": "v7.4.8",
+ "version": "v7.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "9381209597ec66c25be154cbf2289076e64d1eab"
+ "reference": "bc354f47c62301e990b7874fa662326368508e2c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab",
- "reference": "9381209597ec66c25be154cbf2289076e64d1eab",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bc354f47c62301e990b7874fa662326368508e2c",
+ "reference": "bc354f47c62301e990b7874fa662326368508e2c",
"shasum": ""
},
"require": {
@@ -9031,7 +9104,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.4.8"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.4.13"
},
"funding": [
{
@@ -9051,7 +9124,7 @@
"type": "tidelift"
}
],
- "time": "2026-03-24T13:12:05+00:00"
+ "time": "2026-05-24T11:20:33+00:00"
},
{
"name": "symfony/http-kernel",
@@ -10008,16 +10081,16 @@
},
{
"name": "symfony/polyfill-php83",
- "version": "v1.37.0",
+ "version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149"
+ "reference": "8339098cae28673c15cce00d80734af0453054e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149",
- "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/8339098cae28673c15cce00d80734af0453054e2",
+ "reference": "8339098cae28673c15cce00d80734af0453054e2",
"shasum": ""
},
"require": {
@@ -10064,7 +10137,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.37.0"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.38.1"
},
"funding": [
{
@@ -10084,7 +10157,7 @@
"type": "tidelift"
}
],
- "time": "2026-04-10T17:25:58+00:00"
+ "time": "2026-05-26T12:51:13+00:00"
},
{
"name": "symfony/polyfill-php84",
@@ -10650,16 +10723,16 @@
},
{
"name": "symfony/routing",
- "version": "v7.4.12",
+ "version": "v7.4.13",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "3b04a5ec4887a8135a12ebf0f4cbc5b8fc8ee204"
+ "reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/3b04a5ec4887a8135a12ebf0f4cbc5b8fc8ee204",
- "reference": "3b04a5ec4887a8135a12ebf0f4cbc5b8fc8ee204",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/3a162171bb008e5e0f15dce6581373a4c0e8390d",
+ "reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d",
"shasum": ""
},
"require": {
@@ -10711,7 +10784,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v7.4.12"
+ "source": "https://github.com/symfony/routing/tree/v7.4.13"
},
"funding": [
{
@@ -10731,7 +10804,7 @@
"type": "tidelift"
}
],
- "time": "2026-05-20T07:20:23+00:00"
+ "time": "2026-05-24T11:20:33+00:00"
},
{
"name": "symfony/serializer",
diff --git a/config/flux.php b/config/flux.php
new file mode 100644
index 000000000..e82914de0
--- /dev/null
+++ b/config/flux.php
@@ -0,0 +1,6 @@
+ env('COOLIFY_FLUX_UNIX_SOCKET_PATH', '/run/coolify/flux.sock'),
+ 'health_timeout_seconds' => (float) env('COOLIFY_FLUX_HEALTH_TIMEOUT_SECONDS', 1.0),
+];
diff --git a/database/migrations/2026_06_04_050157_create_v5_projects_table.php b/database/migrations/2026_06_04_050157_create_v5_projects_table.php
new file mode 100644
index 000000000..8148c6cce
--- /dev/null
+++ b/database/migrations/2026_06_04_050157_create_v5_projects_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('team_id')->constrained('teams')->cascadeOnDelete();
+ $table->foreignId('created_by_user_id')->constrained('users')->cascadeOnDelete();
+ $table->string('name');
+ $table->text('description')->nullable();
+ $table->timestamps();
+
+ $table->index(['team_id', 'name']);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('v5_projects');
+ }
+};
diff --git a/database/schema/testing-schema.sql b/database/schema/testing-schema.sql
index edbc35db4..7555922ce 100644
--- a/database/schema/testing-schema.sql
+++ b/database/schema/testing-schema.sql
@@ -1321,6 +1321,16 @@ CREATE TABLE IF NOT EXISTS "users" (
"email_change_code_expires_at" TEXT
);
+CREATE TABLE IF NOT EXISTS "v5_projects" (
+ "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ "team_id" INTEGER NOT NULL,
+ "created_by_user_id" INTEGER NOT NULL,
+ "name" TEXT NOT NULL,
+ "description" TEXT,
+ "created_at" TEXT,
+ "updated_at" TEXT
+);
+
CREATE TABLE IF NOT EXISTS "webhook_notification_settings" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"team_id" INTEGER NOT NULL,
@@ -1752,3 +1762,4 @@ INSERT INTO "migrations" ("id", "migration", "batch") VALUES (311, '2025_12_10_1
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (312, '2025_12_15_143052_trim_s3_storage_credentials', 312);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (313, '2025_12_17_000001_add_is_wire_navigate_enabled_to_instance_settings_table', 313);
INSERT INTO "migrations" ("id", "migration", "batch") VALUES (314, '2025_12_17_000002_add_restart_tracking_to_standalone_databases', 314);
+INSERT INTO "migrations" ("id", "migration", "batch") VALUES (315, '2026_06_04_050157_create_v5_projects_table', 315);
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 9c93678af..bad72a22d 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -10,8 +10,10 @@ services:
- GROUP_ID=${GROUPID:-1000}
ports:
- "${APP_PORT:-8000}:8080"
+ - "${FORWARD_FLUX_PORT:-6443}:6443"
environment:
AUTORUN_ENABLED: false
+ COOLIFY_CONTAINER_ROLE: "${COOLIFY_CONTAINER_ROLE:-all}"
PUSHER_HOST: "${PUSHER_HOST}"
PUSHER_PORT: "${PUSHER_PORT}"
PUSHER_SCHEME: "${PUSHER_SCHEME:-http}"
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index 8907a30b9..fd4aabeef 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -11,6 +11,7 @@ services:
- /data/coolify/databases:/var/www/html/storage/app/databases
- /data/coolify/services:/var/www/html/storage/app/services
- /data/coolify/backups:/var/www/html/storage/app/backups
+ - /data/coolify/flux:/var/www/html/storage/app/flux
environment:
- APP_ENV=${APP_ENV:-production}
- PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-256M}
@@ -18,12 +19,15 @@ services:
- PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1}
- PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1}
- PHP_FPM_PM_MAX_SPARE_SERVERS=${PHP_FPM_PM_MAX_SPARE_SERVERS:-10}
+ - COOLIFY_CONTAINER_ROLE=${COOLIFY_CONTAINER_ROLE:-all}
env_file:
- /data/coolify/source/.env
ports:
- "${APP_PORT:-8000}:8080"
+ - "${COOLIFY_FLUX_PORT:-6443}:6443"
expose:
- "${APP_PORT:-8000}"
+ - "${COOLIFY_FLUX_PORT:-6443}"
healthcheck:
test: curl --fail http://127.0.0.1:8080/api/health || exit 1
interval: 5s
diff --git a/docker/development/Dockerfile b/docker/development/Dockerfile
index 8fc46e32d..08450e817 100644
--- a/docker/development/Dockerfile
+++ b/docker/development/Dockerfile
@@ -5,6 +5,8 @@ ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine
ARG MINIO_VERSION=RELEASE.2025-05-21T01-59-54Z
# https://github.com/cloudflare/cloudflared/releases
ARG CLOUDFLARED_VERSION=2025.7.0
+# https://github.com/coollabsio/coold/releases/tag/nightly
+ARG COOLIFY_FLUX_VERSION=nightly
# https://www.postgresql.org/support/versioning/
# Note: We are using version 18 of the postgres client (while still using postgres 15 for the postgres server) as version 15 has been removed from Alpine 3.23+ https://pkgs.alpinelinux.org/packages?name=postgresql*-client&branch=v3.23&repo=&arch=x86_64&origin=&flagged=&maintainer=
ARG POSTGRES_VERSION=18
@@ -24,8 +26,10 @@ FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION}
ARG USER_ID
ARG GROUP_ID
ARG TARGETPLATFORM
+ARG TARGETARCH
ARG POSTGRES_VERSION
ARG CLOUDFLARED_VERSION
+ARG COOLIFY_FLUX_VERSION
ARG NGINX_VERSION
WORKDIR /var/www/html
@@ -58,6 +62,7 @@ RUN apk upgrade --no-cache && \
RUN apk add --no-cache \
postgresql${POSTGRES_VERSION}-client \
openssh-client \
+ openssl \
git \
git-lfs \
jq \
@@ -81,6 +86,28 @@ RUN mkdir -p /usr/local/bin && \
fi && \
chmod +x /usr/local/bin/cloudflared
+# Install Flux from coold nightly release based on architecture
+RUN set -eux; \
+ mkdir -p /usr/local/bin /run/coolify /etc/coolify; \
+ chown -R www-data:www-data /run/coolify /etc/coolify; \
+ case "${TARGETARCH:-}" in \
+ amd64|arm64) FLUX_ARCH="${TARGETARCH}" ;; \
+ "") \
+ case "$(uname -m)" in \
+ x86_64) FLUX_ARCH="amd64" ;; \
+ aarch64) FLUX_ARCH="arm64" ;; \
+ *) echo "unsupported Flux arch: $(uname -m)" >&2; exit 1 ;; \
+ esac ;; \
+ *) echo "unsupported Flux TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
+ esac; \
+ curl -fsSL --retry 3 --max-time 120 \
+ -o /tmp/flux.tar.gz \
+ "https://github.com/coollabsio/coold/releases/download/${COOLIFY_FLUX_VERSION}/flux-linux-musl-${FLUX_ARCH}.tar.gz"; \
+ tar -xzf /tmp/flux.tar.gz -C /tmp; \
+ test -f /tmp/flux; \
+ install -m 0755 /tmp/flux /usr/local/bin/flux; \
+ rm -f /tmp/flux /tmp/flux.tar.gz
+
# Configure PHP
COPY docker/development/etc/php/conf.d/zzz-custom-php.ini /usr/local/etc/php/conf.d/zzz-custom-php.ini
ENV PHP_OPCACHE_ENABLE=0
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/flux/dependencies.d/init-setup b/docker/development/etc/s6-overlay/s6-rc.d/flux/dependencies.d/init-setup
new file mode 100644
index 000000000..e69de29bb
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/flux/run b/docker/development/etc/s6-overlay/s6-rc.d/flux/run
new file mode 100755
index 000000000..95f648f8e
--- /dev/null
+++ b/docker/development/etc/s6-overlay/s6-rc.d/flux/run
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+cd /var/www/html
+
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|flux) ;;
+ *)
+ echo " INFO Flux is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
+if grep -qE '^COOLIFY_FLUX_ENABLED=false' .env 2>/dev/null || [ "${COOLIFY_FLUX_ENABLED:-}" = "false" ]; then
+ echo " INFO Flux is disabled, sleeping."
+ exec sleep infinity
+fi
+
+export COOLIFY_FLUX_GRPC_BIND="${COOLIFY_FLUX_GRPC_BIND:-0.0.0.0:6443}"
+export COOLIFY_FLUX_UNIX_SOCKET_PATH="${COOLIFY_FLUX_UNIX_SOCKET_PATH:-/run/coolify/flux.sock}"
+export COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH="${COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH:-/var/www/html/storage/app/flux/jwt.priv}"
+export COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH="${COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH:-/var/www/html/storage/app/flux/jwt.pub}"
+export COOLIFY_FLUX_ALLOW_PUBLIC_BIND="${COOLIFY_FLUX_ALLOW_PUBLIC_BIND:-1}"
+
+if [ ! -r "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH" ]; then
+ echo " INFO Flux JWT public key not found at $COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH, generating keypair..."
+ mkdir -p "$(dirname "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH")" "$(dirname "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH")"
+ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH.tmp"
+ chmod 0600 "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH.tmp"
+ mv "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH.tmp" "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH"
+ openssl pkey -in "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH" -pubout -out "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH.tmp"
+ chmod 0644 "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH.tmp"
+ mv "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH.tmp" "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH"
+fi
+
+if ! /usr/local/bin/flux --version >/dev/null 2>&1; then
+ echo " ERROR Flux binary cannot run in this container. Check that the installed coold nightly Flux artifact is compatible with Alpine."
+ exec sleep infinity
+fi
+
+mkdir -p "$(dirname "$COOLIFY_FLUX_UNIX_SOCKET_PATH")"
+
+echo " INFO Flux is enabled for role '$role', starting..."
+exec /usr/local/bin/flux
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/flux/type b/docker/development/etc/s6-overlay/s6-rc.d/flux/type
new file mode 100644
index 000000000..1780f9f44
--- /dev/null
+++ b/docker/development/etc/s6-overlay/s6-rc.d/flux/type
@@ -0,0 +1 @@
+longrun
\ No newline at end of file
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/horizon/run b/docker/development/etc/s6-overlay/s6-rc.d/horizon/run
index dbc472d06..9a8d96d2a 100644
--- a/docker/development/etc/s6-overlay/s6-rc.d/horizon/run
+++ b/docker/development/etc/s6-overlay/s6-rc.d/horizon/run
@@ -2,6 +2,20 @@
cd /var/www/html
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|worker) ;;
+ *)
+ echo " INFO Horizon is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
if grep -qE '^HORIZON_ENABLED=false' .env 2>/dev/null; then
echo " INFO Horizon is disabled, sleeping."
exec sleep infinity
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/nightwatch-agent/run b/docker/development/etc/s6-overlay/s6-rc.d/nightwatch-agent/run
index ee46dba7e..7242b3f79 100644
--- a/docker/development/etc/s6-overlay/s6-rc.d/nightwatch-agent/run
+++ b/docker/development/etc/s6-overlay/s6-rc.d/nightwatch-agent/run
@@ -2,6 +2,20 @@
cd /var/www/html
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|worker) ;;
+ *)
+ echo " INFO Nightwatch is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
if grep -qE '^NIGHTWATCH_ENABLED=true' .env 2>/dev/null; then
echo " INFO Nightwatch is enabled, starting..."
exec php artisan nightwatch:agent
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/run b/docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/run
index bfa44c7e3..0dbc2e716 100644
--- a/docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/run
+++ b/docker/development/etc/s6-overlay/s6-rc.d/scheduler-worker/run
@@ -2,6 +2,20 @@
cd /var/www/html
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|worker) ;;
+ *)
+ echo " INFO Scheduler worker is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
if grep -qE '^SCHEDULER_ENABLED=false' .env 2>/dev/null; then
echo " INFO Scheduler is disabled, sleeping."
exec sleep infinity
diff --git a/docker/development/etc/s6-overlay/s6-rc.d/user/contents.d/flux b/docker/development/etc/s6-overlay/s6-rc.d/user/contents.d/flux
new file mode 100644
index 000000000..e69de29bb
diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile
index 0f849785e..b6dd5fac0 100644
--- a/docker/production/Dockerfile
+++ b/docker/production/Dockerfile
@@ -5,6 +5,8 @@ ARG SERVERSIDEUP_PHP_VERSION=8.4-fpm-nginx-alpine
ARG MINIO_VERSION=RELEASE.2025-05-21T01-59-54Z
# https://github.com/cloudflare/cloudflared/releases
ARG CLOUDFLARED_VERSION=2025.7.0
+# https://github.com/coollabsio/coold/releases/tag/nightly
+ARG COOLIFY_FLUX_VERSION=nightly
# https://www.postgresql.org/support/versioning/
# Note: We are using version 18 of the postgres client (while still using postgres 15 for the postgres server) as version 15 has been removed from Alpine 3.23+ https://pkgs.alpinelinux.org/packages?name=postgresql*-client&branch=v3.23&repo=&arch=x86_64&origin=&flagged=&maintainer=
ARG POSTGRES_VERSION=18
@@ -73,8 +75,10 @@ FROM serversideup/php:${SERVERSIDEUP_PHP_VERSION}
ARG USER_ID
ARG GROUP_ID
ARG TARGETPLATFORM
+ARG TARGETARCH
ARG POSTGRES_VERSION
ARG CLOUDFLARED_VERSION
+ARG COOLIFY_FLUX_VERSION
ARG NGINX_VERSION
ARG CI=true
@@ -108,6 +112,7 @@ RUN --mount=type=cache,target=/var/cache/apk \
apk add --no-cache \
postgresql${POSTGRES_VERSION}-client \
openssh-client \
+ openssl \
git \
git-lfs \
jq \
@@ -128,6 +133,28 @@ RUN mkdir -p /usr/local/bin && \
fi && \
chmod +x /usr/local/bin/cloudflared
+# Install Flux from coold nightly release based on architecture
+RUN set -eux; \
+ mkdir -p /usr/local/bin /run/coolify /etc/coolify; \
+ chown -R www-data:www-data /run/coolify /etc/coolify; \
+ case "${TARGETARCH:-}" in \
+ amd64|arm64) FLUX_ARCH="${TARGETARCH}" ;; \
+ "") \
+ case "$(uname -m)" in \
+ x86_64) FLUX_ARCH="amd64" ;; \
+ aarch64) FLUX_ARCH="arm64" ;; \
+ *) echo "unsupported Flux arch: $(uname -m)" >&2; exit 1 ;; \
+ esac ;; \
+ *) echo "unsupported Flux TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
+ esac; \
+ curl -fsSL --retry 3 --max-time 120 \
+ -o /tmp/flux.tar.gz \
+ "https://github.com/coollabsio/coold/releases/download/${COOLIFY_FLUX_VERSION}/flux-linux-musl-${FLUX_ARCH}.tar.gz"; \
+ tar -xzf /tmp/flux.tar.gz -C /tmp; \
+ test -f /tmp/flux; \
+ install -m 0755 /tmp/flux /usr/local/bin/flux; \
+ rm -f /tmp/flux /tmp/flux.tar.gz
+
# Configure PHP
COPY docker/production/etc/php/conf.d/zzz-custom-php.ini /usr/local/etc/php/conf.d/zzz-custom-php.ini
ENV PHP_OPCACHE_ENABLE=1
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/flux/dependencies.d/init-script b/docker/production/etc/s6-overlay/s6-rc.d/flux/dependencies.d/init-script
new file mode 100644
index 000000000..e69de29bb
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/flux/run b/docker/production/etc/s6-overlay/s6-rc.d/flux/run
new file mode 100755
index 000000000..95f648f8e
--- /dev/null
+++ b/docker/production/etc/s6-overlay/s6-rc.d/flux/run
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+cd /var/www/html
+
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|flux) ;;
+ *)
+ echo " INFO Flux is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
+if grep -qE '^COOLIFY_FLUX_ENABLED=false' .env 2>/dev/null || [ "${COOLIFY_FLUX_ENABLED:-}" = "false" ]; then
+ echo " INFO Flux is disabled, sleeping."
+ exec sleep infinity
+fi
+
+export COOLIFY_FLUX_GRPC_BIND="${COOLIFY_FLUX_GRPC_BIND:-0.0.0.0:6443}"
+export COOLIFY_FLUX_UNIX_SOCKET_PATH="${COOLIFY_FLUX_UNIX_SOCKET_PATH:-/run/coolify/flux.sock}"
+export COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH="${COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH:-/var/www/html/storage/app/flux/jwt.priv}"
+export COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH="${COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH:-/var/www/html/storage/app/flux/jwt.pub}"
+export COOLIFY_FLUX_ALLOW_PUBLIC_BIND="${COOLIFY_FLUX_ALLOW_PUBLIC_BIND:-1}"
+
+if [ ! -r "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH" ]; then
+ echo " INFO Flux JWT public key not found at $COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH, generating keypair..."
+ mkdir -p "$(dirname "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH")" "$(dirname "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH")"
+ openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH.tmp"
+ chmod 0600 "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH.tmp"
+ mv "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH.tmp" "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH"
+ openssl pkey -in "$COOLIFY_FLUX_JWT_PRIVATE_KEY_PATH" -pubout -out "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH.tmp"
+ chmod 0644 "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH.tmp"
+ mv "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH.tmp" "$COOLIFY_FLUX_JWT_PUBLIC_KEY_PATH"
+fi
+
+if ! /usr/local/bin/flux --version >/dev/null 2>&1; then
+ echo " ERROR Flux binary cannot run in this container. Check that the installed coold nightly Flux artifact is compatible with Alpine."
+ exec sleep infinity
+fi
+
+mkdir -p "$(dirname "$COOLIFY_FLUX_UNIX_SOCKET_PATH")"
+
+echo " INFO Flux is enabled for role '$role', starting..."
+exec /usr/local/bin/flux
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/flux/type b/docker/production/etc/s6-overlay/s6-rc.d/flux/type
new file mode 100644
index 000000000..1780f9f44
--- /dev/null
+++ b/docker/production/etc/s6-overlay/s6-rc.d/flux/type
@@ -0,0 +1 @@
+longrun
\ No newline at end of file
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/horizon/run b/docker/production/etc/s6-overlay/s6-rc.d/horizon/run
index dbc472d06..9a8d96d2a 100644
--- a/docker/production/etc/s6-overlay/s6-rc.d/horizon/run
+++ b/docker/production/etc/s6-overlay/s6-rc.d/horizon/run
@@ -2,6 +2,20 @@
cd /var/www/html
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|worker) ;;
+ *)
+ echo " INFO Horizon is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
if grep -qE '^HORIZON_ENABLED=false' .env 2>/dev/null; then
echo " INFO Horizon is disabled, sleeping."
exec sleep infinity
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/nightwatch-agent/run b/docker/production/etc/s6-overlay/s6-rc.d/nightwatch-agent/run
index ee46dba7e..7242b3f79 100644
--- a/docker/production/etc/s6-overlay/s6-rc.d/nightwatch-agent/run
+++ b/docker/production/etc/s6-overlay/s6-rc.d/nightwatch-agent/run
@@ -2,6 +2,20 @@
cd /var/www/html
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|worker) ;;
+ *)
+ echo " INFO Nightwatch is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
if grep -qE '^NIGHTWATCH_ENABLED=true' .env 2>/dev/null; then
echo " INFO Nightwatch is enabled, starting..."
exec php artisan nightwatch:agent
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/run b/docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/run
index bfa44c7e3..0dbc2e716 100644
--- a/docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/run
+++ b/docker/production/etc/s6-overlay/s6-rc.d/scheduler-worker/run
@@ -2,6 +2,20 @@
cd /var/www/html
+role="${COOLIFY_CONTAINER_ROLE:-}"
+if [ -z "$role" ]; then
+ role="$(grep -E '^COOLIFY_CONTAINER_ROLE=' .env 2>/dev/null | tail -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
+fi
+role="${role:-all}"
+
+case "$role" in
+ all|worker) ;;
+ *)
+ echo " INFO Scheduler worker is disabled for role '$role', sleeping."
+ exec sleep infinity
+ ;;
+esac
+
if grep -qE '^SCHEDULER_ENABLED=false' .env 2>/dev/null; then
echo " INFO Scheduler is disabled, sleeping."
exec sleep infinity
diff --git a/docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/flux b/docker/production/etc/s6-overlay/s6-rc.d/user/contents.d/flux
new file mode 100644
index 000000000..e69de29bb
diff --git a/package-lock.json b/package-lock.json
index 9d495c412..288474a88 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,14 +6,19 @@
"": {
"name": "coolify",
"dependencies": {
+ "@inertiajs/react": "^3.3.0",
+ "@inertiajs/vite": "^3.3.0",
"@tailwindcss/forms": "0.5.10",
"@tailwindcss/typography": "0.5.16",
"@xterm/addon-fit": "0.10.0",
"@xterm/xterm": "5.5.0",
- "playwright": "^1.58.2"
+ "playwright": "^1.58.2",
+ "react": "^19.2.7",
+ "react-dom": "^19.2.7"
},
"devDependencies": {
"@tailwindcss/postcss": "4.1.18",
+ "@vitejs/plugin-react": "^5.2.0",
"laravel-vite-plugin": "2.0.1",
"postcss": "8.5.15",
"tailwind-scrollbar": "4.0.2",
@@ -34,6 +39,289 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz",
+ "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
+ "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.7"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz",
+ "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz",
+ "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
+ "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
+ "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
@@ -41,7 +329,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -58,7 +345,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -75,7 +361,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -92,7 +377,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -109,7 +393,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -126,7 +409,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -143,7 +425,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -160,7 +441,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -177,7 +457,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -194,7 +473,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -211,7 +489,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -228,7 +505,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -245,7 +521,6 @@
"cpu": [
"mips64el"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -262,7 +537,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -279,7 +553,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -296,7 +569,6 @@
"cpu": [
"s390x"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -313,7 +585,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -330,7 +601,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -347,7 +617,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -364,7 +633,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -381,7 +649,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -398,7 +665,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -415,7 +681,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -432,7 +697,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -449,7 +713,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -466,7 +729,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -476,6 +738,53 @@
"node": ">=18"
}
},
+ "node_modules/@inertiajs/core": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-3.3.0.tgz",
+ "integrity": "sha512-6tEe5vtjwXJj68h0nkz84WkeZ8XA0phJ8ep1l/V+im62KTzlZTw9sxlmf8uNKu4seleXVw+idw48svxUCWla/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.31",
+ "es-toolkit": "^1.33.0",
+ "laravel-precognition": "^2.0.0"
+ },
+ "peerDependencies": {
+ "axios": "^1.15.2"
+ },
+ "peerDependenciesMeta": {
+ "axios": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@inertiajs/react": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-3.3.0.tgz",
+ "integrity": "sha512-8Es6i1FOyP5sHWjLlE3yFi+dOuJp3IBkl1ccoxb101Jr4/vTcNsdXvpl+U8IZmvnmyDS4dikeAa29p7xFUwgyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@inertiajs/core": "3.3.0",
+ "es-toolkit": "^1.33.0",
+ "laravel-precognition": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0"
+ }
+ },
+ "node_modules/@inertiajs/vite": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@inertiajs/vite/-/vite-3.3.0.tgz",
+ "integrity": "sha512-UWm+I5OpxGnm1LBjgaPOI6/M8gurloxXRnzeNMd2UC6f6ObQo6RZvyLMMWInwS0fBief7lfkpj5sPZy+680CRA==",
+ "license": "MIT",
+ "dependencies": {
+ "@inertiajs/core": "3.3.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "peerDependencies": {
+ "vite": "^7.0.0 || ^8.0.0"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -502,7 +811,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -512,20 +820,25 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
+ "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
@@ -533,7 +846,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -547,7 +859,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -561,7 +872,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -575,7 +885,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -589,7 +898,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -603,7 +911,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -617,7 +924,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -631,7 +937,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -645,7 +950,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -659,7 +963,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -673,7 +976,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -687,7 +989,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -701,7 +1002,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -715,7 +1015,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -729,7 +1028,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -743,7 +1041,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -757,7 +1054,6 @@
"cpu": [
"s390x"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -771,7 +1067,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -785,7 +1080,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -799,7 +1093,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -813,7 +1106,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -827,7 +1119,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -841,7 +1132,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -855,7 +1145,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -869,7 +1158,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1234,11 +1522,55 @@
"tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
}
},
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/prismjs": {
@@ -1248,6 +1580,27 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
+ "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.29.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-rc.3",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
"node_modules/@xterm/addon-fit": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
@@ -1261,7 +1614,77 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.33",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz",
+ "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001793",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
+ "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
},
"node_modules/clsx": {
"version": "2.1.1",
@@ -1273,6 +1696,13 @@
"node": ">=6"
}
},
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -1285,16 +1715,41 @@
"node": ">=4"
}
},
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "dev": true,
+ "devOptional": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
}
},
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.366",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.366.tgz",
+ "integrity": "sha512-OlRuhb688YTCzzU3gXPLn6nGyd+F+53INE1qaKKlu6kETErE8FYsyDh0XqXEU+uBRn0MpCzz2vfNwORhkap8qg==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/enhanced-resolve": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz",
@@ -1309,11 +1764,20 @@
"node": ">=10.13.0"
}
},
+ "node_modules/es-toolkit": {
+ "version": "1.47.0",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz",
+ "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
"node_modules/esbuild": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -1351,11 +1815,20 @@
"@esbuild/win32-x64": "0.27.2"
}
},
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
@@ -1373,7 +1846,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -1384,6 +1856,16 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -1395,12 +1877,62 @@
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/laravel-precognition": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/laravel-precognition/-/laravel-precognition-2.0.0.tgz",
+ "integrity": "sha512-dmA4HGc9m+TsVNsJs9/XQBI8u6j7coilN+qKkBuhuXQzH3HypwS/c5dFQ4UqUGjBbcxIM7zdk91kM/SRZwIvWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-toolkit": "^1.32.0"
+ },
+ "peerDependencies": {
+ "axios": "^1.4.0"
+ },
+ "peerDependenciesMeta": {
+ "axios": {
+ "optional": true
+ }
+ }
+ },
"node_modules/laravel-vite-plugin": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.0.1.tgz",
@@ -1425,7 +1957,7 @@
"version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
"integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
- "dev": true,
+ "devOptional": true,
"license": "MPL-2.0",
"dependencies": {
"detect-libc": "^2.0.3"
@@ -1458,7 +1990,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1479,7 +2010,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1500,7 +2030,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1521,7 +2050,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1542,7 +2070,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1563,7 +2090,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1584,7 +2110,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1605,7 +2130,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1626,7 +2150,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1647,7 +2170,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1668,7 +2190,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -1700,6 +2221,16 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"license": "MIT"
},
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -1719,11 +2250,17 @@
"mini-svg-data-uri": "cli.js"
}
},
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/nanoid": {
"version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -1738,19 +2275,28 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/node-releases": {
+ "version": "2.0.47",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz",
+ "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
- "dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -1806,7 +2352,6 @@
"version": "8.5.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -1859,21 +2404,42 @@
}
},
"node_modules/react": {
- "version": "19.2.4",
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
- "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
- "dev": true,
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz",
+ "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/react-dom": {
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz",
+ "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.7"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/rollup": {
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
"integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.8"
@@ -1914,11 +2480,26 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -1944,7 +2525,8 @@
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/tapable": {
"version": "2.3.0",
@@ -1964,7 +2546,6 @@
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
@@ -1977,6 +2558,37 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -1987,8 +2599,8 @@
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
"integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
- "dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -2081,6 +2693,13 @@
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
}
}
}
diff --git a/package.json b/package.json
index c3fb1bc5f..43c4c738a 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
},
"devDependencies": {
"@tailwindcss/postcss": "4.1.18",
+ "@vitejs/plugin-react": "^5.2.0",
"laravel-vite-plugin": "2.0.1",
"postcss": "8.5.15",
"tailwind-scrollbar": "4.0.2",
@@ -15,10 +16,14 @@
"vite": "7.3.2"
},
"dependencies": {
+ "@inertiajs/react": "^3.3.0",
+ "@inertiajs/vite": "^3.3.0",
"@tailwindcss/forms": "0.5.10",
"@tailwindcss/typography": "0.5.16",
"@xterm/addon-fit": "0.10.0",
"@xterm/xterm": "5.5.0",
- "playwright": "^1.58.2"
+ "playwright": "^1.58.2",
+ "react": "^19.2.7",
+ "react-dom": "^19.2.7"
}
}
diff --git a/resources/css/v5/app.css b/resources/css/v5/app.css
new file mode 100644
index 000000000..a363687ee
--- /dev/null
+++ b/resources/css/v5/app.css
@@ -0,0 +1,11 @@
+@font-face {
+ font-display: swap;
+ font-family: 'Geist Sans';
+ font-style: normal;
+ font-weight: 100 900;
+ src: url('../../fonts/geist-sans-variable.woff2') format('woff2');
+}
+
+body {
+ font-family: 'Geist Sans', sans-serif;
+}
diff --git a/resources/js/v5/Pages/Home.jsx b/resources/js/v5/Pages/Home.jsx
new file mode 100644
index 000000000..0fa9a231b
--- /dev/null
+++ b/resources/js/v5/Pages/Home.jsx
@@ -0,0 +1,59 @@
+import { Head } from '@inertiajs/react';
+
+export default function Home({ status, currentTeam, teams, flux }) {
+ return (
+ <>
+
+
+
+
+